1015a6ef6SSaurabh Misra /*
2015a6ef6SSaurabh Misra * CDDL HEADER START
3015a6ef6SSaurabh Misra *
4015a6ef6SSaurabh Misra * The contents of this file are subject to the terms of the
5015a6ef6SSaurabh Misra * Common Development and Distribution License (the "License").
6015a6ef6SSaurabh Misra * You may not use this file except in compliance with the License.
7015a6ef6SSaurabh Misra *
8015a6ef6SSaurabh Misra * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9015a6ef6SSaurabh Misra * or http://www.opensolaris.org/os/licensing.
10015a6ef6SSaurabh Misra * See the License for the specific language governing permissions
11015a6ef6SSaurabh Misra * and limitations under the License.
12015a6ef6SSaurabh Misra *
13015a6ef6SSaurabh Misra * When distributing Covered Code, include this CDDL HEADER in each
14015a6ef6SSaurabh Misra * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15015a6ef6SSaurabh Misra * If applicable, add the following below this CDDL HEADER, with the
16015a6ef6SSaurabh Misra * fields enclosed by brackets "[]" replaced with your own identifying
17015a6ef6SSaurabh Misra * information: Portions Copyright [yyyy] [name of copyright owner]
18015a6ef6SSaurabh Misra *
19015a6ef6SSaurabh Misra * CDDL HEADER END
20015a6ef6SSaurabh Misra */
21015a6ef6SSaurabh Misra
22015a6ef6SSaurabh Misra /*
23*5e8715b9SGary Mills * Copyright (c) 2012 Gary Mills
24*5e8715b9SGary Mills *
259d8d9e11SGarrett D'Amore * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
26015a6ef6SSaurabh Misra */
27*5e8715b9SGary Mills /*
28*5e8715b9SGary Mills * Copyright (c) 2009, Pyun YongHyeon <yongari@FreeBSD.org>
29*5e8715b9SGary Mills * All rights reserved.
30*5e8715b9SGary Mills *
31*5e8715b9SGary Mills * Redistribution and use in source and binary forms, with or without
32*5e8715b9SGary Mills * modification, are permitted provided that the following conditions
33*5e8715b9SGary Mills * are met:
34*5e8715b9SGary Mills * 1. Redistributions of source code must retain the above copyright
35*5e8715b9SGary Mills * notice unmodified, this list of conditions, and the following
36*5e8715b9SGary Mills * disclaimer.
37*5e8715b9SGary Mills * 2. Redistributions in binary form must reproduce the above copyright
38*5e8715b9SGary Mills * notice, this list of conditions and the following disclaimer in the
39*5e8715b9SGary Mills * documentation and/or other materials provided with the distribution.
40*5e8715b9SGary Mills *
41*5e8715b9SGary Mills * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
42*5e8715b9SGary Mills * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43*5e8715b9SGary Mills * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44*5e8715b9SGary Mills * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45*5e8715b9SGary Mills * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46*5e8715b9SGary Mills * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47*5e8715b9SGary Mills * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48*5e8715b9SGary Mills * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49*5e8715b9SGary Mills * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50*5e8715b9SGary Mills * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51*5e8715b9SGary Mills * SUCH DAMAGE.
52*5e8715b9SGary Mills */
53015a6ef6SSaurabh Misra
54015a6ef6SSaurabh Misra #include <sys/types.h>
55015a6ef6SSaurabh Misra #include <sys/stream.h>
56015a6ef6SSaurabh Misra #include <sys/strsun.h>
57015a6ef6SSaurabh Misra #include <sys/stat.h>
58015a6ef6SSaurabh Misra #include <sys/modctl.h>
59015a6ef6SSaurabh Misra #include <sys/kstat.h>
60015a6ef6SSaurabh Misra #include <sys/ethernet.h>
61015a6ef6SSaurabh Misra #include <sys/devops.h>
62015a6ef6SSaurabh Misra #include <sys/debug.h>
63015a6ef6SSaurabh Misra #include <sys/conf.h>
64015a6ef6SSaurabh Misra #include <sys/mii.h>
65015a6ef6SSaurabh Misra #include <sys/miiregs.h>
66015a6ef6SSaurabh Misra #include <sys/mac.h>
67015a6ef6SSaurabh Misra #include <sys/mac_provider.h>
68015a6ef6SSaurabh Misra #include <sys/mac_ether.h>
69015a6ef6SSaurabh Misra #include <sys/sysmacros.h>
70015a6ef6SSaurabh Misra #include <sys/dditypes.h>
71015a6ef6SSaurabh Misra #include <sys/ddi.h>
72015a6ef6SSaurabh Misra #include <sys/sunddi.h>
73015a6ef6SSaurabh Misra #include <sys/byteorder.h>
74015a6ef6SSaurabh Misra #include <sys/note.h>
75015a6ef6SSaurabh Misra #include <sys/vlan.h>
76015a6ef6SSaurabh Misra #include <sys/strsubr.h>
77015a6ef6SSaurabh Misra #include <sys/crc32.h>
78015a6ef6SSaurabh Misra #include <sys/sdt.h>
79015a6ef6SSaurabh Misra #include <sys/pci.h>
80015a6ef6SSaurabh Misra #include <sys/pci_cap.h>
81015a6ef6SSaurabh Misra
82015a6ef6SSaurabh Misra #include "atge.h"
83015a6ef6SSaurabh Misra #include "atge_cmn_reg.h"
84*5e8715b9SGary Mills #include "atge_l1c_reg.h"
85015a6ef6SSaurabh Misra #include "atge_l1e_reg.h"
860eb090a7SSaurabh Misra #include "atge_l1_reg.h"
87015a6ef6SSaurabh Misra
88015a6ef6SSaurabh Misra
89015a6ef6SSaurabh Misra /*
90*5e8715b9SGary Mills * Atheros/Attansic Ethernet chips are of four types - L1, L2, L1E and L1C.
91*5e8715b9SGary Mills * This driver is for L1E/L1/L1C but can be extended to support other chips.
920eb090a7SSaurabh Misra * L1E comes in 1Gigabit and Fast Ethernet flavors. L1 comes in 1Gigabit
93*5e8715b9SGary Mills * flavors only. L1C comes in both flavours.
94015a6ef6SSaurabh Misra *
95015a6ef6SSaurabh Misra * Atheros/Attansic Ethernet controllers have descriptor based TX and RX
96015a6ef6SSaurabh Misra * with an exception of L1E. L1E's RX side is not descriptor based ring.
97015a6ef6SSaurabh Misra * The L1E's RX uses pages (not to be confused with MMU pages) for
98015a6ef6SSaurabh Misra * receiving pkts. The header has four fields :
99015a6ef6SSaurabh Misra *
100015a6ef6SSaurabh Misra * uint32_t seqno; Sequence number of the frame.
101015a6ef6SSaurabh Misra * uint32_t length; Length of the frame.
102015a6ef6SSaurabh Misra * uint32_t flags; Flags
103015a6ef6SSaurabh Misra * uint32_t vtag; We don't use hardware VTAG.
104015a6ef6SSaurabh Misra *
105015a6ef6SSaurabh Misra * We use only one queue for RX (each queue can have two pages) and each
106015a6ef6SSaurabh Misra * page is L1E_RX_PAGE_SZ large in bytes. That's the reason we don't
107015a6ef6SSaurabh Misra * use zero-copy RX because we are limited to two pages and each page
108015a6ef6SSaurabh Misra * accomodates large number of pkts.
109015a6ef6SSaurabh Misra *
110015a6ef6SSaurabh Misra * The TX side on all three chips is descriptor based ring; and all the
111015a6ef6SSaurabh Misra * more reason to have one driver for these chips.
112015a6ef6SSaurabh Misra *
113015a6ef6SSaurabh Misra * We use two locks - atge_intr_lock and atge_tx_lock. Both the locks
114015a6ef6SSaurabh Misra * should be held if the operation has impact on the driver instance.
115015a6ef6SSaurabh Misra *
116015a6ef6SSaurabh Misra * All the three chips have hash-based multicast filter.
117015a6ef6SSaurabh Misra *
118015a6ef6SSaurabh Misra * We use CMB (Coalescing Message Block) for RX but not for TX as there
119015a6ef6SSaurabh Misra * are some issues with TX. RX CMB is used to get the last descriptor
120015a6ef6SSaurabh Misra * posted by the chip. Each CMB is for a RX page (one queue can have two
121015a6ef6SSaurabh Misra * pages) and are uint32_t (4 bytes) long.
122015a6ef6SSaurabh Misra *
123015a6ef6SSaurabh Misra * The descriptor table should have 32-bit physical address limit due to
124015a6ef6SSaurabh Misra * the limitation of having same high address for TX/RX/SMB/CMB. The
125015a6ef6SSaurabh Misra * TX/RX buffers can be 64-bit.
126015a6ef6SSaurabh Misra *
127015a6ef6SSaurabh Misra * Every DMA memory in atge is represented by atge_dma_t be it TX/RX Buffers
128015a6ef6SSaurabh Misra * or TX/RX descriptor table or SMB/CMB. To keep the code simple, we have
129015a6ef6SSaurabh Misra * kept sgl as 1 so that we get contingous pages from root complex.
1300eb090a7SSaurabh Misra *
1310eb090a7SSaurabh Misra * L1 chip (0x1048) uses descriptor based TX and RX ring. Most of registers are
1320eb090a7SSaurabh Misra * common with L1E chip (0x1026).
133015a6ef6SSaurabh Misra */
134015a6ef6SSaurabh Misra
135015a6ef6SSaurabh Misra /*
136015a6ef6SSaurabh Misra * Function Prototypes for debugging.
137015a6ef6SSaurabh Misra */
138015a6ef6SSaurabh Misra void atge_error(dev_info_t *, char *, ...);
139015a6ef6SSaurabh Misra void atge_debug_func(char *, ...);
140015a6ef6SSaurabh Misra
141015a6ef6SSaurabh Misra /*
142015a6ef6SSaurabh Misra * Function Prototypes for driver operations.
143015a6ef6SSaurabh Misra */
144015a6ef6SSaurabh Misra static int atge_resume(dev_info_t *);
145015a6ef6SSaurabh Misra static int atge_add_intr(atge_t *);
146015a6ef6SSaurabh Misra static int atge_alloc_dma(atge_t *);
147015a6ef6SSaurabh Misra static void atge_remove_intr(atge_t *);
148015a6ef6SSaurabh Misra static void atge_free_dma(atge_t *);
149015a6ef6SSaurabh Misra static void atge_device_reset(atge_t *);
150015a6ef6SSaurabh Misra static void atge_device_init(atge_t *);
151015a6ef6SSaurabh Misra static void atge_device_start(atge_t *);
152015a6ef6SSaurabh Misra static void atge_disable_intrs(atge_t *);
153015a6ef6SSaurabh Misra atge_dma_t *atge_alloc_a_dma_blk(atge_t *, ddi_dma_attr_t *, int, int);
154015a6ef6SSaurabh Misra void atge_free_a_dma_blk(atge_dma_t *);
155015a6ef6SSaurabh Misra static void atge_rxfilter(atge_t *);
156015a6ef6SSaurabh Misra static void atge_device_reset_l1_l1e(atge_t *);
157015a6ef6SSaurabh Misra void atge_program_ether(atge_t *atgep);
158015a6ef6SSaurabh Misra void atge_device_restart(atge_t *);
1590eb090a7SSaurabh Misra void atge_device_stop(atge_t *);
160015a6ef6SSaurabh Misra static int atge_send_a_packet(atge_t *, mblk_t *);
161015a6ef6SSaurabh Misra static uint32_t atge_ether_crc(const uint8_t *, int);
162015a6ef6SSaurabh Misra
163015a6ef6SSaurabh Misra
164015a6ef6SSaurabh Misra /*
1650eb090a7SSaurabh Misra * L1E/L2E specific functions.
166015a6ef6SSaurabh Misra */
167015a6ef6SSaurabh Misra void atge_l1e_device_reset(atge_t *);
168015a6ef6SSaurabh Misra void atge_l1e_stop_mac(atge_t *);
169015a6ef6SSaurabh Misra int atge_l1e_alloc_dma(atge_t *);
170015a6ef6SSaurabh Misra void atge_l1e_free_dma(atge_t *);
171015a6ef6SSaurabh Misra void atge_l1e_init_tx_ring(atge_t *);
172015a6ef6SSaurabh Misra void atge_l1e_init_rx_pages(atge_t *);
173015a6ef6SSaurabh Misra void atge_l1e_program_dma(atge_t *);
1740eb090a7SSaurabh Misra void atge_l1e_send_packet(atge_ring_t *);
175015a6ef6SSaurabh Misra mblk_t *atge_l1e_receive(atge_t *);
1760eb090a7SSaurabh Misra uint_t atge_l1e_interrupt(caddr_t, caddr_t);
177015a6ef6SSaurabh Misra void atge_l1e_gather_stats(atge_t *);
178015a6ef6SSaurabh Misra void atge_l1e_clear_stats(atge_t *);
179015a6ef6SSaurabh Misra
180015a6ef6SSaurabh Misra /*
1810eb090a7SSaurabh Misra * L1 specific functions.
1820eb090a7SSaurabh Misra */
1830eb090a7SSaurabh Misra int atge_l1_alloc_dma(atge_t *);
184*5e8715b9SGary Mills void atge_l1_free_dma(atge_t *);
1850eb090a7SSaurabh Misra void atge_l1_init_tx_ring(atge_t *);
1860eb090a7SSaurabh Misra void atge_l1_init_rx_ring(atge_t *);
1870eb090a7SSaurabh Misra void atge_l1_init_rr_ring(atge_t *);
1880eb090a7SSaurabh Misra void atge_l1_init_cmb(atge_t *);
1890eb090a7SSaurabh Misra void atge_l1_init_smb(atge_t *);
1900eb090a7SSaurabh Misra void atge_l1_program_dma(atge_t *);
1910eb090a7SSaurabh Misra void atge_l1_stop_tx_mac(atge_t *);
1920eb090a7SSaurabh Misra void atge_l1_stop_rx_mac(atge_t *);
1930eb090a7SSaurabh Misra uint_t atge_l1_interrupt(caddr_t, caddr_t);
1940eb090a7SSaurabh Misra void atge_l1_send_packet(atge_ring_t *);
1950eb090a7SSaurabh Misra
196*5e8715b9SGary Mills /*
197*5e8715b9SGary Mills * L1C specific functions.
198*5e8715b9SGary Mills */
199*5e8715b9SGary Mills int atge_l1c_alloc_dma(atge_t *);
200*5e8715b9SGary Mills void atge_l1c_free_dma(atge_t *);
201*5e8715b9SGary Mills void atge_l1c_init_tx_ring(atge_t *);
202*5e8715b9SGary Mills void atge_l1c_init_rx_ring(atge_t *);
203*5e8715b9SGary Mills void atge_l1c_init_rr_ring(atge_t *);
204*5e8715b9SGary Mills void atge_l1c_init_cmb(atge_t *);
205*5e8715b9SGary Mills void atge_l1c_init_smb(atge_t *);
206*5e8715b9SGary Mills void atge_l1c_program_dma(atge_t *);
207*5e8715b9SGary Mills void atge_l1c_stop_tx_mac(atge_t *);
208*5e8715b9SGary Mills void atge_l1c_stop_rx_mac(atge_t *);
209*5e8715b9SGary Mills uint_t atge_l1c_interrupt(caddr_t, caddr_t);
210*5e8715b9SGary Mills void atge_l1c_send_packet(atge_ring_t *);
211*5e8715b9SGary Mills void atge_l1c_gather_stats(atge_t *);
212*5e8715b9SGary Mills void atge_l1c_clear_stats(atge_t *);
2130eb090a7SSaurabh Misra
2140eb090a7SSaurabh Misra /*
215015a6ef6SSaurabh Misra * Function prototyps for MII operations.
216015a6ef6SSaurabh Misra */
217015a6ef6SSaurabh Misra uint16_t atge_mii_read(void *, uint8_t, uint8_t);
218015a6ef6SSaurabh Misra void atge_mii_write(void *, uint8_t, uint8_t, uint16_t);
219*5e8715b9SGary Mills uint16_t atge_l1c_mii_read(void *, uint8_t, uint8_t);
220*5e8715b9SGary Mills void atge_l1c_mii_write(void *, uint8_t, uint8_t, uint16_t);
221015a6ef6SSaurabh Misra void atge_l1e_mii_reset(void *);
2220eb090a7SSaurabh Misra void atge_l1_mii_reset(void *);
223*5e8715b9SGary Mills void atge_l1c_mii_reset(void *);
224015a6ef6SSaurabh Misra static void atge_mii_notify(void *, link_state_t);
2250eb090a7SSaurabh Misra void atge_tx_reclaim(atge_t *atgep, int cons);
226015a6ef6SSaurabh Misra
2270eb090a7SSaurabh Misra /*
2280eb090a7SSaurabh Misra * L1E/L2E chip.
2290eb090a7SSaurabh Misra */
230015a6ef6SSaurabh Misra static mii_ops_t atge_l1e_mii_ops = {
231015a6ef6SSaurabh Misra MII_OPS_VERSION,
232015a6ef6SSaurabh Misra atge_mii_read,
233015a6ef6SSaurabh Misra atge_mii_write,
234015a6ef6SSaurabh Misra atge_mii_notify,
235015a6ef6SSaurabh Misra atge_l1e_mii_reset
236015a6ef6SSaurabh Misra };
237015a6ef6SSaurabh Misra
238015a6ef6SSaurabh Misra /*
2390eb090a7SSaurabh Misra * L1 chip.
2400eb090a7SSaurabh Misra */
2410eb090a7SSaurabh Misra static mii_ops_t atge_l1_mii_ops = {
2420eb090a7SSaurabh Misra MII_OPS_VERSION,
2430eb090a7SSaurabh Misra atge_mii_read,
2440eb090a7SSaurabh Misra atge_mii_write,
2450eb090a7SSaurabh Misra atge_mii_notify,
2460eb090a7SSaurabh Misra atge_l1_mii_reset
2470eb090a7SSaurabh Misra };
2480eb090a7SSaurabh Misra
2490eb090a7SSaurabh Misra /*
250*5e8715b9SGary Mills * L1C chip.
251*5e8715b9SGary Mills */
252*5e8715b9SGary Mills static mii_ops_t atge_l1c_mii_ops = {
253*5e8715b9SGary Mills MII_OPS_VERSION,
254*5e8715b9SGary Mills atge_l1c_mii_read,
255*5e8715b9SGary Mills atge_l1c_mii_write,
256*5e8715b9SGary Mills atge_mii_notify,
257*5e8715b9SGary Mills NULL
258*5e8715b9SGary Mills };
259*5e8715b9SGary Mills
260*5e8715b9SGary Mills /*
261015a6ef6SSaurabh Misra * Function Prototypes for MAC callbacks.
262015a6ef6SSaurabh Misra */
263015a6ef6SSaurabh Misra static int atge_m_stat(void *, uint_t, uint64_t *);
264015a6ef6SSaurabh Misra static int atge_m_start(void *);
265015a6ef6SSaurabh Misra static void atge_m_stop(void *);
266015a6ef6SSaurabh Misra static int atge_m_getprop(void *, const char *, mac_prop_id_t, uint_t,
2670dc2366fSVenugopal Iyer void *);
268015a6ef6SSaurabh Misra static int atge_m_setprop(void *, const char *, mac_prop_id_t, uint_t,
269015a6ef6SSaurabh Misra const void *);
2700dc2366fSVenugopal Iyer static void atge_m_propinfo(void *, const char *, mac_prop_id_t,
2710dc2366fSVenugopal Iyer mac_prop_info_handle_t);
272015a6ef6SSaurabh Misra static int atge_m_unicst(void *, const uint8_t *);
273015a6ef6SSaurabh Misra static int atge_m_multicst(void *, boolean_t, const uint8_t *);
274015a6ef6SSaurabh Misra static int atge_m_promisc(void *, boolean_t);
275015a6ef6SSaurabh Misra static mblk_t *atge_m_tx(void *, mblk_t *);
276015a6ef6SSaurabh Misra
277015a6ef6SSaurabh Misra static mac_callbacks_t atge_m_callbacks = {
2780dc2366fSVenugopal Iyer MC_SETPROP | MC_GETPROP | MC_PROPINFO,
279015a6ef6SSaurabh Misra atge_m_stat,
280015a6ef6SSaurabh Misra atge_m_start,
281015a6ef6SSaurabh Misra atge_m_stop,
282015a6ef6SSaurabh Misra atge_m_promisc,
283015a6ef6SSaurabh Misra atge_m_multicst,
284015a6ef6SSaurabh Misra atge_m_unicst,
285015a6ef6SSaurabh Misra atge_m_tx,
2860dc2366fSVenugopal Iyer NULL, /* mc_reserved */
287015a6ef6SSaurabh Misra NULL, /* mc_ioctl */
288015a6ef6SSaurabh Misra NULL, /* mc_getcapab */
289015a6ef6SSaurabh Misra NULL, /* mc_open */
290015a6ef6SSaurabh Misra NULL, /* mc_close */
291015a6ef6SSaurabh Misra atge_m_setprop,
292015a6ef6SSaurabh Misra atge_m_getprop,
2930dc2366fSVenugopal Iyer atge_m_propinfo
294015a6ef6SSaurabh Misra };
295015a6ef6SSaurabh Misra
296015a6ef6SSaurabh Misra /*
297015a6ef6SSaurabh Misra * DMA Data access requirements.
298015a6ef6SSaurabh Misra */
299015a6ef6SSaurabh Misra static struct ddi_device_acc_attr atge_dev_attr = {
300015a6ef6SSaurabh Misra DDI_DEVICE_ATTR_V0,
301015a6ef6SSaurabh Misra DDI_STRUCTURE_LE_ACC,
302015a6ef6SSaurabh Misra DDI_STRICTORDER_ACC
303015a6ef6SSaurabh Misra };
304015a6ef6SSaurabh Misra
305015a6ef6SSaurabh Misra /*
306015a6ef6SSaurabh Misra * Buffers should be native endianness.
307015a6ef6SSaurabh Misra */
308015a6ef6SSaurabh Misra static struct ddi_device_acc_attr atge_buf_attr = {
309015a6ef6SSaurabh Misra DDI_DEVICE_ATTR_V0,
310015a6ef6SSaurabh Misra DDI_NEVERSWAP_ACC, /* native endianness */
311015a6ef6SSaurabh Misra DDI_STRICTORDER_ACC
312015a6ef6SSaurabh Misra };
313015a6ef6SSaurabh Misra
314015a6ef6SSaurabh Misra /*
3150eb090a7SSaurabh Misra * DMA device attributes. Buffer can be 64-bit.
316015a6ef6SSaurabh Misra */
317015a6ef6SSaurabh Misra static ddi_dma_attr_t atge_dma_attr_buf = {
318015a6ef6SSaurabh Misra DMA_ATTR_V0, /* dma_attr_version */
319015a6ef6SSaurabh Misra 0, /* dma_attr_addr_lo */
320015a6ef6SSaurabh Misra 0x00ffffffffffull, /* dma_attr_addr_hi */
321015a6ef6SSaurabh Misra 0x000000003fffull, /* dma_attr_count_max */
322015a6ef6SSaurabh Misra 8, /* dma_attr_align */
323015a6ef6SSaurabh Misra 0x00003ffc, /* dma_attr_burstsizes */
324015a6ef6SSaurabh Misra 1, /* dma_attr_minxfer */
325015a6ef6SSaurabh Misra 0x0000000027ffull, /* dma_attr_maxxfer */
326015a6ef6SSaurabh Misra 0x0000ffffffffull, /* dma_attr_seg */
327015a6ef6SSaurabh Misra 1, /* dma_attr_sgllen */
328015a6ef6SSaurabh Misra 1, /* dma_attr_granular */
329015a6ef6SSaurabh Misra 0 /* dma_attr_flags */
330015a6ef6SSaurabh Misra };
331015a6ef6SSaurabh Misra
332015a6ef6SSaurabh Misra /*
333015a6ef6SSaurabh Misra * Table of supported devices.
334015a6ef6SSaurabh Misra */
335015a6ef6SSaurabh Misra #define ATGE_VENDOR_ID 0x1969
336*5e8715b9SGary Mills #define ATGE_L1_STR "Attansic L1"
337*5e8715b9SGary Mills #define ATGE_L1CG_STR "Atheros AR8131 Gigabit Ethernet"
338*5e8715b9SGary Mills #define ATGE_L1CF_STR "Atheros AR8132 Fast Ethernet"
339015a6ef6SSaurabh Misra #define ATGE_L1E_STR "Atheros AR8121/8113/8114"
340*5e8715b9SGary Mills #define ATGE_AR8151V1_STR "Atheros AR8151 v1.0 Gigabit Ethernet"
341*5e8715b9SGary Mills #define ATGE_AR8151V2_STR "Atheros AR8151 v2.0 Gigabit Ethernet"
342*5e8715b9SGary Mills #define ATGE_AR8152V1_STR "Atheros AR8152 v1.1 Fast Ethernet"
343*5e8715b9SGary Mills #define ATGE_AR8152V2_STR "Atheros AR8152 v2.0 Fast Ethernet"
344015a6ef6SSaurabh Misra
345015a6ef6SSaurabh Misra static atge_cards_t atge_cards[] = {
346*5e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_AR8151V2_DEV_ID, ATGE_AR8151V2_STR,
347*5e8715b9SGary Mills ATGE_CHIP_L1C},
348*5e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_AR8151V1_DEV_ID, ATGE_AR8151V1_STR,
349*5e8715b9SGary Mills ATGE_CHIP_L1C},
350*5e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_AR8152V2_DEV_ID, ATGE_AR8152V2_STR,
351*5e8715b9SGary Mills ATGE_CHIP_L1C},
352*5e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_AR8152V1_DEV_ID, ATGE_AR8152V1_STR,
353*5e8715b9SGary Mills ATGE_CHIP_L1C},
354*5e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_L1CG_DEV_ID, ATGE_L1CG_STR, ATGE_CHIP_L1C},
355*5e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_L1CF_DEV_ID, ATGE_L1CF_STR, ATGE_CHIP_L1C},
356015a6ef6SSaurabh Misra {ATGE_VENDOR_ID, ATGE_CHIP_L1E_DEV_ID, ATGE_L1E_STR, ATGE_CHIP_L1E},
357*5e8715b9SGary Mills {ATGE_VENDOR_ID, ATGE_CHIP_L1_DEV_ID, ATGE_L1_STR, ATGE_CHIP_L1},
358015a6ef6SSaurabh Misra };
359015a6ef6SSaurabh Misra
360015a6ef6SSaurabh Misra /*
361015a6ef6SSaurabh Misra * Global Debugging flag. Developer level debugging is done only in DEBUG mode.
362015a6ef6SSaurabh Misra */
363015a6ef6SSaurabh Misra int atge_debug = 1;
364015a6ef6SSaurabh Misra
365015a6ef6SSaurabh Misra /*
366015a6ef6SSaurabh Misra * Debugging and error reporting.
367015a6ef6SSaurabh Misra */
368015a6ef6SSaurabh Misra void
atge_debug_func(char * fmt,...)369015a6ef6SSaurabh Misra atge_debug_func(char *fmt, ...)
370015a6ef6SSaurabh Misra {
371015a6ef6SSaurabh Misra va_list ap;
372015a6ef6SSaurabh Misra char buf[256];
373015a6ef6SSaurabh Misra
374015a6ef6SSaurabh Misra va_start(ap, fmt);
375015a6ef6SSaurabh Misra (void) vsnprintf(buf, sizeof (buf), fmt, ap);
376015a6ef6SSaurabh Misra va_end(ap);
377015a6ef6SSaurabh Misra
378015a6ef6SSaurabh Misra DTRACE_PROBE1(atge__debug, char *, buf);
379015a6ef6SSaurabh Misra }
380015a6ef6SSaurabh Misra
381*5e8715b9SGary Mills static
382*5e8715b9SGary Mills void
atge_message(dev_info_t * dip,int level,char * fmt,va_list ap)383*5e8715b9SGary Mills atge_message(dev_info_t *dip, int level, char *fmt, va_list ap)
384*5e8715b9SGary Mills {
385*5e8715b9SGary Mills char buf[256];
386*5e8715b9SGary Mills char *p = "!%s%d: %s";
387*5e8715b9SGary Mills char *q = "!atge: %s";
388*5e8715b9SGary Mills
389*5e8715b9SGary Mills (void) vsnprintf(buf, sizeof (buf), fmt, ap);
390*5e8715b9SGary Mills
391*5e8715b9SGary Mills if (level != CE_NOTE) {
392*5e8715b9SGary Mills p++;
393*5e8715b9SGary Mills q++;
394*5e8715b9SGary Mills }
395*5e8715b9SGary Mills
396*5e8715b9SGary Mills if (dip) {
397*5e8715b9SGary Mills cmn_err(level, p,
398*5e8715b9SGary Mills ddi_driver_name(dip), ddi_get_instance(dip), buf);
399*5e8715b9SGary Mills } else {
400*5e8715b9SGary Mills cmn_err(level, q, buf);
401*5e8715b9SGary Mills }
402*5e8715b9SGary Mills }
403*5e8715b9SGary Mills
404*5e8715b9SGary Mills void
atge_notice(dev_info_t * dip,char * fmt,...)405*5e8715b9SGary Mills atge_notice(dev_info_t *dip, char *fmt, ...)
406*5e8715b9SGary Mills {
407*5e8715b9SGary Mills va_list ap;
408*5e8715b9SGary Mills
409*5e8715b9SGary Mills va_start(ap, fmt);
410*5e8715b9SGary Mills (void) atge_message(dip, CE_NOTE, fmt, ap);
411*5e8715b9SGary Mills va_end(ap);
412*5e8715b9SGary Mills }
413*5e8715b9SGary Mills
414015a6ef6SSaurabh Misra void
atge_error(dev_info_t * dip,char * fmt,...)415015a6ef6SSaurabh Misra atge_error(dev_info_t *dip, char *fmt, ...)
416015a6ef6SSaurabh Misra {
417015a6ef6SSaurabh Misra va_list ap;
418015a6ef6SSaurabh Misra
419015a6ef6SSaurabh Misra va_start(ap, fmt);
420*5e8715b9SGary Mills (void) atge_message(dip, CE_WARN, fmt, ap);
421015a6ef6SSaurabh Misra va_end(ap);
422015a6ef6SSaurabh Misra }
423015a6ef6SSaurabh Misra
424015a6ef6SSaurabh Misra void
atge_mac_config(atge_t * atgep)425015a6ef6SSaurabh Misra atge_mac_config(atge_t *atgep)
426015a6ef6SSaurabh Misra {
427015a6ef6SSaurabh Misra uint32_t reg;
428015a6ef6SSaurabh Misra int speed;
429015a6ef6SSaurabh Misra link_duplex_t ld;
430015a6ef6SSaurabh Misra
431*5e8715b9SGary Mills /* Re-enable TX/RX MACs */
432015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_MAC_CFG);
433015a6ef6SSaurabh Misra reg &= ~(ATGE_CFG_FULL_DUPLEX | ATGE_CFG_TX_FC | ATGE_CFG_RX_FC |
434015a6ef6SSaurabh Misra ATGE_CFG_SPEED_MASK);
435015a6ef6SSaurabh Misra
436*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
437*5e8715b9SGary Mills case ATGE_CHIP_L1C:
438*5e8715b9SGary Mills switch (ATGE_DID(atgep)) {
439*5e8715b9SGary Mills case ATGE_CHIP_AR8151V2_DEV_ID:
440*5e8715b9SGary Mills case ATGE_CHIP_AR8151V1_DEV_ID:
441*5e8715b9SGary Mills case ATGE_CHIP_AR8152V2_DEV_ID:
442*5e8715b9SGary Mills reg |= ATGE_CFG_HASH_ALG_CRC32 | ATGE_CFG_SPEED_MODE_SW;
443*5e8715b9SGary Mills break;
444*5e8715b9SGary Mills }
445*5e8715b9SGary Mills break;
446*5e8715b9SGary Mills }
447*5e8715b9SGary Mills
448015a6ef6SSaurabh Misra speed = mii_get_speed(atgep->atge_mii);
449015a6ef6SSaurabh Misra switch (speed) {
450015a6ef6SSaurabh Misra case 10:
451015a6ef6SSaurabh Misra case 100:
452015a6ef6SSaurabh Misra reg |= ATGE_CFG_SPEED_10_100;
453015a6ef6SSaurabh Misra break;
454015a6ef6SSaurabh Misra case 1000:
455015a6ef6SSaurabh Misra reg |= ATGE_CFG_SPEED_1000;
456015a6ef6SSaurabh Misra break;
457015a6ef6SSaurabh Misra }
458015a6ef6SSaurabh Misra
459015a6ef6SSaurabh Misra ld = mii_get_duplex(atgep->atge_mii);
460015a6ef6SSaurabh Misra if (ld == LINK_DUPLEX_FULL)
461015a6ef6SSaurabh Misra reg |= ATGE_CFG_FULL_DUPLEX;
462015a6ef6SSaurabh Misra
463015a6ef6SSaurabh Misra /* Re-enable TX/RX MACs */
464*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
465*5e8715b9SGary Mills case ATGE_CHIP_L1E:
466015a6ef6SSaurabh Misra reg |= ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB | ATGE_CFG_RX_FC;
467*5e8715b9SGary Mills break;
468*5e8715b9SGary Mills case ATGE_CHIP_L1:
469*5e8715b9SGary Mills case ATGE_CHIP_L1C:
4700eb090a7SSaurabh Misra reg |= ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB;
471*5e8715b9SGary Mills break;
4720eb090a7SSaurabh Misra }
4730eb090a7SSaurabh Misra
474015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MAC_CFG, reg);
475015a6ef6SSaurabh Misra
476*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
477*5e8715b9SGary Mills case ATGE_CHIP_L1E:
478015a6ef6SSaurabh Misra reg = ATGE_USECS(ATGE_IM_RX_TIMER_DEFAULT) << IM_TIMER_RX_SHIFT;
479015a6ef6SSaurabh Misra reg |= ATGE_USECS(ATGE_IM_TX_TIMER_DEFAULT) <<
480015a6ef6SSaurabh Misra IM_TIMER_TX_SHIFT;
481015a6ef6SSaurabh Misra OUTL(atgep, ATGE_IM_TIMER, reg);
482*5e8715b9SGary Mills break;
483*5e8715b9SGary Mills case ATGE_CHIP_L1:
484*5e8715b9SGary Mills break;
485*5e8715b9SGary Mills case ATGE_CHIP_L1C:
486*5e8715b9SGary Mills /* Configure interrupt moderation timer. */
487*5e8715b9SGary Mills reg = ATGE_USECS(atgep->atge_int_rx_mod) << IM_TIMER_RX_SHIFT;
488*5e8715b9SGary Mills reg |= ATGE_USECS(atgep->atge_int_tx_mod) << IM_TIMER_TX_SHIFT;
489*5e8715b9SGary Mills OUTL(atgep, ATGE_IM_TIMER, reg);
490*5e8715b9SGary Mills /*
491*5e8715b9SGary Mills * We don't want to automatic interrupt clear as task queue
492*5e8715b9SGary Mills * for the interrupt should know interrupt status.
493*5e8715b9SGary Mills */
494*5e8715b9SGary Mills reg = 0;
495*5e8715b9SGary Mills if (ATGE_USECS(atgep->atge_int_rx_mod) != 0)
496*5e8715b9SGary Mills reg |= MASTER_IM_RX_TIMER_ENB;
497*5e8715b9SGary Mills if (ATGE_USECS(atgep->atge_int_tx_mod) != 0)
498*5e8715b9SGary Mills reg |= MASTER_IM_TX_TIMER_ENB;
499*5e8715b9SGary Mills OUTL(atgep, ATGE_MASTER_CFG, reg);
500*5e8715b9SGary Mills break;
501015a6ef6SSaurabh Misra }
502015a6ef6SSaurabh Misra
503015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() mac_cfg is : %x",
504015a6ef6SSaurabh Misra atgep->atge_name, __func__, INL(atgep, ATGE_MAC_CFG)));
505015a6ef6SSaurabh Misra }
506015a6ef6SSaurabh Misra
507015a6ef6SSaurabh Misra static void
atge_mii_notify(void * arg,link_state_t link)508015a6ef6SSaurabh Misra atge_mii_notify(void *arg, link_state_t link)
509015a6ef6SSaurabh Misra {
510015a6ef6SSaurabh Misra atge_t *atgep = arg;
511015a6ef6SSaurabh Misra
512015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() LINK STATUS CHANGED from %x -> %x",
513015a6ef6SSaurabh Misra atgep->atge_name, __func__, atgep->atge_link_state, link));
514015a6ef6SSaurabh Misra
515015a6ef6SSaurabh Misra mac_link_update(atgep->atge_mh, link);
516015a6ef6SSaurabh Misra
517015a6ef6SSaurabh Misra /*
518015a6ef6SSaurabh Misra * Reconfigure MAC if link status is UP now.
519015a6ef6SSaurabh Misra */
520015a6ef6SSaurabh Misra mutex_enter(&atgep->atge_tx_lock);
521015a6ef6SSaurabh Misra if (link == LINK_STATE_UP) {
522015a6ef6SSaurabh Misra atgep->atge_link_state = LINK_STATE_UP;
5230eb090a7SSaurabh Misra atge_mac_config(atgep);
524015a6ef6SSaurabh Misra atgep->atge_tx_resched = 0;
525015a6ef6SSaurabh Misra } else {
526015a6ef6SSaurabh Misra atgep->atge_link_state = LINK_STATE_DOWN;
5270eb090a7SSaurabh Misra atgep->atge_flags |= ATGE_MII_CHECK;
528015a6ef6SSaurabh Misra }
529015a6ef6SSaurabh Misra
530015a6ef6SSaurabh Misra mutex_exit(&atgep->atge_tx_lock);
531015a6ef6SSaurabh Misra
532015a6ef6SSaurabh Misra if (link == LINK_STATE_UP)
533015a6ef6SSaurabh Misra mac_tx_update(atgep->atge_mh);
534015a6ef6SSaurabh Misra }
535015a6ef6SSaurabh Misra
5360eb090a7SSaurabh Misra void
atge_tx_reclaim(atge_t * atgep,int end)5370eb090a7SSaurabh Misra atge_tx_reclaim(atge_t *atgep, int end)
538015a6ef6SSaurabh Misra {
5390eb090a7SSaurabh Misra atge_tx_desc_t *txd;
5400eb090a7SSaurabh Misra atge_ring_t *r = atgep->atge_tx_ring;
5410eb090a7SSaurabh Misra uchar_t *c;
5420eb090a7SSaurabh Misra int start;
543015a6ef6SSaurabh Misra
5440eb090a7SSaurabh Misra ASSERT(MUTEX_HELD(&atgep->atge_tx_lock));
5450eb090a7SSaurabh Misra ASSERT(r != NULL);
546015a6ef6SSaurabh Misra
5470eb090a7SSaurabh Misra start = r->r_consumer;
548015a6ef6SSaurabh Misra
5490eb090a7SSaurabh Misra if (start == end)
5500eb090a7SSaurabh Misra return;
551015a6ef6SSaurabh Misra
5520eb090a7SSaurabh Misra while (start != end) {
5530eb090a7SSaurabh Misra r->r_avail_desc++;
5540eb090a7SSaurabh Misra if (r->r_avail_desc > ATGE_TX_RING_CNT) {
555015a6ef6SSaurabh Misra
556015a6ef6SSaurabh Misra atge_error(atgep->atge_dip,
5570eb090a7SSaurabh Misra "Reclaim : TX descriptor error");
558015a6ef6SSaurabh Misra
5590eb090a7SSaurabh Misra if (r->r_avail_desc > (ATGE_TX_RING_CNT + 5)) {
560015a6ef6SSaurabh Misra atge_device_stop(atgep);
5610eb090a7SSaurabh Misra break;
562015a6ef6SSaurabh Misra }
563015a6ef6SSaurabh Misra }
564015a6ef6SSaurabh Misra
5650eb090a7SSaurabh Misra c = (uchar_t *)r->r_desc_ring->addr;
5660eb090a7SSaurabh Misra c += (sizeof (atge_tx_desc_t) * start);
5670eb090a7SSaurabh Misra txd = (atge_tx_desc_t *)c;
568015a6ef6SSaurabh Misra
569015a6ef6SSaurabh Misra /*
5700eb090a7SSaurabh Misra * Clearing TX descriptor helps in debugging some strange
5710eb090a7SSaurabh Misra * problems.
572015a6ef6SSaurabh Misra */
5730eb090a7SSaurabh Misra txd->addr = 0;
5740eb090a7SSaurabh Misra txd->len = 0;
5750eb090a7SSaurabh Misra txd->flags = 0;
576015a6ef6SSaurabh Misra
5770eb090a7SSaurabh Misra ATGE_INC_SLOT(start, ATGE_TX_RING_CNT);
578015a6ef6SSaurabh Misra }
579015a6ef6SSaurabh Misra
5800eb090a7SSaurabh Misra atgep->atge_tx_ring->r_consumer = start;
581015a6ef6SSaurabh Misra
5820eb090a7SSaurabh Misra DMA_SYNC(r->r_desc_ring, 0, ATGE_TX_RING_SZ, DDI_DMA_SYNC_FORDEV);
583015a6ef6SSaurabh Misra }
584015a6ef6SSaurabh Misra
585015a6ef6SSaurabh Misra /*
586015a6ef6SSaurabh Misra * Adds interrupt handler depending upon the type of interrupt supported by
587015a6ef6SSaurabh Misra * the chip.
588015a6ef6SSaurabh Misra */
589015a6ef6SSaurabh Misra static int
atge_add_intr_handler(atge_t * atgep,int intr_type)590015a6ef6SSaurabh Misra atge_add_intr_handler(atge_t *atgep, int intr_type)
591015a6ef6SSaurabh Misra {
592015a6ef6SSaurabh Misra int err;
593015a6ef6SSaurabh Misra int count = 0;
594015a6ef6SSaurabh Misra int avail = 0;
595015a6ef6SSaurabh Misra int i;
596015a6ef6SSaurabh Misra int flag;
597015a6ef6SSaurabh Misra
598015a6ef6SSaurabh Misra if (intr_type != DDI_INTR_TYPE_FIXED) {
599015a6ef6SSaurabh Misra err = ddi_intr_get_nintrs(atgep->atge_dip, intr_type, &count);
600015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
601015a6ef6SSaurabh Misra atge_error(atgep->atge_dip,
602015a6ef6SSaurabh Misra "ddi_intr_get_nintrs failed : %d", err);
6030eb090a7SSaurabh Misra return (DDI_FAILURE);
604015a6ef6SSaurabh Misra }
605015a6ef6SSaurabh Misra
606015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() count : %d",
607015a6ef6SSaurabh Misra atgep->atge_name, __func__, count));
608015a6ef6SSaurabh Misra
609015a6ef6SSaurabh Misra err = ddi_intr_get_navail(atgep->atge_dip, intr_type, &avail);
610015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
611015a6ef6SSaurabh Misra atge_error(atgep->atge_dip,
612015a6ef6SSaurabh Misra "ddi_intr_get_navail failed : %d", err);
6130eb090a7SSaurabh Misra return (DDI_FAILURE);
614015a6ef6SSaurabh Misra }
615015a6ef6SSaurabh Misra
616015a6ef6SSaurabh Misra if (avail < count) {
617015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "count :%d,"
618015a6ef6SSaurabh Misra " avail : %d", count, avail);
619015a6ef6SSaurabh Misra }
620015a6ef6SSaurabh Misra
621015a6ef6SSaurabh Misra flag = DDI_INTR_ALLOC_STRICT;
622015a6ef6SSaurabh Misra } else {
623015a6ef6SSaurabh Misra /*
624015a6ef6SSaurabh Misra * DDI_INTR_TYPE_FIXED case.
625015a6ef6SSaurabh Misra */
626015a6ef6SSaurabh Misra count = 1;
627015a6ef6SSaurabh Misra avail = 1;
628015a6ef6SSaurabh Misra flag = DDI_INTR_ALLOC_NORMAL;
629015a6ef6SSaurabh Misra }
630015a6ef6SSaurabh Misra
631015a6ef6SSaurabh Misra atgep->atge_intr_size = avail * sizeof (ddi_intr_handle_t);
632015a6ef6SSaurabh Misra atgep->atge_intr_handle = kmem_zalloc(atgep->atge_intr_size, KM_SLEEP);
633015a6ef6SSaurabh Misra
634015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() avail:%d, count : %d, type : %d",
635015a6ef6SSaurabh Misra atgep->atge_name, __func__, avail, count,
636015a6ef6SSaurabh Misra intr_type));
637015a6ef6SSaurabh Misra
638015a6ef6SSaurabh Misra err = ddi_intr_alloc(atgep->atge_dip, atgep->atge_intr_handle,
639015a6ef6SSaurabh Misra intr_type, 0, avail, &atgep->atge_intr_cnt, flag);
640015a6ef6SSaurabh Misra
641015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
642015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "ddi_intr_alloc failed : %d", err);
643015a6ef6SSaurabh Misra kmem_free(atgep->atge_intr_handle, atgep->atge_intr_size);
6440eb090a7SSaurabh Misra return (DDI_FAILURE);
645015a6ef6SSaurabh Misra }
646015a6ef6SSaurabh Misra
647015a6ef6SSaurabh Misra ATGE_DB(("%s: atge_add_intr_handler() after alloc count"
648015a6ef6SSaurabh Misra " :%d, avail : %d", atgep->atge_name, count, avail));
649015a6ef6SSaurabh Misra
650015a6ef6SSaurabh Misra err = ddi_intr_get_pri(atgep->atge_intr_handle[0],
651015a6ef6SSaurabh Misra &atgep->atge_intr_pri);
652015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
653015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "ddi_intr_get_pri failed:%d", err);
654015a6ef6SSaurabh Misra for (i = 0; i < atgep->atge_intr_cnt; i++) {
655015a6ef6SSaurabh Misra (void) ddi_intr_free(atgep->atge_intr_handle[i]);
656015a6ef6SSaurabh Misra }
657015a6ef6SSaurabh Misra kmem_free(atgep->atge_intr_handle, atgep->atge_intr_size);
658015a6ef6SSaurabh Misra
6590eb090a7SSaurabh Misra return (DDI_FAILURE);
660015a6ef6SSaurabh Misra }
661015a6ef6SSaurabh Misra
662015a6ef6SSaurabh Misra /*
663015a6ef6SSaurabh Misra * Add interrupt handler now.
664015a6ef6SSaurabh Misra */
665015a6ef6SSaurabh Misra for (i = 0; i < atgep->atge_intr_cnt; i++) {
666*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
667*5e8715b9SGary Mills case ATGE_CHIP_L1E:
668015a6ef6SSaurabh Misra err = ddi_intr_add_handler(atgep->atge_intr_handle[i],
669015a6ef6SSaurabh Misra atge_l1e_interrupt, atgep, (caddr_t)(uintptr_t)i);
670*5e8715b9SGary Mills break;
671*5e8715b9SGary Mills case ATGE_CHIP_L1:
6720eb090a7SSaurabh Misra err = ddi_intr_add_handler(atgep->atge_intr_handle[i],
6730eb090a7SSaurabh Misra atge_l1_interrupt, atgep, (caddr_t)(uintptr_t)i);
674*5e8715b9SGary Mills break;
675*5e8715b9SGary Mills case ATGE_CHIP_L1C:
676*5e8715b9SGary Mills err = ddi_intr_add_handler(atgep->atge_intr_handle[i],
677*5e8715b9SGary Mills atge_l1c_interrupt, atgep, (caddr_t)(uintptr_t)i);
678*5e8715b9SGary Mills break;
6790eb090a7SSaurabh Misra }
680015a6ef6SSaurabh Misra
681015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
682015a6ef6SSaurabh Misra atge_error(atgep->atge_dip,
683015a6ef6SSaurabh Misra "ddi_intr_add_handler failed : %d", err);
684015a6ef6SSaurabh Misra
685015a6ef6SSaurabh Misra (void) ddi_intr_free(atgep->atge_intr_handle[i]);
686015a6ef6SSaurabh Misra while (--i >= 0) {
687015a6ef6SSaurabh Misra (void) ddi_intr_remove_handler(
688015a6ef6SSaurabh Misra atgep->atge_intr_handle[i]);
689015a6ef6SSaurabh Misra (void) ddi_intr_free(
690015a6ef6SSaurabh Misra atgep->atge_intr_handle[i]);
691015a6ef6SSaurabh Misra }
692015a6ef6SSaurabh Misra
693015a6ef6SSaurabh Misra kmem_free(atgep->atge_intr_handle,
694015a6ef6SSaurabh Misra atgep->atge_intr_size);
695015a6ef6SSaurabh Misra
6960eb090a7SSaurabh Misra return (DDI_FAILURE);
697015a6ef6SSaurabh Misra }
698015a6ef6SSaurabh Misra }
699015a6ef6SSaurabh Misra
700015a6ef6SSaurabh Misra err = ddi_intr_get_cap(atgep->atge_intr_handle[0],
701015a6ef6SSaurabh Misra &atgep->atge_intr_cap);
702015a6ef6SSaurabh Misra
703015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
704015a6ef6SSaurabh Misra atge_error(atgep->atge_dip,
705015a6ef6SSaurabh Misra "ddi_intr_get_cap failed : %d", err);
706015a6ef6SSaurabh Misra atge_remove_intr(atgep);
7070eb090a7SSaurabh Misra return (DDI_FAILURE);
708015a6ef6SSaurabh Misra }
709015a6ef6SSaurabh Misra
710015a6ef6SSaurabh Misra if (intr_type == DDI_INTR_TYPE_FIXED)
711015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_FIXED_TYPE;
712015a6ef6SSaurabh Misra else if (intr_type == DDI_INTR_TYPE_MSI)
713015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_MSI_TYPE;
714015a6ef6SSaurabh Misra else if (intr_type == DDI_INTR_TYPE_MSIX)
715015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_MSIX_TYPE;
716015a6ef6SSaurabh Misra
7170eb090a7SSaurabh Misra return (DDI_SUCCESS);
718015a6ef6SSaurabh Misra }
719015a6ef6SSaurabh Misra
720015a6ef6SSaurabh Misra void
atge_remove_intr(atge_t * atgep)721015a6ef6SSaurabh Misra atge_remove_intr(atge_t *atgep)
722015a6ef6SSaurabh Misra {
723015a6ef6SSaurabh Misra int i;
724015a6ef6SSaurabh Misra int cap = 0;
725015a6ef6SSaurabh Misra
726015a6ef6SSaurabh Misra if (atgep->atge_intr_handle == NULL)
727015a6ef6SSaurabh Misra return;
728015a6ef6SSaurabh Misra
729015a6ef6SSaurabh Misra if (atgep->atge_intr_cap & DDI_INTR_FLAG_BLOCK) {
730015a6ef6SSaurabh Misra (void) ddi_intr_block_disable(atgep->atge_intr_handle,
731015a6ef6SSaurabh Misra atgep->atge_intr_cnt);
732015a6ef6SSaurabh Misra
733015a6ef6SSaurabh Misra cap = 1;
734015a6ef6SSaurabh Misra }
735015a6ef6SSaurabh Misra
736015a6ef6SSaurabh Misra for (i = 0; i < atgep->atge_intr_cnt; i++) {
737015a6ef6SSaurabh Misra if (cap == 0)
738015a6ef6SSaurabh Misra (void) ddi_intr_disable(atgep->atge_intr_handle[i]);
739015a6ef6SSaurabh Misra
740015a6ef6SSaurabh Misra (void) ddi_intr_remove_handler(atgep->atge_intr_handle[i]);
741015a6ef6SSaurabh Misra (void) ddi_intr_free(atgep->atge_intr_handle[i]);
742015a6ef6SSaurabh Misra }
743015a6ef6SSaurabh Misra
744015a6ef6SSaurabh Misra kmem_free(atgep->atge_intr_handle, atgep->atge_intr_size);
745015a6ef6SSaurabh Misra }
746015a6ef6SSaurabh Misra
747015a6ef6SSaurabh Misra int
atge_enable_intrs(atge_t * atgep)748015a6ef6SSaurabh Misra atge_enable_intrs(atge_t *atgep)
749015a6ef6SSaurabh Misra {
750015a6ef6SSaurabh Misra int err;
751015a6ef6SSaurabh Misra int i;
752015a6ef6SSaurabh Misra
753015a6ef6SSaurabh Misra if (atgep->atge_intr_cap & DDI_INTR_FLAG_BLOCK) {
754015a6ef6SSaurabh Misra /*
755015a6ef6SSaurabh Misra * Do block enable.
756015a6ef6SSaurabh Misra */
757015a6ef6SSaurabh Misra err = ddi_intr_block_enable(atgep->atge_intr_handle,
758015a6ef6SSaurabh Misra atgep->atge_intr_cnt);
759015a6ef6SSaurabh Misra
760015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
761015a6ef6SSaurabh Misra atge_error(atgep->atge_dip,
762015a6ef6SSaurabh Misra "Failed to block enable intrs %d", err);
7630eb090a7SSaurabh Misra err = DDI_FAILURE;
764015a6ef6SSaurabh Misra } else {
7650eb090a7SSaurabh Misra err = DDI_SUCCESS;
766015a6ef6SSaurabh Misra }
767015a6ef6SSaurabh Misra } else {
768015a6ef6SSaurabh Misra /*
769015a6ef6SSaurabh Misra * Call ddi_intr_enable() for MSI non-block enable.
770015a6ef6SSaurabh Misra */
771015a6ef6SSaurabh Misra for (i = 0; i < atgep->atge_intr_cnt; i++) {
772015a6ef6SSaurabh Misra err = ddi_intr_enable(atgep->atge_intr_handle[i]);
773015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
774015a6ef6SSaurabh Misra atge_error(atgep->atge_dip,
775015a6ef6SSaurabh Misra "Failed to enable intrs on %d with : %d",
776015a6ef6SSaurabh Misra i, err);
777015a6ef6SSaurabh Misra break;
778015a6ef6SSaurabh Misra }
779015a6ef6SSaurabh Misra }
780015a6ef6SSaurabh Misra
781015a6ef6SSaurabh Misra if (err == DDI_SUCCESS)
7820eb090a7SSaurabh Misra err = DDI_SUCCESS;
783015a6ef6SSaurabh Misra else
7840eb090a7SSaurabh Misra err = DDI_FAILURE;
785015a6ef6SSaurabh Misra }
786015a6ef6SSaurabh Misra
787015a6ef6SSaurabh Misra return (err);
788015a6ef6SSaurabh Misra }
789015a6ef6SSaurabh Misra
790015a6ef6SSaurabh Misra /*
791015a6ef6SSaurabh Misra * Adds interrupt handler depending on the supported interrupt type by the
792015a6ef6SSaurabh Misra * chip.
793015a6ef6SSaurabh Misra */
794015a6ef6SSaurabh Misra static int
atge_add_intr(atge_t * atgep)795015a6ef6SSaurabh Misra atge_add_intr(atge_t *atgep)
796015a6ef6SSaurabh Misra {
797015a6ef6SSaurabh Misra int err;
798015a6ef6SSaurabh Misra
799015a6ef6SSaurabh Misra /*
800015a6ef6SSaurabh Misra * Get the supported interrupt types.
801015a6ef6SSaurabh Misra */
802015a6ef6SSaurabh Misra err = ddi_intr_get_supported_types(atgep->atge_dip,
803015a6ef6SSaurabh Misra &atgep->atge_intr_types);
804015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
805015a6ef6SSaurabh Misra atge_error(atgep->atge_dip,
806015a6ef6SSaurabh Misra "ddi_intr_get_supported_types failed : %d", err);
8070eb090a7SSaurabh Misra return (DDI_FAILURE);
808015a6ef6SSaurabh Misra }
809015a6ef6SSaurabh Misra
810015a6ef6SSaurabh Misra ATGE_DB(("%s: ddi_intr_get_supported_types() returned : %d",
811015a6ef6SSaurabh Misra atgep->atge_name, atgep->atge_intr_types));
812015a6ef6SSaurabh Misra
813015a6ef6SSaurabh Misra
814015a6ef6SSaurabh Misra if (atgep->atge_intr_types & DDI_INTR_TYPE_MSIX) {
815015a6ef6SSaurabh Misra err = atge_add_intr_handler(atgep, DDI_INTR_TYPE_MSIX);
8160eb090a7SSaurabh Misra if (err == DDI_SUCCESS) {
817015a6ef6SSaurabh Misra ATGE_DB(("%s: Using MSIx for interrupt",
818015a6ef6SSaurabh Misra atgep->atge_name));
819015a6ef6SSaurabh Misra return (err);
820015a6ef6SSaurabh Misra }
821015a6ef6SSaurabh Misra }
822015a6ef6SSaurabh Misra
823015a6ef6SSaurabh Misra if (atgep->atge_intr_types & DDI_INTR_TYPE_MSI) {
824015a6ef6SSaurabh Misra err = atge_add_intr_handler(atgep, DDI_INTR_TYPE_MSI);
8250eb090a7SSaurabh Misra if (err == DDI_SUCCESS) {
826015a6ef6SSaurabh Misra ATGE_DB(("%s: Using MSI for interrupt",
827015a6ef6SSaurabh Misra atgep->atge_name));
828015a6ef6SSaurabh Misra return (err);
829015a6ef6SSaurabh Misra }
830015a6ef6SSaurabh Misra }
831015a6ef6SSaurabh Misra
8320eb090a7SSaurabh Misra err = DDI_FAILURE;
833015a6ef6SSaurabh Misra if (atgep->atge_intr_types & DDI_INTR_TYPE_FIXED) {
834015a6ef6SSaurabh Misra err = atge_add_intr_handler(atgep, DDI_INTR_TYPE_FIXED);
8350eb090a7SSaurabh Misra if (err == DDI_SUCCESS) {
836015a6ef6SSaurabh Misra ATGE_DB(("%s: Using FIXED type for interrupt",
837015a6ef6SSaurabh Misra atgep->atge_name));
838015a6ef6SSaurabh Misra return (err);
839015a6ef6SSaurabh Misra }
840015a6ef6SSaurabh Misra }
841015a6ef6SSaurabh Misra
842015a6ef6SSaurabh Misra return (err);
843015a6ef6SSaurabh Misra }
844015a6ef6SSaurabh Misra
845015a6ef6SSaurabh Misra int
atge_identify_hardware(atge_t * atgep)846015a6ef6SSaurabh Misra atge_identify_hardware(atge_t *atgep)
847015a6ef6SSaurabh Misra {
848015a6ef6SSaurabh Misra uint16_t vid, did;
849015a6ef6SSaurabh Misra int i;
850015a6ef6SSaurabh Misra
851015a6ef6SSaurabh Misra vid = pci_config_get16(atgep->atge_conf_handle, PCI_CONF_VENID);
852015a6ef6SSaurabh Misra did = pci_config_get16(atgep->atge_conf_handle, PCI_CONF_DEVID);
853015a6ef6SSaurabh Misra
854015a6ef6SSaurabh Misra atgep->atge_model = 0;
855015a6ef6SSaurabh Misra for (i = 0; i < (sizeof (atge_cards) / sizeof (atge_cards_t)); i++) {
856015a6ef6SSaurabh Misra if (atge_cards[i].vendor_id == vid &&
857015a6ef6SSaurabh Misra atge_cards[i].device_id == did) {
858015a6ef6SSaurabh Misra atgep->atge_model = atge_cards[i].model;
859*5e8715b9SGary Mills atgep->atge_vid = vid;
860*5e8715b9SGary Mills atgep->atge_did = did;
861015a6ef6SSaurabh Misra atgep->atge_revid =
862015a6ef6SSaurabh Misra pci_config_get8(atgep->atge_conf_handle,
863015a6ef6SSaurabh Misra PCI_CONF_REVID);
864*5e8715b9SGary Mills atge_notice(atgep->atge_dip, "PCI-ID pci%x,%x,%x: %s",
865*5e8715b9SGary Mills vid, did, atgep->atge_revid,
866*5e8715b9SGary Mills atge_cards[i].cardname);
867015a6ef6SSaurabh Misra ATGE_DB(("%s: %s : PCI-ID pci%x,%x and model : %d",
868015a6ef6SSaurabh Misra atgep->atge_name, __func__, vid, did,
869015a6ef6SSaurabh Misra atgep->atge_model));
870015a6ef6SSaurabh Misra
8710eb090a7SSaurabh Misra return (DDI_SUCCESS);
872015a6ef6SSaurabh Misra }
873015a6ef6SSaurabh Misra }
874015a6ef6SSaurabh Misra
875015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "atge driver is attaching to unknown"
876*5e8715b9SGary Mills " pci%x,%x vendor/device-id card", vid, did);
877015a6ef6SSaurabh Misra
878015a6ef6SSaurabh Misra /*
879*5e8715b9SGary Mills * Assume it's L1C chip.
880015a6ef6SSaurabh Misra */
881*5e8715b9SGary Mills atgep->atge_model = ATGE_CHIP_L1C;
882*5e8715b9SGary Mills atgep->atge_vid = vid;
883*5e8715b9SGary Mills atgep->atge_did = did;
884015a6ef6SSaurabh Misra atgep->atge_revid = pci_config_get8(atgep->atge_conf_handle,
885015a6ef6SSaurabh Misra PCI_CONF_REVID);
886015a6ef6SSaurabh Misra
887015a6ef6SSaurabh Misra /*
888015a6ef6SSaurabh Misra * We will leave the decision to caller.
889015a6ef6SSaurabh Misra */
8900eb090a7SSaurabh Misra return (DDI_FAILURE);
891015a6ef6SSaurabh Misra }
892015a6ef6SSaurabh Misra
893015a6ef6SSaurabh Misra int
atge_get_macaddr(atge_t * atgep)894015a6ef6SSaurabh Misra atge_get_macaddr(atge_t *atgep)
895015a6ef6SSaurabh Misra {
896015a6ef6SSaurabh Misra uint32_t reg;
897015a6ef6SSaurabh Misra
898015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_SPI_CTRL);
899015a6ef6SSaurabh Misra if ((reg & SPI_VPD_ENB) != 0) {
900015a6ef6SSaurabh Misra /*
901015a6ef6SSaurabh Misra * Get VPD stored in TWSI EEPROM.
902015a6ef6SSaurabh Misra */
903015a6ef6SSaurabh Misra reg &= ~SPI_VPD_ENB;
904015a6ef6SSaurabh Misra OUTL(atgep, ATGE_SPI_CTRL, reg);
905015a6ef6SSaurabh Misra
906015a6ef6SSaurabh Misra ATGE_DB(("%s: %s called Get VPD", atgep->atge_name, __func__));
907015a6ef6SSaurabh Misra }
908015a6ef6SSaurabh Misra
909015a6ef6SSaurabh Misra atgep->atge_ether_addr[5] = INB(atgep, ATGE_PAR0 + 0);
910015a6ef6SSaurabh Misra atgep->atge_ether_addr[4] = INB(atgep, ATGE_PAR0 + 1);
911015a6ef6SSaurabh Misra atgep->atge_ether_addr[3] = INB(atgep, ATGE_PAR0 + 2);
912015a6ef6SSaurabh Misra atgep->atge_ether_addr[2] = INB(atgep, ATGE_PAR0 + 3);
913015a6ef6SSaurabh Misra atgep->atge_ether_addr[1] = INB(atgep, ATGE_PAR1 + 0);
914015a6ef6SSaurabh Misra atgep->atge_ether_addr[0] = INB(atgep, ATGE_PAR1 + 1);
915015a6ef6SSaurabh Misra
916015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() Station Address - %x:%x:%x:%x:%x:%x",
917015a6ef6SSaurabh Misra atgep->atge_name, __func__,
918015a6ef6SSaurabh Misra atgep->atge_ether_addr[0],
919015a6ef6SSaurabh Misra atgep->atge_ether_addr[1],
920015a6ef6SSaurabh Misra atgep->atge_ether_addr[2],
921015a6ef6SSaurabh Misra atgep->atge_ether_addr[3],
922015a6ef6SSaurabh Misra atgep->atge_ether_addr[4],
923015a6ef6SSaurabh Misra atgep->atge_ether_addr[5]));
924015a6ef6SSaurabh Misra
925015a6ef6SSaurabh Misra bcopy(atgep->atge_ether_addr, atgep->atge_dev_addr, ETHERADDRL);
926015a6ef6SSaurabh Misra
9270eb090a7SSaurabh Misra return (DDI_SUCCESS);
928015a6ef6SSaurabh Misra }
929015a6ef6SSaurabh Misra
930015a6ef6SSaurabh Misra /*
931*5e8715b9SGary Mills * Reset functionality for L1, L1E, and L1C. It's same.
932015a6ef6SSaurabh Misra */
933015a6ef6SSaurabh Misra static void
atge_device_reset(atge_t * atgep)934015a6ef6SSaurabh Misra atge_device_reset(atge_t *atgep)
935015a6ef6SSaurabh Misra {
936*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
937*5e8715b9SGary Mills case ATGE_CHIP_L1E:
938*5e8715b9SGary Mills case ATGE_CHIP_L1:
939*5e8715b9SGary Mills case ATGE_CHIP_L1C:
940015a6ef6SSaurabh Misra atge_device_reset_l1_l1e(atgep);
941*5e8715b9SGary Mills break;
942*5e8715b9SGary Mills }
943015a6ef6SSaurabh Misra }
944015a6ef6SSaurabh Misra
945015a6ef6SSaurabh Misra void
atge_device_reset_l1_l1e(atge_t * atgep)946015a6ef6SSaurabh Misra atge_device_reset_l1_l1e(atge_t *atgep)
947015a6ef6SSaurabh Misra {
948015a6ef6SSaurabh Misra uint32_t reg;
949015a6ef6SSaurabh Misra int t;
950*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
951*5e8715b9SGary Mills case ATGE_CHIP_L1C:
952*5e8715b9SGary Mills OUTL(atgep, ATGE_MASTER_CFG, MASTER_RESET | 0x40);
953*5e8715b9SGary Mills break;
954*5e8715b9SGary Mills default:
955015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MASTER_CFG, MASTER_RESET);
956*5e8715b9SGary Mills break;
957*5e8715b9SGary Mills }
958015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_MASTER_CFG);
959015a6ef6SSaurabh Misra for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
960015a6ef6SSaurabh Misra drv_usecwait(10);
961015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_MASTER_CFG);
962015a6ef6SSaurabh Misra if ((reg & MASTER_RESET) == 0)
963015a6ef6SSaurabh Misra break;
964015a6ef6SSaurabh Misra }
965015a6ef6SSaurabh Misra
966015a6ef6SSaurabh Misra if (t == 0) {
967015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, " master reset timeout reg : %x",
968015a6ef6SSaurabh Misra reg);
969015a6ef6SSaurabh Misra }
970015a6ef6SSaurabh Misra
971015a6ef6SSaurabh Misra for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
972015a6ef6SSaurabh Misra if ((reg = INL(atgep, ATGE_IDLE_STATUS)) == 0)
973015a6ef6SSaurabh Misra break;
974015a6ef6SSaurabh Misra
975015a6ef6SSaurabh Misra drv_usecwait(10);
976015a6ef6SSaurabh Misra }
977015a6ef6SSaurabh Misra
978015a6ef6SSaurabh Misra if (t == 0) {
979015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "device reset timeout reg : %x",
980015a6ef6SSaurabh Misra reg);
981015a6ef6SSaurabh Misra }
982015a6ef6SSaurabh Misra
983*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
984*5e8715b9SGary Mills case ATGE_CHIP_L1E:
985*5e8715b9SGary Mills case ATGE_CHIP_L1:
986015a6ef6SSaurabh Misra /*
987015a6ef6SSaurabh Misra * Initialize PCIe module. These values came from FreeBSD and
988015a6ef6SSaurabh Misra * we don't know the meaning of it.
989015a6ef6SSaurabh Misra */
990*5e8715b9SGary Mills OUTL(atgep, ATGE_LTSSM_ID_CFG, 0x6500);
991015a6ef6SSaurabh Misra reg = INL(atgep, 0x1008) | 0x8000;
992015a6ef6SSaurabh Misra OUTL(atgep, 0x1008, reg);
993*5e8715b9SGary Mills break;
994*5e8715b9SGary Mills case ATGE_CHIP_L1C:
995*5e8715b9SGary Mills break;
996*5e8715b9SGary Mills }
997015a6ef6SSaurabh Misra
998015a6ef6SSaurabh Misra /*
999015a6ef6SSaurabh Misra * Get chip revision.
1000015a6ef6SSaurabh Misra */
1001015a6ef6SSaurabh Misra atgep->atge_chip_rev = INL(atgep, ATGE_MASTER_CFG) >>
1002015a6ef6SSaurabh Misra MASTER_CHIP_REV_SHIFT;
1003015a6ef6SSaurabh Misra
1004015a6ef6SSaurabh Misra ATGE_DB(("%s: %s reset successfully rev : %x", atgep->atge_name,
1005015a6ef6SSaurabh Misra __func__, atgep->atge_chip_rev));
1006015a6ef6SSaurabh Misra }
1007015a6ef6SSaurabh Misra
1008015a6ef6SSaurabh Misra /*
1009015a6ef6SSaurabh Misra * DMA allocation for L1 and L1E is bit different since L1E uses RX pages
1010015a6ef6SSaurabh Misra * instead of descriptor based RX model.
1011015a6ef6SSaurabh Misra */
1012015a6ef6SSaurabh Misra static int
atge_alloc_dma(atge_t * atgep)1013015a6ef6SSaurabh Misra atge_alloc_dma(atge_t *atgep)
1014015a6ef6SSaurabh Misra {
10150eb090a7SSaurabh Misra int err = DDI_FAILURE;
1016015a6ef6SSaurabh Misra
1017*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
1018*5e8715b9SGary Mills case ATGE_CHIP_L1E:
1019015a6ef6SSaurabh Misra err = atge_l1e_alloc_dma(atgep);
1020*5e8715b9SGary Mills break;
1021*5e8715b9SGary Mills case ATGE_CHIP_L1:
10220eb090a7SSaurabh Misra err = atge_l1_alloc_dma(atgep);
1023*5e8715b9SGary Mills break;
1024*5e8715b9SGary Mills case ATGE_CHIP_L1C:
1025*5e8715b9SGary Mills err = atge_l1c_alloc_dma(atgep);
1026*5e8715b9SGary Mills break;
1027015a6ef6SSaurabh Misra }
1028015a6ef6SSaurabh Misra
1029015a6ef6SSaurabh Misra return (err);
1030015a6ef6SSaurabh Misra }
1031015a6ef6SSaurabh Misra
1032015a6ef6SSaurabh Misra static void
atge_free_dma(atge_t * atgep)1033015a6ef6SSaurabh Misra atge_free_dma(atge_t *atgep)
1034015a6ef6SSaurabh Misra {
1035*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
1036*5e8715b9SGary Mills case ATGE_CHIP_L1E:
1037015a6ef6SSaurabh Misra atge_l1e_free_dma(atgep);
1038*5e8715b9SGary Mills break;
1039*5e8715b9SGary Mills case ATGE_CHIP_L1:
1040*5e8715b9SGary Mills atge_l1_free_dma(atgep);
1041*5e8715b9SGary Mills break;
1042*5e8715b9SGary Mills case ATGE_CHIP_L1C:
1043*5e8715b9SGary Mills atge_l1c_free_dma(atgep);
1044*5e8715b9SGary Mills break;
1045015a6ef6SSaurabh Misra }
1046015a6ef6SSaurabh Misra }
1047015a6ef6SSaurabh Misra
1048015a6ef6SSaurabh Misra /*
1049015a6ef6SSaurabh Misra * Attach entry point in the driver.
1050015a6ef6SSaurabh Misra */
1051015a6ef6SSaurabh Misra static int
atge_attach(dev_info_t * devinfo,ddi_attach_cmd_t cmd)1052015a6ef6SSaurabh Misra atge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
1053015a6ef6SSaurabh Misra {
1054015a6ef6SSaurabh Misra atge_t *atgep;
1055015a6ef6SSaurabh Misra mac_register_t *macreg;
1056015a6ef6SSaurabh Misra int instance;
1057015a6ef6SSaurabh Misra uint16_t cap_ptr;
1058015a6ef6SSaurabh Misra uint16_t burst;
1059015a6ef6SSaurabh Misra int err;
1060015a6ef6SSaurabh Misra mii_ops_t *mii_ops;
1061015a6ef6SSaurabh Misra
1062015a6ef6SSaurabh Misra instance = ddi_get_instance(devinfo);
1063015a6ef6SSaurabh Misra
1064015a6ef6SSaurabh Misra switch (cmd) {
1065015a6ef6SSaurabh Misra case DDI_RESUME:
1066015a6ef6SSaurabh Misra return (atge_resume(devinfo));
1067015a6ef6SSaurabh Misra
1068015a6ef6SSaurabh Misra case DDI_ATTACH:
1069015a6ef6SSaurabh Misra ddi_set_driver_private(devinfo, NULL);
1070015a6ef6SSaurabh Misra break;
1071*5e8715b9SGary Mills default:
1072*5e8715b9SGary Mills return (DDI_FAILURE);
1073*5e8715b9SGary Mills
1074015a6ef6SSaurabh Misra }
1075015a6ef6SSaurabh Misra
1076015a6ef6SSaurabh Misra atgep = kmem_zalloc(sizeof (atge_t), KM_SLEEP);
1077015a6ef6SSaurabh Misra ddi_set_driver_private(devinfo, atgep);
1078015a6ef6SSaurabh Misra atgep->atge_dip = devinfo;
1079015a6ef6SSaurabh Misra
1080015a6ef6SSaurabh Misra /*
1081015a6ef6SSaurabh Misra * Setup name and instance number to be used for debugging and
1082015a6ef6SSaurabh Misra * error reporting.
1083015a6ef6SSaurabh Misra */
1084015a6ef6SSaurabh Misra (void) snprintf(atgep->atge_name, sizeof (atgep->atge_name), "%s%d",
1085015a6ef6SSaurabh Misra "atge", instance);
1086015a6ef6SSaurabh Misra
1087015a6ef6SSaurabh Misra
1088015a6ef6SSaurabh Misra /*
1089015a6ef6SSaurabh Misra * Map PCI config space.
1090015a6ef6SSaurabh Misra */
1091015a6ef6SSaurabh Misra err = pci_config_setup(devinfo, &atgep->atge_conf_handle);
1092015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
1093015a6ef6SSaurabh Misra atge_error(devinfo, "pci_config_setup() failed");
1094015a6ef6SSaurabh Misra goto fail1;
1095015a6ef6SSaurabh Misra }
1096015a6ef6SSaurabh Misra
1097015a6ef6SSaurabh Misra (void) atge_identify_hardware(atgep);
1098015a6ef6SSaurabh Misra
1099015a6ef6SSaurabh Misra /*
1100015a6ef6SSaurabh Misra * Map Device registers.
1101015a6ef6SSaurabh Misra */
1102015a6ef6SSaurabh Misra err = ddi_regs_map_setup(devinfo, ATGE_PCI_REG_NUMBER,
1103015a6ef6SSaurabh Misra &atgep->atge_io_regs, 0, 0, &atge_dev_attr, &atgep->atge_io_handle);
1104015a6ef6SSaurabh Misra if (err != DDI_SUCCESS) {
1105015a6ef6SSaurabh Misra atge_error(devinfo, "ddi_regs_map_setup() failed");
1106015a6ef6SSaurabh Misra goto fail2;
1107015a6ef6SSaurabh Misra }
1108015a6ef6SSaurabh Misra
1109015a6ef6SSaurabh Misra /*
1110015a6ef6SSaurabh Misra * Add interrupt and its associated handler.
1111015a6ef6SSaurabh Misra */
1112015a6ef6SSaurabh Misra err = atge_add_intr(atgep);
11130eb090a7SSaurabh Misra if (err != DDI_SUCCESS) {
1114015a6ef6SSaurabh Misra atge_error(devinfo, "Failed to add interrupt handler");
1115015a6ef6SSaurabh Misra goto fail3;
1116015a6ef6SSaurabh Misra }
1117015a6ef6SSaurabh Misra
1118015a6ef6SSaurabh Misra mutex_init(&atgep->atge_intr_lock, NULL, MUTEX_DRIVER,
1119015a6ef6SSaurabh Misra DDI_INTR_PRI(atgep->atge_intr_pri));
1120015a6ef6SSaurabh Misra
1121015a6ef6SSaurabh Misra mutex_init(&atgep->atge_tx_lock, NULL, MUTEX_DRIVER,
1122015a6ef6SSaurabh Misra DDI_INTR_PRI(atgep->atge_intr_pri));
1123015a6ef6SSaurabh Misra
1124015a6ef6SSaurabh Misra mutex_init(&atgep->atge_rx_lock, NULL, MUTEX_DRIVER,
1125015a6ef6SSaurabh Misra DDI_INTR_PRI(atgep->atge_intr_pri));
1126015a6ef6SSaurabh Misra
1127015a6ef6SSaurabh Misra mutex_init(&atgep->atge_mii_lock, NULL, MUTEX_DRIVER, NULL);
1128015a6ef6SSaurabh Misra
11290eb090a7SSaurabh Misra /*
11300eb090a7SSaurabh Misra * Used to lock down MBOX register on L1 chip since RX consumer,
11310eb090a7SSaurabh Misra * TX producer and RX return ring consumer are shared.
11320eb090a7SSaurabh Misra */
11330eb090a7SSaurabh Misra mutex_init(&atgep->atge_mbox_lock, NULL, MUTEX_DRIVER,
11340eb090a7SSaurabh Misra DDI_INTR_PRI(atgep->atge_intr_pri));
11350eb090a7SSaurabh Misra
1136015a6ef6SSaurabh Misra atgep->atge_link_state = LINK_STATE_DOWN;
1137015a6ef6SSaurabh Misra atgep->atge_mtu = ETHERMTU;
1138015a6ef6SSaurabh Misra
1139*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
1140*5e8715b9SGary Mills case ATGE_CHIP_L1E:
1141015a6ef6SSaurabh Misra if (atgep->atge_revid > 0xF0) {
1142015a6ef6SSaurabh Misra /* L2E Rev. B. AR8114 */
1143015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_FLAG_FASTETHER;
1144015a6ef6SSaurabh Misra } else {
11450eb090a7SSaurabh Misra if ((INL(atgep, L1E_PHY_STATUS) &
11460eb090a7SSaurabh Misra PHY_STATUS_100M) != 0) {
1147015a6ef6SSaurabh Misra /* L1E AR8121 */
1148015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_FLAG_JUMBO;
1149015a6ef6SSaurabh Misra } else {
1150015a6ef6SSaurabh Misra /* L2E Rev. A. AR8113 */
1151015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_FLAG_FASTETHER;
1152015a6ef6SSaurabh Misra }
1153015a6ef6SSaurabh Misra }
1154*5e8715b9SGary Mills break;
1155*5e8715b9SGary Mills case ATGE_CHIP_L1:
1156*5e8715b9SGary Mills break;
1157*5e8715b9SGary Mills case ATGE_CHIP_L1C:
1158*5e8715b9SGary Mills /*
1159*5e8715b9SGary Mills * One odd thing is AR8132 uses the same PHY hardware(F1
1160*5e8715b9SGary Mills * gigabit PHY) of AR8131. So atphy(4) of AR8132 reports
1161*5e8715b9SGary Mills * the PHY supports 1000Mbps but that's not true. The PHY
1162*5e8715b9SGary Mills * used in AR8132 can't establish gigabit link even if it
1163*5e8715b9SGary Mills * shows the same PHY model/revision number of AR8131.
1164*5e8715b9SGary Mills *
1165*5e8715b9SGary Mills * It seems that AR813x/AR815x has silicon bug for SMB. In
1166*5e8715b9SGary Mills * addition, Atheros said that enabling SMB wouldn't improve
1167*5e8715b9SGary Mills * performance. However I think it's bad to access lots of
1168*5e8715b9SGary Mills * registers to extract MAC statistics.
1169*5e8715b9SGary Mills *
1170*5e8715b9SGary Mills * Don't use Tx CMB. It is known to have silicon bug.
1171*5e8715b9SGary Mills */
1172*5e8715b9SGary Mills switch (ATGE_DID(atgep)) {
1173*5e8715b9SGary Mills case ATGE_CHIP_AR8152V2_DEV_ID:
1174*5e8715b9SGary Mills case ATGE_CHIP_AR8152V1_DEV_ID:
1175*5e8715b9SGary Mills atgep->atge_flags |= ATGE_FLAG_APS |
1176*5e8715b9SGary Mills ATGE_FLAG_FASTETHER |
1177*5e8715b9SGary Mills ATGE_FLAG_ASPM_MON | ATGE_FLAG_JUMBO |
1178*5e8715b9SGary Mills ATGE_FLAG_SMB_BUG | ATGE_FLAG_CMB_BUG;
1179*5e8715b9SGary Mills break;
1180*5e8715b9SGary Mills case ATGE_CHIP_AR8151V2_DEV_ID:
1181*5e8715b9SGary Mills case ATGE_CHIP_AR8151V1_DEV_ID:
1182*5e8715b9SGary Mills atgep->atge_flags |= ATGE_FLAG_APS |
1183*5e8715b9SGary Mills ATGE_FLAG_ASPM_MON | ATGE_FLAG_JUMBO |
1184*5e8715b9SGary Mills ATGE_FLAG_SMB_BUG | ATGE_FLAG_CMB_BUG;
1185*5e8715b9SGary Mills break;
1186*5e8715b9SGary Mills case ATGE_CHIP_L1CF_DEV_ID:
1187*5e8715b9SGary Mills atgep->atge_flags |= ATGE_FLAG_FASTETHER;
1188*5e8715b9SGary Mills break;
1189*5e8715b9SGary Mills case ATGE_CHIP_L1CG_DEV_ID:
1190*5e8715b9SGary Mills break;
1191*5e8715b9SGary Mills }
1192*5e8715b9SGary Mills break;
11930eb090a7SSaurabh Misra }
1194015a6ef6SSaurabh Misra
1195015a6ef6SSaurabh Misra /*
1196015a6ef6SSaurabh Misra * Get DMA parameters from PCIe device control register.
1197015a6ef6SSaurabh Misra */
1198015a6ef6SSaurabh Misra err = PCI_CAP_LOCATE(atgep->atge_conf_handle, PCI_CAP_ID_PCI_E,
1199015a6ef6SSaurabh Misra &cap_ptr);
1200015a6ef6SSaurabh Misra
1201015a6ef6SSaurabh Misra if (err == DDI_FAILURE) {
1202015a6ef6SSaurabh Misra atgep->atge_dma_rd_burst = DMA_CFG_RD_BURST_128;
1203015a6ef6SSaurabh Misra atgep->atge_dma_wr_burst = DMA_CFG_WR_BURST_128;
1204015a6ef6SSaurabh Misra } else {
1205015a6ef6SSaurabh Misra atgep->atge_flags |= ATGE_FLAG_PCIE;
1206015a6ef6SSaurabh Misra burst = pci_config_get16(atgep->atge_conf_handle,
1207015a6ef6SSaurabh Misra cap_ptr + 0x08);
1208015a6ef6SSaurabh Misra
1209015a6ef6SSaurabh Misra /*
1210015a6ef6SSaurabh Misra * Max read request size.
1211015a6ef6SSaurabh Misra */
1212015a6ef6SSaurabh Misra atgep->atge_dma_rd_burst = ((burst >> 12) & 0x07) <<
1213015a6ef6SSaurabh Misra DMA_CFG_RD_BURST_SHIFT;
1214015a6ef6SSaurabh Misra
1215015a6ef6SSaurabh Misra /*
1216015a6ef6SSaurabh Misra * Max Payload Size.
1217015a6ef6SSaurabh Misra */
1218015a6ef6SSaurabh Misra atgep->atge_dma_wr_burst = ((burst >> 5) & 0x07) <<
1219015a6ef6SSaurabh Misra DMA_CFG_WR_BURST_SHIFT;
1220015a6ef6SSaurabh Misra
1221015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() MRR : %d, MPS : %d",
1222015a6ef6SSaurabh Misra atgep->atge_name, __func__,
1223015a6ef6SSaurabh Misra (128 << ((burst >> 12) & 0x07)),
1224015a6ef6SSaurabh Misra (128 << ((burst >> 5) & 0x07))));
1225015a6ef6SSaurabh Misra }
1226015a6ef6SSaurabh Misra
1227*5e8715b9SGary Mills /* Clear data link and flow-control protocol error. */
1228*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
1229*5e8715b9SGary Mills case ATGE_CHIP_L1E:
1230*5e8715b9SGary Mills break;
1231*5e8715b9SGary Mills case ATGE_CHIP_L1:
1232*5e8715b9SGary Mills break;
1233*5e8715b9SGary Mills case ATGE_CHIP_L1C:
1234*5e8715b9SGary Mills OUTL_AND(atgep, ATGE_PEX_UNC_ERR_SEV,
1235*5e8715b9SGary Mills ~(PEX_UNC_ERR_SEV_UC | PEX_UNC_ERR_SEV_FCP));
1236*5e8715b9SGary Mills OUTL_AND(atgep, ATGE_LTSSM_ID_CFG, ~LTSSM_ID_WRO_ENB);
1237*5e8715b9SGary Mills OUTL_OR(atgep, ATGE_PCIE_PHYMISC, PCIE_PHYMISC_FORCE_RCV_DET);
1238*5e8715b9SGary Mills break;
1239*5e8715b9SGary Mills }
1240*5e8715b9SGary Mills
1241015a6ef6SSaurabh Misra /*
1242015a6ef6SSaurabh Misra * Allocate DMA resources.
1243015a6ef6SSaurabh Misra */
1244015a6ef6SSaurabh Misra err = atge_alloc_dma(atgep);
12450eb090a7SSaurabh Misra if (err != DDI_SUCCESS) {
1246015a6ef6SSaurabh Misra atge_error(devinfo, "Failed to allocate DMA resources");
1247015a6ef6SSaurabh Misra goto fail4;
1248015a6ef6SSaurabh Misra }
1249015a6ef6SSaurabh Misra
1250015a6ef6SSaurabh Misra /*
1251015a6ef6SSaurabh Misra * Get station address.
1252015a6ef6SSaurabh Misra */
1253015a6ef6SSaurabh Misra (void) atge_get_macaddr(atgep);
1254015a6ef6SSaurabh Misra
1255015a6ef6SSaurabh Misra /*
1256015a6ef6SSaurabh Misra * Setup MII.
1257015a6ef6SSaurabh Misra */
1258*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
1259*5e8715b9SGary Mills case ATGE_CHIP_L1E:
1260015a6ef6SSaurabh Misra mii_ops = &atge_l1e_mii_ops;
1261*5e8715b9SGary Mills break;
1262*5e8715b9SGary Mills case ATGE_CHIP_L1:
12630eb090a7SSaurabh Misra mii_ops = &atge_l1_mii_ops;
1264*5e8715b9SGary Mills break;
1265*5e8715b9SGary Mills case ATGE_CHIP_L1C:
1266*5e8715b9SGary Mills mii_ops = &atge_l1c_mii_ops;
1267*5e8715b9SGary Mills break;
1268015a6ef6SSaurabh Misra }
1269015a6ef6SSaurabh Misra
1270015a6ef6SSaurabh Misra if ((atgep->atge_mii = mii_alloc(atgep, devinfo,
1271015a6ef6SSaurabh Misra mii_ops)) == NULL) {
1272015a6ef6SSaurabh Misra atge_error(devinfo, "mii_alloc() failed");
1273015a6ef6SSaurabh Misra goto fail4;
1274015a6ef6SSaurabh Misra }
1275015a6ef6SSaurabh Misra
1276015a6ef6SSaurabh Misra /*
1277015a6ef6SSaurabh Misra * Register with MAC layer.
1278015a6ef6SSaurabh Misra */
1279015a6ef6SSaurabh Misra if ((macreg = mac_alloc(MAC_VERSION)) == NULL) {
1280015a6ef6SSaurabh Misra atge_error(devinfo, "mac_alloc() failed due to version");
1281015a6ef6SSaurabh Misra goto fail4;
1282015a6ef6SSaurabh Misra }
1283015a6ef6SSaurabh Misra
1284015a6ef6SSaurabh Misra macreg->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
1285015a6ef6SSaurabh Misra macreg->m_driver = atgep;
1286015a6ef6SSaurabh Misra macreg->m_dip = devinfo;
1287015a6ef6SSaurabh Misra macreg->m_instance = instance;
1288015a6ef6SSaurabh Misra macreg->m_src_addr = atgep->atge_ether_addr;
1289015a6ef6SSaurabh Misra macreg->m_callbacks = &atge_m_callbacks;
1290015a6ef6SSaurabh Misra macreg->m_min_sdu = 0;
1291015a6ef6SSaurabh Misra macreg->m_max_sdu = atgep->atge_mtu;
1292015a6ef6SSaurabh Misra macreg->m_margin = VLAN_TAGSZ;
1293015a6ef6SSaurabh Misra
1294015a6ef6SSaurabh Misra if ((err = mac_register(macreg, &atgep->atge_mh)) != 0) {
1295015a6ef6SSaurabh Misra atge_error(devinfo, "mac_register() failed with :%d", err);
1296015a6ef6SSaurabh Misra mac_free(macreg);
1297015a6ef6SSaurabh Misra goto fail4;
1298015a6ef6SSaurabh Misra }
1299015a6ef6SSaurabh Misra
1300015a6ef6SSaurabh Misra mac_free(macreg);
1301015a6ef6SSaurabh Misra
1302015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() driver attached successfully",
1303015a6ef6SSaurabh Misra atgep->atge_name, __func__));
1304015a6ef6SSaurabh Misra
1305015a6ef6SSaurabh Misra atge_device_reset(atgep);
1306015a6ef6SSaurabh Misra
1307015a6ef6SSaurabh Misra atgep->atge_chip_state = ATGE_CHIP_INITIALIZED;
1308015a6ef6SSaurabh Misra
1309015a6ef6SSaurabh Misra /*
1310015a6ef6SSaurabh Misra * At last - enable interrupts.
1311015a6ef6SSaurabh Misra */
1312015a6ef6SSaurabh Misra err = atge_enable_intrs(atgep);
13130eb090a7SSaurabh Misra if (err == DDI_FAILURE) {
1314015a6ef6SSaurabh Misra goto fail5;
1315015a6ef6SSaurabh Misra }
1316015a6ef6SSaurabh Misra
1317015a6ef6SSaurabh Misra /*
1318015a6ef6SSaurabh Misra * Reset the PHY before starting.
1319015a6ef6SSaurabh Misra */
1320*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
1321*5e8715b9SGary Mills case ATGE_CHIP_L1E:
1322015a6ef6SSaurabh Misra atge_l1e_mii_reset(atgep);
1323*5e8715b9SGary Mills break;
1324*5e8715b9SGary Mills case ATGE_CHIP_L1:
13250eb090a7SSaurabh Misra atge_l1_mii_reset(atgep);
1326*5e8715b9SGary Mills break;
1327*5e8715b9SGary Mills case ATGE_CHIP_L1C:
1328*5e8715b9SGary Mills atge_l1c_mii_reset(atgep);
1329*5e8715b9SGary Mills break;
1330015a6ef6SSaurabh Misra }
1331015a6ef6SSaurabh Misra
1332015a6ef6SSaurabh Misra /*
1333015a6ef6SSaurabh Misra * Let the PHY run.
1334015a6ef6SSaurabh Misra */
1335015a6ef6SSaurabh Misra mii_start(atgep->atge_mii);
1336015a6ef6SSaurabh Misra
1337015a6ef6SSaurabh Misra return (DDI_SUCCESS);
1338015a6ef6SSaurabh Misra
1339015a6ef6SSaurabh Misra fail5:
1340015a6ef6SSaurabh Misra (void) mac_unregister(atgep->atge_mh);
1341015a6ef6SSaurabh Misra atge_device_stop(atgep);
1342015a6ef6SSaurabh Misra mii_stop(atgep->atge_mii);
1343015a6ef6SSaurabh Misra mii_free(atgep->atge_mii);
1344015a6ef6SSaurabh Misra fail4:
1345015a6ef6SSaurabh Misra atge_free_dma(atgep);
1346015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_intr_lock);
1347015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_tx_lock);
1348015a6ef6SSaurabh Misra mutex_destroy(&atgep->atge_rx_lock);
1349015a6ef6SSaurabh Misra atge_remove_intr(atgep);
1350015a6ef6SSaurabh Misra fail3:
1351015a6ef6SSaurabh Misra ddi_regs_map_free(&atgep->atge_io_handle);
1352015a6ef6SSaurabh Misra fail2:
1353015a6ef6SSaurabh Misra pci_config_teardown(&atgep->atge_conf_handle);
1354015a6ef6SSaurabh Misra fail1:
1355015a6ef6SSaurabh Misra if (atgep)
1356015a6ef6SSaurabh Misra kmem_free(atgep, sizeof (atge_t));
1357015a6ef6SSaurabh Misra
1358015a6ef6SSaurabh Misra return (DDI_FAILURE);
1359015a6ef6SSaurabh Misra }
1360015a6ef6SSaurabh Misra
1361015a6ef6SSaurabh Misra static int
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 */
1616*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
1617*5e8715b9SGary Mills case ATGE_CHIP_L1E:
1618015a6ef6SSaurabh Misra atge_l1e_mii_reset(atgep);
1619*5e8715b9SGary Mills break;
1620*5e8715b9SGary Mills case ATGE_CHIP_L1:
1621*5e8715b9SGary Mills break;
1622*5e8715b9SGary Mills case ATGE_CHIP_L1C:
1623*5e8715b9SGary Mills break;
1624015a6ef6SSaurabh Misra }
1625015a6ef6SSaurabh Misra
1626015a6ef6SSaurabh Misra mii_resume(atgep->atge_mii);
1627015a6ef6SSaurabh Misra
1628015a6ef6SSaurabh Misra /* kick-off downstream */
1629015a6ef6SSaurabh Misra mac_tx_update(atgep->atge_mh);
1630015a6ef6SSaurabh Misra
1631015a6ef6SSaurabh Misra return (DDI_SUCCESS);
1632015a6ef6SSaurabh Misra }
1633015a6ef6SSaurabh Misra
1634015a6ef6SSaurabh Misra static int
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;
2001015a6ef6SSaurabh Misra
20020eb090a7SSaurabh Misra r = mii_m_setprop(atgep->atge_mii, name, num, sz, val);
20030eb090a7SSaurabh Misra
20040eb090a7SSaurabh Misra if (r == 0) {
20050eb090a7SSaurabh Misra mutex_enter(&atgep->atge_intr_lock);
20060eb090a7SSaurabh Misra mutex_enter(&atgep->atge_tx_lock);
20070eb090a7SSaurabh Misra
20080eb090a7SSaurabh Misra if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) {
20090eb090a7SSaurabh Misra atge_device_restart(atgep);
20100eb090a7SSaurabh Misra }
20110eb090a7SSaurabh Misra
20120eb090a7SSaurabh Misra mutex_exit(&atgep->atge_tx_lock);
20130eb090a7SSaurabh Misra mutex_exit(&atgep->atge_intr_lock);
20140eb090a7SSaurabh Misra }
20150eb090a7SSaurabh Misra
20160eb090a7SSaurabh Misra return (r);
2017015a6ef6SSaurabh Misra }
2018015a6ef6SSaurabh Misra
20190dc2366fSVenugopal Iyer static void
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
2057*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
2058*5e8715b9SGary Mills case ATGE_CHIP_L1E:
2059015a6ef6SSaurabh Misra atge_l1e_program_dma(atgep);
2060*5e8715b9SGary Mills break;
2061*5e8715b9SGary Mills case ATGE_CHIP_L1:
20620eb090a7SSaurabh Misra atge_l1_program_dma(atgep);
2063*5e8715b9SGary Mills break;
2064*5e8715b9SGary Mills case ATGE_CHIP_L1C:
2065*5e8715b9SGary Mills atge_l1c_program_dma(atgep);
2066*5e8715b9SGary Mills break;
2067015a6ef6SSaurabh Misra }
2068015a6ef6SSaurabh Misra
2069015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() dma, counters programmed ", atgep->atge_name,
2070015a6ef6SSaurabh Misra __func__));
2071015a6ef6SSaurabh Misra
2072*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
2073*5e8715b9SGary Mills case ATGE_CHIP_L1E:
2074*5e8715b9SGary Mills case ATGE_CHIP_L1:
2075015a6ef6SSaurabh Misra OUTW(atgep, ATGE_INTR_CLR_TIMER, 1*1000/2);
2076*5e8715b9SGary Mills break;
2077*5e8715b9SGary Mills case ATGE_CHIP_L1C:
2078*5e8715b9SGary Mills /*
2079*5e8715b9SGary Mills * Disable interrupt re-trigger timer. We don't want automatic
2080*5e8715b9SGary Mills * re-triggering of un-ACKed interrupts.
2081*5e8715b9SGary Mills */
2082*5e8715b9SGary Mills OUTL(atgep, ATGE_INTR_RETRIG_TIMER, ATGE_USECS(0));
2083*5e8715b9SGary Mills /* Configure CMB. */
2084*5e8715b9SGary Mills OUTL(atgep, ATGE_CMB_TX_TIMER, ATGE_USECS(0));
2085*5e8715b9SGary Mills /*
2086*5e8715b9SGary Mills * Hardware can be configured to issue SMB interrupt based
2087*5e8715b9SGary Mills * on programmed interval. Since there is a callout that is
2088*5e8715b9SGary Mills * invoked for every hz in driver we use that instead of
2089*5e8715b9SGary Mills * relying on periodic SMB interrupt.
2090*5e8715b9SGary Mills */
2091*5e8715b9SGary Mills OUTL(atgep, ATGE_SMB_STAT_TIMER, ATGE_USECS(0));
2092*5e8715b9SGary Mills /* Clear MAC statistics. */
2093*5e8715b9SGary Mills atge_l1c_clear_stats(atgep);
2094*5e8715b9SGary Mills break;
2095*5e8715b9SGary Mills }
2096015a6ef6SSaurabh Misra
2097015a6ef6SSaurabh Misra /*
20980eb090a7SSaurabh Misra * Set Maximum frame size but don't let MTU be less than ETHER_MTU.
2099015a6ef6SSaurabh Misra */
2100015a6ef6SSaurabh Misra if (atgep->atge_mtu < ETHERMTU)
2101015a6ef6SSaurabh Misra atgep->atge_max_frame_size = ETHERMTU;
2102015a6ef6SSaurabh Misra else
2103015a6ef6SSaurabh Misra atgep->atge_max_frame_size = atgep->atge_mtu;
2104015a6ef6SSaurabh Misra
2105015a6ef6SSaurabh Misra atgep->atge_max_frame_size += sizeof (struct ether_header) +
2106015a6ef6SSaurabh Misra VLAN_TAGSZ + ETHERFCSL;
2107015a6ef6SSaurabh Misra OUTL(atgep, ATGE_FRAME_SIZE, atgep->atge_max_frame_size);
2108015a6ef6SSaurabh Misra
2109*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
2110*5e8715b9SGary Mills case ATGE_CHIP_L1E:
2111*5e8715b9SGary Mills break;
2112*5e8715b9SGary Mills case ATGE_CHIP_L1:
2113*5e8715b9SGary Mills break;
2114*5e8715b9SGary Mills case ATGE_CHIP_L1C:
2115*5e8715b9SGary Mills /* Disable header split(?) */
2116*5e8715b9SGary Mills OUTL(atgep, ATGE_HDS_CFG, 0);
2117*5e8715b9SGary Mills break;
2118*5e8715b9SGary Mills }
2119015a6ef6SSaurabh Misra
2120015a6ef6SSaurabh Misra /*
2121015a6ef6SSaurabh Misra * Configure IPG/IFG parameters.
2122015a6ef6SSaurabh Misra */
2123015a6ef6SSaurabh Misra OUTL(atgep, ATGE_IPG_IFG_CFG,
2124015a6ef6SSaurabh Misra ((IPG_IFG_IPG2_DEFAULT << IPG_IFG_IPG2_SHIFT) & IPG_IFG_IPG2_MASK) |
2125015a6ef6SSaurabh Misra ((IPG_IFG_IPG1_DEFAULT << IPG_IFG_IPG1_SHIFT) & IPG_IFG_IPG1_MASK) |
2126015a6ef6SSaurabh Misra ((IPG_IFG_MIFG_DEFAULT << IPG_IFG_MIFG_SHIFT) & IPG_IFG_MIFG_MASK) |
2127015a6ef6SSaurabh Misra ((IPG_IFG_IPGT_DEFAULT << IPG_IFG_IPGT_SHIFT) & IPG_IFG_IPGT_MASK));
2128015a6ef6SSaurabh Misra
2129015a6ef6SSaurabh Misra /*
2130015a6ef6SSaurabh Misra * Set parameters for half-duplex media.
2131015a6ef6SSaurabh Misra */
2132015a6ef6SSaurabh Misra OUTL(atgep, ATGE_HDPX_CFG,
2133015a6ef6SSaurabh Misra ((HDPX_CFG_LCOL_DEFAULT << HDPX_CFG_LCOL_SHIFT) &
2134015a6ef6SSaurabh Misra HDPX_CFG_LCOL_MASK) |
2135015a6ef6SSaurabh Misra ((HDPX_CFG_RETRY_DEFAULT << HDPX_CFG_RETRY_SHIFT) &
2136015a6ef6SSaurabh Misra HDPX_CFG_RETRY_MASK) | HDPX_CFG_EXC_DEF_EN |
2137015a6ef6SSaurabh Misra ((HDPX_CFG_ABEBT_DEFAULT << HDPX_CFG_ABEBT_SHIFT) &
2138015a6ef6SSaurabh Misra HDPX_CFG_ABEBT_MASK) |
2139015a6ef6SSaurabh Misra ((HDPX_CFG_JAMIPG_DEFAULT << HDPX_CFG_JAMIPG_SHIFT) &
2140015a6ef6SSaurabh Misra HDPX_CFG_JAMIPG_MASK));
2141015a6ef6SSaurabh Misra
2142015a6ef6SSaurabh Misra /*
2143015a6ef6SSaurabh Misra * Configure jumbo frame.
2144015a6ef6SSaurabh Misra */
2145*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
2146*5e8715b9SGary Mills case ATGE_CHIP_L1E:
2147*5e8715b9SGary Mills if (atgep->atge_flags & ATGE_FLAG_JUMBO) {
2148015a6ef6SSaurabh Misra
2149015a6ef6SSaurabh Misra if (atgep->atge_mtu < ETHERMTU)
2150015a6ef6SSaurabh Misra reg = atgep->atge_max_frame_size;
2151015a6ef6SSaurabh Misra else if (atgep->atge_mtu < 6 * 1024)
2152015a6ef6SSaurabh Misra reg = (atgep->atge_max_frame_size * 2) / 3;
2153015a6ef6SSaurabh Misra else
2154015a6ef6SSaurabh Misra reg = atgep->atge_max_frame_size / 2;
2155015a6ef6SSaurabh Misra
2156015a6ef6SSaurabh Misra OUTL(atgep, L1E_TX_JUMBO_THRESH,
2157015a6ef6SSaurabh Misra ROUNDUP(reg, TX_JUMBO_THRESH_UNIT) >>
2158015a6ef6SSaurabh Misra TX_JUMBO_THRESH_UNIT_SHIFT);
2159015a6ef6SSaurabh Misra }
2160*5e8715b9SGary Mills break;
2161*5e8715b9SGary Mills case ATGE_CHIP_L1:
2162*5e8715b9SGary Mills fsize = ROUNDUP(atgep->atge_max_frame_size, sizeof (uint64_t));
2163*5e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_JUMBO_CFG,
2164*5e8715b9SGary Mills (((fsize / sizeof (uint64_t)) <<
2165*5e8715b9SGary Mills RXQ_JUMBO_CFG_SZ_THRESH_SHIFT) &
2166*5e8715b9SGary Mills RXQ_JUMBO_CFG_SZ_THRESH_MASK) |
2167*5e8715b9SGary Mills ((RXQ_JUMBO_CFG_LKAH_DEFAULT <<
2168*5e8715b9SGary Mills RXQ_JUMBO_CFG_LKAH_SHIFT) & RXQ_JUMBO_CFG_LKAH_MASK) |
2169*5e8715b9SGary Mills ((ATGE_USECS(8) << RXQ_JUMBO_CFG_RRD_TIMER_SHIFT) &
2170*5e8715b9SGary Mills RXQ_JUMBO_CFG_RRD_TIMER_MASK));
2171*5e8715b9SGary Mills break;
2172*5e8715b9SGary Mills case ATGE_CHIP_L1C:
2173*5e8715b9SGary Mills break;
2174*5e8715b9SGary Mills }
2175015a6ef6SSaurabh Misra
2176015a6ef6SSaurabh Misra /*
2177015a6ef6SSaurabh Misra * Configure flow-control parameters.
2178015a6ef6SSaurabh Misra */
2179*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
2180*5e8715b9SGary Mills case ATGE_CHIP_L1E:
2181*5e8715b9SGary Mills case ATGE_CHIP_L1:
2182015a6ef6SSaurabh Misra if ((atgep->atge_flags & ATGE_FLAG_PCIE) != 0) {
2183015a6ef6SSaurabh Misra /*
2184015a6ef6SSaurabh Misra * Some hardware version require this magic.
2185015a6ef6SSaurabh Misra */
2186*5e8715b9SGary Mills OUTL(atgep, ATGE_LTSSM_ID_CFG, 0x6500);
2187015a6ef6SSaurabh Misra reg = INL(atgep, 0x1008);
2188015a6ef6SSaurabh Misra OUTL(atgep, 0x1008, reg | 0x8000);
2189015a6ef6SSaurabh Misra }
2190*5e8715b9SGary Mills break;
2191*5e8715b9SGary Mills case ATGE_CHIP_L1C:
2192*5e8715b9SGary Mills break;
2193*5e8715b9SGary Mills }
2194015a6ef6SSaurabh Misra
2195015a6ef6SSaurabh Misra /*
2196015a6ef6SSaurabh Misra * These are all magic parameters which came from FreeBSD.
2197015a6ef6SSaurabh Misra */
2198*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
2199*5e8715b9SGary Mills case ATGE_CHIP_L1E:
2200*5e8715b9SGary Mills reg = INL(atgep, L1E_SRAM_RX_FIFO_LEN);
2201*5e8715b9SGary Mills rxf_hi = (reg * 4) / 5;
2202*5e8715b9SGary Mills rxf_lo = reg/ 5;
2203*5e8715b9SGary Mills
2204*5e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_FIFO_PAUSE_THRESH,
2205*5e8715b9SGary Mills ((rxf_lo << RXQ_FIFO_PAUSE_THRESH_LO_SHIFT) &
2206*5e8715b9SGary Mills RXQ_FIFO_PAUSE_THRESH_LO_MASK) |
2207*5e8715b9SGary Mills ((rxf_hi << RXQ_FIFO_PAUSE_THRESH_HI_SHIFT) &
2208*5e8715b9SGary Mills RXQ_FIFO_PAUSE_THRESH_HI_MASK));
2209*5e8715b9SGary Mills break;
2210*5e8715b9SGary Mills case ATGE_CHIP_L1:
22110eb090a7SSaurabh Misra switch (atgep->atge_chip_rev) {
22120eb090a7SSaurabh Misra case 0x8001:
22130eb090a7SSaurabh Misra case 0x9001:
22140eb090a7SSaurabh Misra case 0x9002:
22150eb090a7SSaurabh Misra case 0x9003:
22160eb090a7SSaurabh Misra rxf_hi = L1_RX_RING_CNT / 16;
22170eb090a7SSaurabh Misra rxf_lo = (L1_RX_RING_CNT * 7) / 8;
22180eb090a7SSaurabh Misra rrd_hi = (L1_RR_RING_CNT * 7) / 8;
22190eb090a7SSaurabh Misra rrd_lo = L1_RR_RING_CNT / 16;
22200eb090a7SSaurabh Misra break;
22210eb090a7SSaurabh Misra default:
22220eb090a7SSaurabh Misra reg = INL(atgep, L1_SRAM_RX_FIFO_LEN);
22230eb090a7SSaurabh Misra rxf_lo = reg / 16;
22240eb090a7SSaurabh Misra if (rxf_lo > 192)
22250eb090a7SSaurabh Misra rxf_lo = 192;
22260eb090a7SSaurabh Misra rxf_hi = (reg * 7) / 8;
22270eb090a7SSaurabh Misra if (rxf_hi < rxf_lo)
22280eb090a7SSaurabh Misra rxf_hi = rxf_lo + 16;
22290eb090a7SSaurabh Misra reg = INL(atgep, L1_SRAM_RRD_LEN);
22300eb090a7SSaurabh Misra rrd_lo = reg / 8;
22310eb090a7SSaurabh Misra rrd_hi = (reg * 7) / 8;
22320eb090a7SSaurabh Misra if (rrd_lo > 2)
22330eb090a7SSaurabh Misra rrd_lo = 2;
22340eb090a7SSaurabh Misra if (rrd_hi < rrd_lo)
22350eb090a7SSaurabh Misra rrd_hi = rrd_lo + 3;
22360eb090a7SSaurabh Misra break;
22370eb090a7SSaurabh Misra }
22380eb090a7SSaurabh Misra
22390eb090a7SSaurabh Misra OUTL(atgep, ATGE_RXQ_FIFO_PAUSE_THRESH,
22400eb090a7SSaurabh Misra ((rxf_lo << RXQ_FIFO_PAUSE_THRESH_LO_SHIFT) &
22410eb090a7SSaurabh Misra RXQ_FIFO_PAUSE_THRESH_LO_MASK) |
22420eb090a7SSaurabh Misra ((rxf_hi << RXQ_FIFO_PAUSE_THRESH_HI_SHIFT) &
22430eb090a7SSaurabh Misra RXQ_FIFO_PAUSE_THRESH_HI_MASK));
22440eb090a7SSaurabh Misra
22450eb090a7SSaurabh Misra OUTL(atgep, L1_RXQ_RRD_PAUSE_THRESH,
22460eb090a7SSaurabh Misra ((rrd_lo << RXQ_RRD_PAUSE_THRESH_LO_SHIFT) &
22470eb090a7SSaurabh Misra RXQ_RRD_PAUSE_THRESH_LO_MASK) |
22480eb090a7SSaurabh Misra ((rrd_hi << RXQ_RRD_PAUSE_THRESH_HI_SHIFT) &
22490eb090a7SSaurabh Misra RXQ_RRD_PAUSE_THRESH_HI_MASK));
2250*5e8715b9SGary Mills break;
2251*5e8715b9SGary Mills case ATGE_CHIP_L1C:
2252*5e8715b9SGary Mills switch (ATGE_DID(atgep)) {
2253*5e8715b9SGary Mills case ATGE_CHIP_AR8151V2_DEV_ID:
2254*5e8715b9SGary Mills case ATGE_CHIP_AR8152V1_DEV_ID:
2255*5e8715b9SGary Mills OUTL(atgep, ATGE_SERDES_LOCK,
2256*5e8715b9SGary Mills INL(atgep, ATGE_SERDES_LOCK) |
2257*5e8715b9SGary Mills SERDES_MAC_CLK_SLOWDOWN |
2258*5e8715b9SGary Mills SERDES_PHY_CLK_SLOWDOWN);
2259*5e8715b9SGary Mills break;
2260*5e8715b9SGary Mills case ATGE_CHIP_L1CG_DEV_ID:
2261*5e8715b9SGary Mills case ATGE_CHIP_L1CF_DEV_ID:
2262*5e8715b9SGary Mills /*
2263*5e8715b9SGary Mills * Configure flow control parameters.
2264*5e8715b9SGary Mills * XON : 80% of Rx FIFO
2265*5e8715b9SGary Mills * XOFF : 30% of Rx FIFO
2266*5e8715b9SGary Mills */
2267*5e8715b9SGary Mills reg = INL(atgep, L1C_SRAM_RX_FIFO_LEN);
2268*5e8715b9SGary Mills rxf_hi = (reg * 8) / 10;
2269*5e8715b9SGary Mills rxf_lo = (reg * 3) / 10;
2270015a6ef6SSaurabh Misra
2271015a6ef6SSaurabh Misra OUTL(atgep, ATGE_RXQ_FIFO_PAUSE_THRESH,
2272015a6ef6SSaurabh Misra ((rxf_lo << RXQ_FIFO_PAUSE_THRESH_LO_SHIFT) &
2273015a6ef6SSaurabh Misra RXQ_FIFO_PAUSE_THRESH_LO_MASK) |
2274015a6ef6SSaurabh Misra ((rxf_hi << RXQ_FIFO_PAUSE_THRESH_HI_SHIFT) &
2275015a6ef6SSaurabh Misra RXQ_FIFO_PAUSE_THRESH_HI_MASK));
2276*5e8715b9SGary Mills break;
2277*5e8715b9SGary Mills }
2278*5e8715b9SGary Mills break;
2279015a6ef6SSaurabh Misra }
2280015a6ef6SSaurabh Misra
2281*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
2282*5e8715b9SGary Mills case ATGE_CHIP_L1E:
2283015a6ef6SSaurabh Misra /* Configure RxQ. */
2284015a6ef6SSaurabh Misra reg = RXQ_CFG_ALIGN_32 | RXQ_CFG_CUT_THROUGH_ENB |
2285015a6ef6SSaurabh Misra RXQ_CFG_IPV6_CSUM_VERIFY | RXQ_CFG_ENB;
2286015a6ef6SSaurabh Misra OUTL(atgep, ATGE_RXQ_CFG, reg);
2287015a6ef6SSaurabh Misra /*
2288015a6ef6SSaurabh Misra * Configure TxQ.
2289015a6ef6SSaurabh Misra */
2290015a6ef6SSaurabh Misra reg = (128 <<
2291015a6ef6SSaurabh Misra (atgep->atge_dma_rd_burst >> DMA_CFG_RD_BURST_SHIFT)) <<
2292015a6ef6SSaurabh Misra TXQ_CFG_TX_FIFO_BURST_SHIFT;
2293015a6ef6SSaurabh Misra
2294015a6ef6SSaurabh Misra reg |= (TXQ_CFG_TPD_BURST_DEFAULT << TXQ_CFG_TPD_BURST_SHIFT) &
2295015a6ef6SSaurabh Misra TXQ_CFG_TPD_BURST_MASK;
2296015a6ef6SSaurabh Misra
2297015a6ef6SSaurabh Misra reg |= TXQ_CFG_ENHANCED_MODE | TXQ_CFG_ENB;
2298015a6ef6SSaurabh Misra
2299015a6ef6SSaurabh Misra OUTL(atgep, ATGE_TXQ_CFG, reg);
2300015a6ef6SSaurabh Misra /* Disable RSS. */
2301015a6ef6SSaurabh Misra OUTL(atgep, L1E_RSS_IDT_TABLE0, 0);
2302015a6ef6SSaurabh Misra OUTL(atgep, L1E_RSS_CPU, 0);
2303015a6ef6SSaurabh Misra /*
2304015a6ef6SSaurabh Misra * Configure DMA parameters.
2305015a6ef6SSaurabh Misra */
2306015a6ef6SSaurabh Misra /*
2307015a6ef6SSaurabh Misra * Don't use Tx CMB. It is known to cause RRS update failure
2308015a6ef6SSaurabh Misra * under certain circumstances. Typical phenomenon of the
2309015a6ef6SSaurabh Misra * issue would be unexpected sequence number encountered in
2310015a6ef6SSaurabh Misra * Rx handler. Hence we don't set DMA_CFG_TXCMB_ENB.
2311015a6ef6SSaurabh Misra */
2312015a6ef6SSaurabh Misra OUTL(atgep, ATGE_DMA_CFG,
2313015a6ef6SSaurabh Misra DMA_CFG_OUT_ORDER | DMA_CFG_RD_REQ_PRI | DMA_CFG_RCB_64 |
2314015a6ef6SSaurabh Misra atgep->atge_dma_rd_burst | atgep->atge_dma_wr_burst |
2315015a6ef6SSaurabh Misra DMA_CFG_RXCMB_ENB |
2316015a6ef6SSaurabh Misra ((DMA_CFG_RD_DELAY_CNT_DEFAULT <<
2317015a6ef6SSaurabh Misra DMA_CFG_RD_DELAY_CNT_SHIFT) & DMA_CFG_RD_DELAY_CNT_MASK) |
2318015a6ef6SSaurabh Misra ((DMA_CFG_WR_DELAY_CNT_DEFAULT <<
2319015a6ef6SSaurabh Misra DMA_CFG_WR_DELAY_CNT_SHIFT) & DMA_CFG_WR_DELAY_CNT_MASK));
2320015a6ef6SSaurabh Misra /*
23210eb090a7SSaurabh Misra * Enable CMB/SMB timer.
2322015a6ef6SSaurabh Misra */
2323*5e8715b9SGary Mills OUTL(atgep, L1E_SMB_STAT_TIMER, 100000);
2324*5e8715b9SGary Mills atge_l1e_clear_stats(atgep);
2325*5e8715b9SGary Mills break;
2326*5e8715b9SGary Mills case ATGE_CHIP_L1:
2327*5e8715b9SGary Mills /* Configure RxQ. */
2328*5e8715b9SGary Mills reg =
2329*5e8715b9SGary Mills ((RXQ_CFG_RD_BURST_DEFAULT << RXQ_CFG_RD_BURST_SHIFT) &
2330*5e8715b9SGary Mills RXQ_CFG_RD_BURST_MASK) |
2331*5e8715b9SGary Mills ((RXQ_CFG_RRD_BURST_THRESH_DEFAULT <<
2332*5e8715b9SGary Mills RXQ_CFG_RRD_BURST_THRESH_SHIFT) &
2333*5e8715b9SGary Mills RXQ_CFG_RRD_BURST_THRESH_MASK) |
2334*5e8715b9SGary Mills ((RXQ_CFG_RD_PREF_MIN_IPG_DEFAULT <<
2335*5e8715b9SGary Mills RXQ_CFG_RD_PREF_MIN_IPG_SHIFT) &
2336*5e8715b9SGary Mills RXQ_CFG_RD_PREF_MIN_IPG_MASK) |
2337*5e8715b9SGary Mills RXQ_CFG_CUT_THROUGH_ENB | RXQ_CFG_ENB;
2338*5e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_CFG, reg);
2339*5e8715b9SGary Mills /*
2340*5e8715b9SGary Mills * Configure TxQ.
2341*5e8715b9SGary Mills */
2342*5e8715b9SGary Mills reg =
2343*5e8715b9SGary Mills (((TXQ_CFG_TPD_BURST_DEFAULT << TXQ_CFG_TPD_BURST_SHIFT) &
2344*5e8715b9SGary Mills TXQ_CFG_TPD_BURST_MASK) |
2345*5e8715b9SGary Mills ((TXQ_CFG_TX_FIFO_BURST_DEFAULT <<
2346*5e8715b9SGary Mills TXQ_CFG_TX_FIFO_BURST_SHIFT) &
2347*5e8715b9SGary Mills TXQ_CFG_TX_FIFO_BURST_MASK) |
2348*5e8715b9SGary Mills ((TXQ_CFG_TPD_FETCH_DEFAULT <<
2349*5e8715b9SGary Mills TXQ_CFG_TPD_FETCH_THRESH_SHIFT) &
2350*5e8715b9SGary Mills TXQ_CFG_TPD_FETCH_THRESH_MASK) |
2351*5e8715b9SGary Mills TXQ_CFG_ENB);
2352*5e8715b9SGary Mills OUTL(atgep, ATGE_TXQ_CFG, reg);
2353*5e8715b9SGary Mills /* Jumbo frames */
2354*5e8715b9SGary Mills OUTL(atgep, L1_TX_JUMBO_TPD_TH_IPG,
2355*5e8715b9SGary Mills (((fsize / sizeof (uint64_t) << TX_JUMBO_TPD_TH_SHIFT)) &
2356*5e8715b9SGary Mills TX_JUMBO_TPD_TH_MASK) |
2357*5e8715b9SGary Mills ((TX_JUMBO_TPD_IPG_DEFAULT << TX_JUMBO_TPD_IPG_SHIFT) &
2358*5e8715b9SGary Mills TX_JUMBO_TPD_IPG_MASK));
2359*5e8715b9SGary Mills /*
2360*5e8715b9SGary Mills * Configure DMA parameters.
2361*5e8715b9SGary Mills */
2362*5e8715b9SGary Mills OUTL(atgep, ATGE_DMA_CFG,
2363*5e8715b9SGary Mills DMA_CFG_ENH_ORDER | DMA_CFG_RCB_64 |
2364*5e8715b9SGary Mills atgep->atge_dma_rd_burst | DMA_CFG_RD_ENB |
2365*5e8715b9SGary Mills atgep->atge_dma_wr_burst | DMA_CFG_WR_ENB);
2366*5e8715b9SGary Mills
2367*5e8715b9SGary Mills /* Configure CMB DMA write threshold. */
2368*5e8715b9SGary Mills OUTL(atgep, L1_CMB_WR_THRESH,
2369*5e8715b9SGary Mills ((CMB_WR_THRESH_RRD_DEFAULT << CMB_WR_THRESH_RRD_SHIFT) &
2370*5e8715b9SGary Mills CMB_WR_THRESH_RRD_MASK) |
2371*5e8715b9SGary Mills ((CMB_WR_THRESH_TPD_DEFAULT << CMB_WR_THRESH_TPD_SHIFT) &
2372*5e8715b9SGary Mills CMB_WR_THRESH_TPD_MASK));
2373*5e8715b9SGary Mills /*
2374*5e8715b9SGary Mills * Enable CMB/SMB timer.
2375*5e8715b9SGary Mills */
23760eb090a7SSaurabh Misra /* Set CMB/SMB timer and enable them. */
23770eb090a7SSaurabh Misra OUTL(atgep, L1_CMB_WR_TIMER,
23780eb090a7SSaurabh Misra ((ATGE_USECS(2) << CMB_WR_TIMER_TX_SHIFT) &
23790eb090a7SSaurabh Misra CMB_WR_TIMER_TX_MASK) |
23800eb090a7SSaurabh Misra ((ATGE_USECS(2) << CMB_WR_TIMER_RX_SHIFT) &
23810eb090a7SSaurabh Misra CMB_WR_TIMER_RX_MASK));
23820eb090a7SSaurabh Misra
23830eb090a7SSaurabh Misra /* Request SMB updates for every seconds. */
23840eb090a7SSaurabh Misra OUTL(atgep, L1_SMB_TIMER, ATGE_USECS(1000 * 1000));
23850eb090a7SSaurabh Misra OUTL(atgep, L1_CSMB_CTRL,
23860eb090a7SSaurabh Misra CSMB_CTRL_SMB_ENB | CSMB_CTRL_CMB_ENB);
2387*5e8715b9SGary Mills break;
2388*5e8715b9SGary Mills case ATGE_CHIP_L1C:
2389*5e8715b9SGary Mills /* Configure RxQ. */
2390*5e8715b9SGary Mills reg =
2391*5e8715b9SGary Mills RXQ_CFG_RD_BURST_DEFAULT << L1C_RXQ_CFG_RD_BURST_SHIFT |
2392*5e8715b9SGary Mills RXQ_CFG_IPV6_CSUM_VERIFY | RXQ_CFG_ENB;
2393*5e8715b9SGary Mills if ((atgep->atge_flags & ATGE_FLAG_ASPM_MON) != 0)
2394*5e8715b9SGary Mills reg |= RXQ_CFG_ASPM_THROUGHPUT_LIMIT_1M;
2395*5e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_CFG, reg);
2396*5e8715b9SGary Mills /*
2397*5e8715b9SGary Mills * Configure TxQ.
2398*5e8715b9SGary Mills */
2399*5e8715b9SGary Mills reg = (128 <<
2400*5e8715b9SGary Mills (atgep->atge_dma_rd_burst >> DMA_CFG_RD_BURST_SHIFT)) <<
2401*5e8715b9SGary Mills TXQ_CFG_TX_FIFO_BURST_SHIFT;
2402*5e8715b9SGary Mills
2403*5e8715b9SGary Mills switch (ATGE_DID(atgep)) {
2404*5e8715b9SGary Mills case ATGE_CHIP_AR8152V2_DEV_ID:
2405*5e8715b9SGary Mills case ATGE_CHIP_AR8152V1_DEV_ID:
2406*5e8715b9SGary Mills reg >>= 1;
2407*5e8715b9SGary Mills break;
2408015a6ef6SSaurabh Misra }
2409015a6ef6SSaurabh Misra
2410*5e8715b9SGary Mills reg |= (L1C_TXQ_CFG_TPD_BURST_DEFAULT <<
2411*5e8715b9SGary Mills TXQ_CFG_TPD_BURST_SHIFT) & TXQ_CFG_TPD_BURST_MASK;
2412*5e8715b9SGary Mills
2413*5e8715b9SGary Mills reg |= TXQ_CFG_ENHANCED_MODE | TXQ_CFG_ENB;
2414*5e8715b9SGary Mills
2415*5e8715b9SGary Mills OUTL(atgep, L1C_TXQ_CFG, reg);
2416*5e8715b9SGary Mills /* Disable RSS until I understand L1C/L2C's RSS logic. */
2417*5e8715b9SGary Mills OUTL(atgep, L1C_RSS_IDT_TABLE0, 0xe4e4e4e4);
2418*5e8715b9SGary Mills OUTL(atgep, L1C_RSS_CPU, 0);
2419*5e8715b9SGary Mills /*
2420*5e8715b9SGary Mills * Configure DMA parameters.
2421*5e8715b9SGary Mills */
2422*5e8715b9SGary Mills OUTL(atgep, ATGE_DMA_CFG,
2423*5e8715b9SGary Mills DMA_CFG_SMB_DIS |
2424*5e8715b9SGary Mills DMA_CFG_OUT_ORDER | DMA_CFG_RD_REQ_PRI | DMA_CFG_RCB_64 |
2425*5e8715b9SGary Mills DMA_CFG_RD_DELAY_CNT_DEFAULT << DMA_CFG_RD_DELAY_CNT_SHIFT |
2426*5e8715b9SGary Mills DMA_CFG_WR_DELAY_CNT_DEFAULT << DMA_CFG_WR_DELAY_CNT_SHIFT |
2427*5e8715b9SGary Mills
2428*5e8715b9SGary Mills atgep->atge_dma_rd_burst | DMA_CFG_RD_ENB |
2429*5e8715b9SGary Mills atgep->atge_dma_wr_burst | DMA_CFG_WR_ENB);
2430*5e8715b9SGary Mills /* Configure CMB DMA write threshold not required. */
2431*5e8715b9SGary Mills /* Set CMB/SMB timer and enable them not required. */
2432*5e8715b9SGary Mills break;
2433*5e8715b9SGary Mills }
24340eb090a7SSaurabh Misra
2435015a6ef6SSaurabh Misra /*
2436015a6ef6SSaurabh Misra * Disable all WOL bits as WOL can interfere normal Rx
2437015a6ef6SSaurabh Misra * operation.
2438015a6ef6SSaurabh Misra */
2439015a6ef6SSaurabh Misra OUTL(atgep, ATGE_WOL_CFG, 0);
2440015a6ef6SSaurabh Misra
2441015a6ef6SSaurabh Misra /*
2442015a6ef6SSaurabh Misra * Configure Tx/Rx MACs.
2443015a6ef6SSaurabh Misra * - Auto-padding for short frames.
2444015a6ef6SSaurabh Misra * - Enable CRC generation.
2445015a6ef6SSaurabh Misra *
2446015a6ef6SSaurabh Misra * Start with full-duplex/1000Mbps media. Actual reconfiguration
2447015a6ef6SSaurabh Misra * of MAC is followed after link establishment.
2448015a6ef6SSaurabh Misra */
2449015a6ef6SSaurabh Misra reg = (ATGE_CFG_TX_CRC_ENB | ATGE_CFG_TX_AUTO_PAD |
2450015a6ef6SSaurabh Misra ATGE_CFG_FULL_DUPLEX |
2451015a6ef6SSaurabh Misra ((ATGE_CFG_PREAMBLE_DEFAULT << ATGE_CFG_PREAMBLE_SHIFT) &
2452015a6ef6SSaurabh Misra ATGE_CFG_PREAMBLE_MASK));
2453015a6ef6SSaurabh Misra
2454*5e8715b9SGary Mills /*
2455*5e8715b9SGary Mills * AR813x/AR815x always does checksum computation regardless
2456*5e8715b9SGary Mills * of MAC_CFG_RXCSUM_ENB bit. Also the controller is known to
2457*5e8715b9SGary Mills * have bug in protocol field in Rx return structure so
2458*5e8715b9SGary Mills * these controllers can't handle fragmented frames. Disable
2459*5e8715b9SGary Mills * Rx checksum offloading until there is a newer controller
2460*5e8715b9SGary Mills * that has sane implementation.
2461*5e8715b9SGary Mills */
2462*5e8715b9SGary Mills switch (ATGE_DID(atgep)) {
2463*5e8715b9SGary Mills case ATGE_CHIP_AR8151V2_DEV_ID:
2464*5e8715b9SGary Mills case ATGE_CHIP_AR8151V1_DEV_ID:
2465*5e8715b9SGary Mills case ATGE_CHIP_AR8152V2_DEV_ID:
2466*5e8715b9SGary Mills reg |= ATGE_CFG_HASH_ALG_CRC32 | ATGE_CFG_SPEED_MODE_SW;
2467*5e8715b9SGary Mills break;
2468*5e8715b9SGary Mills }
2469*5e8715b9SGary Mills
2470015a6ef6SSaurabh Misra if ((atgep->atge_flags & ATGE_FLAG_FASTETHER) != 0) {
2471015a6ef6SSaurabh Misra reg |= ATGE_CFG_SPEED_10_100;
2472015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() Fast Ethernet", atgep->atge_name, __func__));
2473015a6ef6SSaurabh Misra } else {
2474015a6ef6SSaurabh Misra reg |= ATGE_CFG_SPEED_1000;
2475015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() 1G speed", atgep->atge_name, __func__));
2476015a6ef6SSaurabh Misra }
2477*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
2478*5e8715b9SGary Mills case ATGE_CHIP_L1C:
2479*5e8715b9SGary Mills reg |= L1C_CFG_SINGLE_PAUSE_ENB;
2480*5e8715b9SGary Mills break;
2481*5e8715b9SGary Mills }
2482015a6ef6SSaurabh Misra
2483015a6ef6SSaurabh Misra OUTL(atgep, ATGE_MAC_CFG, reg);
2484015a6ef6SSaurabh Misra
2485015a6ef6SSaurabh Misra atgep->atge_chip_state |= ATGE_CHIP_RUNNING;
2486015a6ef6SSaurabh Misra
2487015a6ef6SSaurabh Misra /*
2488015a6ef6SSaurabh Misra * Set up the receive filter.
2489015a6ef6SSaurabh Misra */
2490015a6ef6SSaurabh Misra atge_rxfilter(atgep);
2491015a6ef6SSaurabh Misra
2492015a6ef6SSaurabh Misra /*
2493015a6ef6SSaurabh Misra * Acknowledge all pending interrupts and clear it.
2494015a6ef6SSaurabh Misra */
2495*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
2496*5e8715b9SGary Mills case ATGE_CHIP_L1E:
2497015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_MASK, L1E_INTRS);
2498015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_STATUS, 0xFFFFFFFF);
2499015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_STATUS, 0);
2500*5e8715b9SGary Mills break;
2501*5e8715b9SGary Mills case ATGE_CHIP_L1:
2502*5e8715b9SGary Mills case ATGE_CHIP_L1C:
2503*5e8715b9SGary Mills OUTL(atgep, ATGE_INTR_STATUS, 0);
2504*5e8715b9SGary Mills OUTL(atgep, ATGE_INTR_MASK, atgep->atge_intrs);
2505*5e8715b9SGary Mills break;
25060eb090a7SSaurabh Misra }
2507015a6ef6SSaurabh Misra
2508015a6ef6SSaurabh Misra atge_mac_config(atgep);
2509015a6ef6SSaurabh Misra
2510015a6ef6SSaurabh Misra ATGE_DB(("%s: %s() device started", atgep->atge_name, __func__));
2511015a6ef6SSaurabh Misra }
2512015a6ef6SSaurabh Misra
2513015a6ef6SSaurabh Misra /*
2514015a6ef6SSaurabh Misra * Generic functions.
2515015a6ef6SSaurabh Misra */
2516015a6ef6SSaurabh Misra
2517015a6ef6SSaurabh Misra #define CRC32_POLY_BE 0x04c11db7
2518015a6ef6SSaurabh Misra uint32_t
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 */
2601*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
2602*5e8715b9SGary Mills case ATGE_CHIP_L1E:
2603015a6ef6SSaurabh Misra atge_l1e_gather_stats(atgep);
2604*5e8715b9SGary Mills break;
2605*5e8715b9SGary Mills case ATGE_CHIP_L1:
2606*5e8715b9SGary Mills case ATGE_CHIP_L1C:
2607*5e8715b9SGary Mills break;
2608015a6ef6SSaurabh Misra }
2609015a6ef6SSaurabh Misra
2610015a6ef6SSaurabh Misra /*
2611015a6ef6SSaurabh Misra * Disable interrupts.
2612015a6ef6SSaurabh Misra */
2613015a6ef6SSaurabh Misra atge_disable_intrs(atgep);
2614015a6ef6SSaurabh Misra
2615*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
2616*5e8715b9SGary Mills case ATGE_CHIP_L1E:
2617*5e8715b9SGary Mills /* Clear CTRL not required. */
2618*5e8715b9SGary Mills /* Stop DMA Engine not required. */
2619015a6ef6SSaurabh Misra /*
2620015a6ef6SSaurabh Misra * Disable queue processing.
2621015a6ef6SSaurabh Misra */
2622015a6ef6SSaurabh Misra /* Stop TxQ */
2623015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_TXQ_CFG);
2624015a6ef6SSaurabh Misra reg = reg & ~TXQ_CFG_ENB;
2625015a6ef6SSaurabh Misra OUTL(atgep, ATGE_TXQ_CFG, reg);
2626015a6ef6SSaurabh Misra /* Stop RxQ */
2627015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_RXQ_CFG);
2628015a6ef6SSaurabh Misra reg = reg & ~RXQ_CFG_ENB;
2629015a6ef6SSaurabh Misra OUTL(atgep, ATGE_RXQ_CFG, reg);
2630*5e8715b9SGary Mills /* Stop DMA */
2631015a6ef6SSaurabh Misra reg = INL(atgep, ATGE_DMA_CFG);
2632015a6ef6SSaurabh Misra reg = reg & ~(DMA_CFG_TXCMB_ENB | DMA_CFG_RXCMB_ENB);
2633015a6ef6SSaurabh Misra OUTL(atgep, ATGE_DMA_CFG, reg);
2634015a6ef6SSaurabh Misra drv_usecwait(1000);
2635015a6ef6SSaurabh Misra atge_l1e_stop_mac(atgep);
2636015a6ef6SSaurabh Misra OUTL(atgep, ATGE_INTR_STATUS, 0xFFFFFFFF);
2637*5e8715b9SGary Mills break;
2638*5e8715b9SGary Mills case ATGE_CHIP_L1:
2639*5e8715b9SGary Mills /* Clear CTRL. */
2640*5e8715b9SGary Mills OUTL(atgep, L1_CSMB_CTRL, 0);
2641*5e8715b9SGary Mills /* Stop DMA Engine */
2642*5e8715b9SGary Mills atge_l1_stop_tx_mac(atgep);
2643*5e8715b9SGary Mills atge_l1_stop_rx_mac(atgep);
2644*5e8715b9SGary Mills reg = INL(atgep, ATGE_DMA_CFG);
2645*5e8715b9SGary Mills reg &= ~(DMA_CFG_RD_ENB | DMA_CFG_WR_ENB);
2646*5e8715b9SGary Mills OUTL(atgep, ATGE_DMA_CFG, reg);
2647*5e8715b9SGary Mills /*
2648*5e8715b9SGary Mills * Disable queue processing.
2649*5e8715b9SGary Mills */
2650*5e8715b9SGary Mills /* Stop TxQ */
2651*5e8715b9SGary Mills reg = INL(atgep, ATGE_TXQ_CFG);
2652*5e8715b9SGary Mills reg = reg & ~TXQ_CFG_ENB;
2653*5e8715b9SGary Mills OUTL(atgep, ATGE_TXQ_CFG, reg);
2654*5e8715b9SGary Mills /* Stop RxQ */
2655*5e8715b9SGary Mills reg = INL(atgep, ATGE_RXQ_CFG);
2656*5e8715b9SGary Mills reg = reg & ~RXQ_CFG_ENB;
2657*5e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_CFG, reg);
2658*5e8715b9SGary Mills break;
2659*5e8715b9SGary Mills case ATGE_CHIP_L1C:
2660*5e8715b9SGary Mills /* Clear CTRL not required. */
2661*5e8715b9SGary Mills /* Stop DMA Engine */
2662*5e8715b9SGary Mills atge_l1c_stop_tx_mac(atgep);
2663*5e8715b9SGary Mills atge_l1c_stop_rx_mac(atgep);
2664*5e8715b9SGary Mills reg = INL(atgep, ATGE_DMA_CFG);
2665*5e8715b9SGary Mills reg &= ~(DMA_CFG_RD_ENB | DMA_CFG_WR_ENB);
2666*5e8715b9SGary Mills OUTL(atgep, ATGE_DMA_CFG, reg);
2667*5e8715b9SGary Mills /*
2668*5e8715b9SGary Mills * Disable queue processing.
2669*5e8715b9SGary Mills */
2670*5e8715b9SGary Mills /* Stop TxQ */
2671*5e8715b9SGary Mills reg = INL(atgep, L1C_TXQ_CFG);
2672*5e8715b9SGary Mills reg = reg & ~TXQ_CFG_ENB;
2673*5e8715b9SGary Mills OUTL(atgep, L1C_TXQ_CFG, reg);
2674*5e8715b9SGary Mills /* Stop RxQ */
2675*5e8715b9SGary Mills reg = INL(atgep, ATGE_RXQ_CFG);
2676*5e8715b9SGary Mills reg = reg & ~RXQ_CFG_ENB;
2677*5e8715b9SGary Mills OUTL(atgep, ATGE_RXQ_CFG, reg);
2678*5e8715b9SGary Mills break;
2679015a6ef6SSaurabh Misra }
2680015a6ef6SSaurabh Misra
2681015a6ef6SSaurabh Misra for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
2682015a6ef6SSaurabh Misra if ((reg = INL(atgep, ATGE_IDLE_STATUS)) == 0)
2683015a6ef6SSaurabh Misra break;
2684015a6ef6SSaurabh Misra drv_usecwait(10);
2685015a6ef6SSaurabh Misra }
2686015a6ef6SSaurabh Misra
2687015a6ef6SSaurabh Misra if (t == 0) {
2688015a6ef6SSaurabh Misra atge_error(atgep->atge_dip, "%s() stopping TX/RX MAC timeout",
2689015a6ef6SSaurabh Misra __func__);
2690015a6ef6SSaurabh Misra }
2691015a6ef6SSaurabh Misra }
2692015a6ef6SSaurabh Misra
2693015a6ef6SSaurabh Misra void
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 {
2703*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
2704*5e8715b9SGary Mills case ATGE_CHIP_L1E:
2705015a6ef6SSaurabh Misra atgep->atge_intrs = L1E_INTRS;
2706015a6ef6SSaurabh Misra atgep->atge_int_mod = ATGE_IM_TIMER_DEFAULT;
2707015a6ef6SSaurabh Misra
2708015a6ef6SSaurabh Misra atge_l1e_init_tx_ring(atgep);
2709015a6ef6SSaurabh Misra atge_l1e_init_rx_pages(atgep);
2710*5e8715b9SGary Mills break;
2711*5e8715b9SGary Mills case ATGE_CHIP_L1:
27120eb090a7SSaurabh Misra atgep->atge_intrs = L1_INTRS | INTR_GPHY | INTR_PHY_LINK_DOWN |
27130eb090a7SSaurabh Misra INTR_LINK_CHG;
27140eb090a7SSaurabh Misra atgep->atge_int_mod = ATGE_IM_TIMER_DEFAULT;
27150eb090a7SSaurabh Misra
27160eb090a7SSaurabh Misra atge_l1_init_tx_ring(atgep);
27170eb090a7SSaurabh Misra atge_l1_init_rx_ring(atgep);
27180eb090a7SSaurabh Misra atge_l1_init_rr_ring(atgep);
27190eb090a7SSaurabh Misra atge_l1_init_cmb(atgep);
27200eb090a7SSaurabh Misra atge_l1_init_smb(atgep);
2721*5e8715b9SGary Mills break;
2722*5e8715b9SGary Mills case ATGE_CHIP_L1C:
2723*5e8715b9SGary Mills atgep->atge_intrs = L1C_INTRS | L1C_INTR_GPHY |
2724*5e8715b9SGary Mills L1C_INTR_PHY_LINK_DOWN;
2725*5e8715b9SGary Mills atgep->atge_int_rx_mod = 400/2;
2726*5e8715b9SGary Mills atgep->atge_int_tx_mod = 2000/1;
2727*5e8715b9SGary Mills
2728*5e8715b9SGary Mills atge_l1c_init_tx_ring(atgep);
2729*5e8715b9SGary Mills atge_l1c_init_rx_ring(atgep);
2730*5e8715b9SGary Mills atge_l1c_init_rr_ring(atgep);
2731*5e8715b9SGary Mills atge_l1c_init_cmb(atgep);
2732*5e8715b9SGary Mills atge_l1c_init_smb(atgep);
2733*5e8715b9SGary Mills
2734*5e8715b9SGary Mills /* Enable all clocks. */
2735*5e8715b9SGary Mills OUTL(atgep, ATGE_CLK_GATING_CFG, 0);
2736*5e8715b9SGary Mills break;
2737015a6ef6SSaurabh Misra }
2738015a6ef6SSaurabh Misra }
2739015a6ef6SSaurabh Misra
2740015a6ef6SSaurabh Misra void
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;
2820*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
2821*5e8715b9SGary Mills case ATGE_CHIP_L1C:
2822*5e8715b9SGary Mills {
2823*5e8715b9SGary Mills l1c_tx_desc_t *txd;
2824*5e8715b9SGary Mills
2825*5e8715b9SGary Mills c += (sizeof (l1c_tx_desc_t) * start);
2826*5e8715b9SGary Mills txd = (l1c_tx_desc_t *)c;
2827*5e8715b9SGary Mills
2828*5e8715b9SGary Mills ATGE_PUT64(r->r_desc_ring, &txd->addr,
2829*5e8715b9SGary Mills r->r_buf_tbl[start]->cookie.dmac_laddress);
2830*5e8715b9SGary Mills
2831*5e8715b9SGary Mills ATGE_PUT32(r->r_desc_ring, &txd->len, L1C_TX_BYTES(pktlen));
2832*5e8715b9SGary Mills
2833*5e8715b9SGary Mills cflags |= L1C_TD_EOP;
2834*5e8715b9SGary Mills ATGE_PUT32(r->r_desc_ring, &txd->flags, cflags);
2835*5e8715b9SGary Mills break;
2836*5e8715b9SGary Mills }
2837*5e8715b9SGary Mills default:
2838*5e8715b9SGary Mills {
2839*5e8715b9SGary Mills atge_tx_desc_t *txd;
2840*5e8715b9SGary Mills
28410eb090a7SSaurabh Misra c += (sizeof (atge_tx_desc_t) * start);
28420eb090a7SSaurabh Misra txd = (atge_tx_desc_t *)c;
28430eb090a7SSaurabh Misra
28440eb090a7SSaurabh Misra ATGE_PUT64(r->r_desc_ring, &txd->addr,
28450eb090a7SSaurabh Misra r->r_buf_tbl[start]->cookie.dmac_laddress);
28460eb090a7SSaurabh Misra
28470eb090a7SSaurabh Misra ATGE_PUT32(r->r_desc_ring, &txd->len, ATGE_TX_BYTES(pktlen));
28480eb090a7SSaurabh Misra
28490eb090a7SSaurabh Misra cflags |= ATGE_TD_EOP;
28500eb090a7SSaurabh Misra ATGE_PUT32(r->r_desc_ring, &txd->flags, cflags);
2851*5e8715b9SGary Mills break;
2852*5e8715b9SGary Mills }
2853*5e8715b9SGary Mills }
28540eb090a7SSaurabh Misra /*
28550eb090a7SSaurabh Misra * Sync buffer first.
28560eb090a7SSaurabh Misra */
28570eb090a7SSaurabh Misra DMA_SYNC(r->r_buf_tbl[start], 0, pktlen, DDI_DMA_SYNC_FORDEV);
28580eb090a7SSaurabh Misra
28590eb090a7SSaurabh Misra /*
28600eb090a7SSaurabh Misra * Increment TX producer count by one.
28610eb090a7SSaurabh Misra */
28620eb090a7SSaurabh Misra ATGE_INC_SLOT(r->r_producer, ATGE_TX_RING_CNT);
28630eb090a7SSaurabh Misra
28640eb090a7SSaurabh Misra /*
28650eb090a7SSaurabh Misra * Sync descriptor table.
28660eb090a7SSaurabh Misra */
28670eb090a7SSaurabh Misra DMA_SYNC(r->r_desc_ring, 0, ATGE_TX_RING_SZ, DDI_DMA_SYNC_FORDEV);
28680eb090a7SSaurabh Misra
2869015a6ef6SSaurabh Misra /*
2870015a6ef6SSaurabh Misra * Program TX descriptor to send a packet.
2871015a6ef6SSaurabh Misra */
2872*5e8715b9SGary Mills switch (ATGE_MODEL(atgep)) {
2873*5e8715b9SGary Mills case ATGE_CHIP_L1E:
28740eb090a7SSaurabh Misra atge_l1e_send_packet(r);
2875*5e8715b9SGary Mills break;
2876*5e8715b9SGary Mills case ATGE_CHIP_L1:
28770eb090a7SSaurabh Misra atge_l1_send_packet(r);
2878*5e8715b9SGary Mills break;
2879*5e8715b9SGary Mills case ATGE_CHIP_L1C:
2880*5e8715b9SGary Mills atge_l1c_send_packet(r);
2881*5e8715b9SGary Mills break;
2882015a6ef6SSaurabh Misra }
2883015a6ef6SSaurabh Misra
28840eb090a7SSaurabh Misra r->r_atge->atge_opackets++;
28850eb090a7SSaurabh Misra r->r_atge->atge_obytes += pktlen;
28860eb090a7SSaurabh Misra
28870eb090a7SSaurabh Misra ATGE_DB(("%s: %s() pktlen : %d, avail_desc : %d, producer :%d, "
28880eb090a7SSaurabh Misra "consumer : %d", atgep->atge_name, __func__, pktlen,
28890eb090a7SSaurabh Misra r->r_avail_desc, r->r_producer, r->r_consumer));
28900eb090a7SSaurabh Misra
28910eb090a7SSaurabh Misra return (DDI_SUCCESS);
2892015a6ef6SSaurabh Misra }
2893015a6ef6SSaurabh Misra
2894015a6ef6SSaurabh Misra /*
2895015a6ef6SSaurabh Misra * Stream Information.
2896015a6ef6SSaurabh Misra */
2897015a6ef6SSaurabh Misra DDI_DEFINE_STREAM_OPS(atge_devops, nulldev, nulldev, atge_attach, atge_detach,
2898015a6ef6SSaurabh Misra nodev, NULL, D_MP, NULL, atge_quiesce);
2899015a6ef6SSaurabh Misra
2900015a6ef6SSaurabh Misra /*
2901015a6ef6SSaurabh Misra * Module linkage information.
2902015a6ef6SSaurabh Misra */
2903015a6ef6SSaurabh Misra static struct modldrv atge_modldrv = {
2904015a6ef6SSaurabh Misra &mod_driverops, /* Type of Module */
2905015a6ef6SSaurabh Misra "Atheros/Attansic Gb Ethernet", /* Description */
2906015a6ef6SSaurabh Misra &atge_devops /* drv_dev_ops */
2907015a6ef6SSaurabh Misra };
2908015a6ef6SSaurabh Misra
2909015a6ef6SSaurabh Misra static struct modlinkage atge_modlinkage = {
2910015a6ef6SSaurabh Misra MODREV_1, /* ml_rev */
2911015a6ef6SSaurabh Misra (void *)&atge_modldrv,
2912015a6ef6SSaurabh Misra NULL
2913015a6ef6SSaurabh Misra };
2914015a6ef6SSaurabh Misra
2915015a6ef6SSaurabh Misra /*
2916015a6ef6SSaurabh Misra * DDI Entry points.
2917015a6ef6SSaurabh Misra */
2918015a6ef6SSaurabh Misra int
_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