1*11353SSaurabh.Mishra@Sun.COM /*
2*11353SSaurabh.Mishra@Sun.COM * CDDL HEADER START
3*11353SSaurabh.Mishra@Sun.COM *
4*11353SSaurabh.Mishra@Sun.COM * The contents of this file are subject to the terms of the
5*11353SSaurabh.Mishra@Sun.COM * Common Development and Distribution License (the "License").
6*11353SSaurabh.Mishra@Sun.COM * You may not use this file except in compliance with the License.
7*11353SSaurabh.Mishra@Sun.COM *
8*11353SSaurabh.Mishra@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*11353SSaurabh.Mishra@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*11353SSaurabh.Mishra@Sun.COM * See the License for the specific language governing permissions
11*11353SSaurabh.Mishra@Sun.COM * and limitations under the License.
12*11353SSaurabh.Mishra@Sun.COM *
13*11353SSaurabh.Mishra@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*11353SSaurabh.Mishra@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*11353SSaurabh.Mishra@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*11353SSaurabh.Mishra@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*11353SSaurabh.Mishra@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*11353SSaurabh.Mishra@Sun.COM *
19*11353SSaurabh.Mishra@Sun.COM * CDDL HEADER END
20*11353SSaurabh.Mishra@Sun.COM */
21*11353SSaurabh.Mishra@Sun.COM
22*11353SSaurabh.Mishra@Sun.COM /*
23*11353SSaurabh.Mishra@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24*11353SSaurabh.Mishra@Sun.COM * Use is subject to license terms.
25*11353SSaurabh.Mishra@Sun.COM */
26*11353SSaurabh.Mishra@Sun.COM
27*11353SSaurabh.Mishra@Sun.COM #include <sys/types.h>
28*11353SSaurabh.Mishra@Sun.COM #include <sys/stream.h>
29*11353SSaurabh.Mishra@Sun.COM #include <sys/strsun.h>
30*11353SSaurabh.Mishra@Sun.COM #include <sys/stat.h>
31*11353SSaurabh.Mishra@Sun.COM #include <sys/modctl.h>
32*11353SSaurabh.Mishra@Sun.COM #include <sys/ethernet.h>
33*11353SSaurabh.Mishra@Sun.COM #include <sys/debug.h>
34*11353SSaurabh.Mishra@Sun.COM #include <sys/conf.h>
35*11353SSaurabh.Mishra@Sun.COM #include <sys/mii.h>
36*11353SSaurabh.Mishra@Sun.COM #include <sys/miiregs.h>
37*11353SSaurabh.Mishra@Sun.COM #include <sys/sysmacros.h>
38*11353SSaurabh.Mishra@Sun.COM #include <sys/dditypes.h>
39*11353SSaurabh.Mishra@Sun.COM #include <sys/ddi.h>
40*11353SSaurabh.Mishra@Sun.COM #include <sys/sunddi.h>
41*11353SSaurabh.Mishra@Sun.COM #include <sys/byteorder.h>
42*11353SSaurabh.Mishra@Sun.COM #include <sys/note.h>
43*11353SSaurabh.Mishra@Sun.COM #include <sys/vlan.h>
44*11353SSaurabh.Mishra@Sun.COM #include <sys/stream.h>
45*11353SSaurabh.Mishra@Sun.COM
46*11353SSaurabh.Mishra@Sun.COM #include "atge.h"
47*11353SSaurabh.Mishra@Sun.COM #include "atge_l1_reg.h"
48*11353SSaurabh.Mishra@Sun.COM #include "atge_cmn_reg.h"
49*11353SSaurabh.Mishra@Sun.COM
50*11353SSaurabh.Mishra@Sun.COM static ddi_dma_attr_t atge_l1_dma_attr_tx_desc = {
51*11353SSaurabh.Mishra@Sun.COM DMA_ATTR_V0, /* dma_attr_version */
52*11353SSaurabh.Mishra@Sun.COM 0, /* dma_attr_addr_lo */
53*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_addr_hi */
54*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_count_max */
55*11353SSaurabh.Mishra@Sun.COM L1_TX_RING_ALIGN, /* dma_attr_align */
56*11353SSaurabh.Mishra@Sun.COM 0x0000fffc, /* dma_attr_burstsizes */
57*11353SSaurabh.Mishra@Sun.COM 1, /* dma_attr_minxfer */
58*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_maxxfer */
59*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_seg */
60*11353SSaurabh.Mishra@Sun.COM 1, /* dma_attr_sgllen */
61*11353SSaurabh.Mishra@Sun.COM 1, /* dma_attr_granular */
62*11353SSaurabh.Mishra@Sun.COM 0 /* dma_attr_flags */
63*11353SSaurabh.Mishra@Sun.COM };
64*11353SSaurabh.Mishra@Sun.COM
65*11353SSaurabh.Mishra@Sun.COM static ddi_dma_attr_t atge_l1_dma_attr_rx_desc = {
66*11353SSaurabh.Mishra@Sun.COM DMA_ATTR_V0, /* dma_attr_version */
67*11353SSaurabh.Mishra@Sun.COM 0, /* dma_attr_addr_lo */
68*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_addr_hi */
69*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_count_max */
70*11353SSaurabh.Mishra@Sun.COM L1_RX_RING_ALIGN, /* dma_attr_align */
71*11353SSaurabh.Mishra@Sun.COM 0x0000fffc, /* dma_attr_burstsizes */
72*11353SSaurabh.Mishra@Sun.COM 1, /* dma_attr_minxfer */
73*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_maxxfer */
74*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_seg */
75*11353SSaurabh.Mishra@Sun.COM 1, /* dma_attr_sgllen */
76*11353SSaurabh.Mishra@Sun.COM 1, /* dma_attr_granular */
77*11353SSaurabh.Mishra@Sun.COM 0 /* dma_attr_flags */
78*11353SSaurabh.Mishra@Sun.COM };
79*11353SSaurabh.Mishra@Sun.COM
80*11353SSaurabh.Mishra@Sun.COM static ddi_dma_attr_t atge_l1_dma_attr_cmb = {
81*11353SSaurabh.Mishra@Sun.COM DMA_ATTR_V0, /* dma_attr_version */
82*11353SSaurabh.Mishra@Sun.COM 0, /* dma_attr_addr_lo */
83*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_addr_hi */
84*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_count_max */
85*11353SSaurabh.Mishra@Sun.COM L1_CMB_ALIGN, /* dma_attr_align */
86*11353SSaurabh.Mishra@Sun.COM 0x0000fffc, /* dma_attr_burstsizes */
87*11353SSaurabh.Mishra@Sun.COM 1, /* dma_attr_minxfer */
88*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_maxxfer */
89*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_seg */
90*11353SSaurabh.Mishra@Sun.COM 1, /* dma_attr_sgllen */
91*11353SSaurabh.Mishra@Sun.COM 1, /* dma_attr_granular */
92*11353SSaurabh.Mishra@Sun.COM 0 /* dma_attr_flags */
93*11353SSaurabh.Mishra@Sun.COM };
94*11353SSaurabh.Mishra@Sun.COM
95*11353SSaurabh.Mishra@Sun.COM static ddi_dma_attr_t atge_l1_dma_attr_smb = {
96*11353SSaurabh.Mishra@Sun.COM DMA_ATTR_V0, /* dma_attr_version */
97*11353SSaurabh.Mishra@Sun.COM 0, /* dma_attr_addr_lo */
98*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_addr_hi */
99*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_count_max */
100*11353SSaurabh.Mishra@Sun.COM L1_SMB_ALIGN, /* dma_attr_align */
101*11353SSaurabh.Mishra@Sun.COM 0x0000fffc, /* dma_attr_burstsizes */
102*11353SSaurabh.Mishra@Sun.COM 1, /* dma_attr_minxfer */
103*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_maxxfer */
104*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_seg */
105*11353SSaurabh.Mishra@Sun.COM 1, /* dma_attr_sgllen */
106*11353SSaurabh.Mishra@Sun.COM 1, /* dma_attr_granular */
107*11353SSaurabh.Mishra@Sun.COM 0 /* dma_attr_flags */
108*11353SSaurabh.Mishra@Sun.COM };
109*11353SSaurabh.Mishra@Sun.COM
110*11353SSaurabh.Mishra@Sun.COM static ddi_dma_attr_t atge_l1_dma_attr_rr = {
111*11353SSaurabh.Mishra@Sun.COM DMA_ATTR_V0, /* dma_attr_version */
112*11353SSaurabh.Mishra@Sun.COM 0, /* dma_attr_addr_lo */
113*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_addr_hi */
114*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_count_max */
115*11353SSaurabh.Mishra@Sun.COM L1_RR_RING_ALIGN, /* dma_attr_align */
116*11353SSaurabh.Mishra@Sun.COM 0x0000fffc, /* dma_attr_burstsizes */
117*11353SSaurabh.Mishra@Sun.COM 1, /* dma_attr_minxfer */
118*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_maxxfer */
119*11353SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_seg */
120*11353SSaurabh.Mishra@Sun.COM 1, /* dma_attr_sgllen */
121*11353SSaurabh.Mishra@Sun.COM 1, /* dma_attr_granular */
122*11353SSaurabh.Mishra@Sun.COM 0 /* dma_attr_flags */
123*11353SSaurabh.Mishra@Sun.COM };
124*11353SSaurabh.Mishra@Sun.COM
125*11353SSaurabh.Mishra@Sun.COM int
atge_l1_alloc_dma(atge_t * atgep)126*11353SSaurabh.Mishra@Sun.COM atge_l1_alloc_dma(atge_t *atgep)
127*11353SSaurabh.Mishra@Sun.COM {
128*11353SSaurabh.Mishra@Sun.COM atge_l1_data_t *l1;
129*11353SSaurabh.Mishra@Sun.COM atge_dma_t *dma;
130*11353SSaurabh.Mishra@Sun.COM int err;
131*11353SSaurabh.Mishra@Sun.COM
132*11353SSaurabh.Mishra@Sun.COM l1 = kmem_zalloc(sizeof (atge_l1_data_t), KM_SLEEP);
133*11353SSaurabh.Mishra@Sun.COM atgep->atge_private_data = l1;
134*11353SSaurabh.Mishra@Sun.COM
135*11353SSaurabh.Mishra@Sun.COM /*
136*11353SSaurabh.Mishra@Sun.COM * Allocate TX ring descriptor.
137*11353SSaurabh.Mishra@Sun.COM */
138*11353SSaurabh.Mishra@Sun.COM atgep->atge_tx_buf_len = atgep->atge_mtu +
139*11353SSaurabh.Mishra@Sun.COM sizeof (struct ether_header) + VLAN_TAGSZ + ETHERFCSL;
140*11353SSaurabh.Mishra@Sun.COM atgep->atge_tx_ring = kmem_alloc(sizeof (atge_ring_t), KM_SLEEP);
141*11353SSaurabh.Mishra@Sun.COM atgep->atge_tx_ring->r_atge = atgep;
142*11353SSaurabh.Mishra@Sun.COM atgep->atge_tx_ring->r_desc_ring = NULL;
143*11353SSaurabh.Mishra@Sun.COM dma = atge_alloc_a_dma_blk(atgep, &atge_l1_dma_attr_tx_desc,
144*11353SSaurabh.Mishra@Sun.COM ATGE_TX_RING_SZ, DDI_DMA_RDWR);
145*11353SSaurabh.Mishra@Sun.COM if (dma == NULL) {
146*11353SSaurabh.Mishra@Sun.COM atge_error(atgep->atge_dip, "DMA allocation failed for TX"
147*11353SSaurabh.Mishra@Sun.COM " desc ring");
148*11353SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
149*11353SSaurabh.Mishra@Sun.COM }
150*11353SSaurabh.Mishra@Sun.COM atgep->atge_tx_ring->r_desc_ring = dma;
151*11353SSaurabh.Mishra@Sun.COM
152*11353SSaurabh.Mishra@Sun.COM /*
153*11353SSaurabh.Mishra@Sun.COM * Allocate DMA buffers for TX ring.
154*11353SSaurabh.Mishra@Sun.COM */
155*11353SSaurabh.Mishra@Sun.COM err = atge_alloc_buffers(atgep->atge_tx_ring, ATGE_TX_RING_CNT,
156*11353SSaurabh.Mishra@Sun.COM atgep->atge_tx_buf_len, DDI_DMA_WRITE);
157*11353SSaurabh.Mishra@Sun.COM if (err != DDI_SUCCESS) {
158*11353SSaurabh.Mishra@Sun.COM atge_error(atgep->atge_dip, "DMA allocation failed for"
159*11353SSaurabh.Mishra@Sun.COM " TX Ring");
160*11353SSaurabh.Mishra@Sun.COM return (err);
161*11353SSaurabh.Mishra@Sun.COM }
162*11353SSaurabh.Mishra@Sun.COM
163*11353SSaurabh.Mishra@Sun.COM /*
164*11353SSaurabh.Mishra@Sun.COM * Allocate RX ring.
165*11353SSaurabh.Mishra@Sun.COM */
166*11353SSaurabh.Mishra@Sun.COM atgep->atge_rx_buf_len = atgep->atge_mtu +
167*11353SSaurabh.Mishra@Sun.COM sizeof (struct ether_header) + VLAN_TAGSZ + ETHERFCSL;
168*11353SSaurabh.Mishra@Sun.COM l1->atge_rx_ring = kmem_alloc(sizeof (atge_ring_t), KM_SLEEP);
169*11353SSaurabh.Mishra@Sun.COM l1->atge_rx_ring->r_atge = atgep;
170*11353SSaurabh.Mishra@Sun.COM l1->atge_rx_ring->r_desc_ring = NULL;
171*11353SSaurabh.Mishra@Sun.COM dma = atge_alloc_a_dma_blk(atgep, &atge_l1_dma_attr_rx_desc,
172*11353SSaurabh.Mishra@Sun.COM L1_RX_RING_SZ, DDI_DMA_RDWR);
173*11353SSaurabh.Mishra@Sun.COM if (dma == NULL) {
174*11353SSaurabh.Mishra@Sun.COM atge_error(atgep->atge_dip, "DMA allocation failed"
175*11353SSaurabh.Mishra@Sun.COM " for RX Ring");
176*11353SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
177*11353SSaurabh.Mishra@Sun.COM }
178*11353SSaurabh.Mishra@Sun.COM l1->atge_rx_ring->r_desc_ring = dma;
179*11353SSaurabh.Mishra@Sun.COM
180*11353SSaurabh.Mishra@Sun.COM /*
181*11353SSaurabh.Mishra@Sun.COM * Allocate DMA buffers for RX ring.
182*11353SSaurabh.Mishra@Sun.COM */
183*11353SSaurabh.Mishra@Sun.COM err = atge_alloc_buffers(l1->atge_rx_ring, L1_RX_RING_CNT,
184*11353SSaurabh.Mishra@Sun.COM atgep->atge_rx_buf_len, DDI_DMA_WRITE);
185*11353SSaurabh.Mishra@Sun.COM if (err != DDI_SUCCESS) {
186*11353SSaurabh.Mishra@Sun.COM atge_error(atgep->atge_dip, "DMA allocation failed for"
187*11353SSaurabh.Mishra@Sun.COM " RX buffers");
188*11353SSaurabh.Mishra@Sun.COM return (err);
189*11353SSaurabh.Mishra@Sun.COM }
190*11353SSaurabh.Mishra@Sun.COM
191*11353SSaurabh.Mishra@Sun.COM /*
192*11353SSaurabh.Mishra@Sun.COM * Allocate CMB used for fetching interrupt status data.
193*11353SSaurabh.Mishra@Sun.COM */
194*11353SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() L1_CMB_BLOCK_SZ : %x", atgep->atge_name,
195*11353SSaurabh.Mishra@Sun.COM __func__, L1_CMB_BLOCK_SZ));
196*11353SSaurabh.Mishra@Sun.COM
197*11353SSaurabh.Mishra@Sun.COM dma = atge_alloc_a_dma_blk(atgep, &atge_l1_dma_attr_cmb,
198*11353SSaurabh.Mishra@Sun.COM L1_CMB_BLOCK_SZ, DDI_DMA_RDWR);
199*11353SSaurabh.Mishra@Sun.COM l1->atge_l1_cmb = dma;
200*11353SSaurabh.Mishra@Sun.COM if (dma == NULL) {
201*11353SSaurabh.Mishra@Sun.COM atge_error(atgep->atge_dip, "DMA allocation failed for CMB");
202*11353SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
203*11353SSaurabh.Mishra@Sun.COM }
204*11353SSaurabh.Mishra@Sun.COM
205*11353SSaurabh.Mishra@Sun.COM /*
206*11353SSaurabh.Mishra@Sun.COM * RR ring (Return Ring for RX and TX).
207*11353SSaurabh.Mishra@Sun.COM */
208*11353SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() L1_RR_RING_SZ : %x", atgep->atge_name,
209*11353SSaurabh.Mishra@Sun.COM __func__, L1_RR_RING_SZ));
210*11353SSaurabh.Mishra@Sun.COM
211*11353SSaurabh.Mishra@Sun.COM dma = atge_alloc_a_dma_blk(atgep, &atge_l1_dma_attr_rr,
212*11353SSaurabh.Mishra@Sun.COM L1_RR_RING_SZ, DDI_DMA_RDWR);
213*11353SSaurabh.Mishra@Sun.COM l1->atge_l1_rr = dma;
214*11353SSaurabh.Mishra@Sun.COM if (dma == NULL) {
215*11353SSaurabh.Mishra@Sun.COM atge_error(atgep->atge_dip, "DMA allocation failed"
216*11353SSaurabh.Mishra@Sun.COM " for RX RR ring");
217*11353SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
218*11353SSaurabh.Mishra@Sun.COM }
219*11353SSaurabh.Mishra@Sun.COM
220*11353SSaurabh.Mishra@Sun.COM /*
221*11353SSaurabh.Mishra@Sun.COM * SMB for statistics.
222*11353SSaurabh.Mishra@Sun.COM */
223*11353SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() L1_SMB_BLOCK_SZ : %x", atgep->atge_name,
224*11353SSaurabh.Mishra@Sun.COM __func__, L1_SMB_BLOCK_SZ));
225*11353SSaurabh.Mishra@Sun.COM
226*11353SSaurabh.Mishra@Sun.COM dma = atge_alloc_a_dma_blk(atgep, &atge_l1_dma_attr_smb,
227*11353SSaurabh.Mishra@Sun.COM L1_SMB_BLOCK_SZ, DDI_DMA_RDWR);
228*11353SSaurabh.Mishra@Sun.COM l1->atge_l1_smb = dma;
229*11353SSaurabh.Mishra@Sun.COM if (dma == NULL) {
230*11353SSaurabh.Mishra@Sun.COM atge_error(atgep->atge_dip, "DMA allocation failed for SMB");
231*11353SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
232*11353SSaurabh.Mishra@Sun.COM }
233*11353SSaurabh.Mishra@Sun.COM
234*11353SSaurabh.Mishra@Sun.COM atgep->atge_hw_stats = kmem_zalloc(sizeof (atge_l1_smb_t), KM_SLEEP);
235*11353SSaurabh.Mishra@Sun.COM
236*11353SSaurabh.Mishra@Sun.COM return (DDI_SUCCESS);
237*11353SSaurabh.Mishra@Sun.COM }
238*11353SSaurabh.Mishra@Sun.COM
239*11353SSaurabh.Mishra@Sun.COM void
atge_l1_free_dma(atge_t * atgep)240*11353SSaurabh.Mishra@Sun.COM atge_l1_free_dma(atge_t *atgep)
241*11353SSaurabh.Mishra@Sun.COM {
242*11353SSaurabh.Mishra@Sun.COM atge_l1_data_t *l1;
243*11353SSaurabh.Mishra@Sun.COM
244*11353SSaurabh.Mishra@Sun.COM l1 = atgep->atge_private_data;
245*11353SSaurabh.Mishra@Sun.COM
246*11353SSaurabh.Mishra@Sun.COM /*
247*11353SSaurabh.Mishra@Sun.COM * Free TX ring.
248*11353SSaurabh.Mishra@Sun.COM */
249*11353SSaurabh.Mishra@Sun.COM if (atgep->atge_tx_ring != NULL) {
250*11353SSaurabh.Mishra@Sun.COM atge_free_buffers(atgep->atge_tx_ring, ATGE_TX_RING_CNT);
251*11353SSaurabh.Mishra@Sun.COM
252*11353SSaurabh.Mishra@Sun.COM if (atgep->atge_tx_ring->r_desc_ring != NULL) {
253*11353SSaurabh.Mishra@Sun.COM atge_free_a_dma_blk(atgep->atge_tx_ring->r_desc_ring);
254*11353SSaurabh.Mishra@Sun.COM }
255*11353SSaurabh.Mishra@Sun.COM
256*11353SSaurabh.Mishra@Sun.COM kmem_free(atgep->atge_tx_ring, sizeof (atge_ring_t));
257*11353SSaurabh.Mishra@Sun.COM atgep->atge_tx_ring = NULL;
258*11353SSaurabh.Mishra@Sun.COM }
259*11353SSaurabh.Mishra@Sun.COM
260*11353SSaurabh.Mishra@Sun.COM if (l1 && l1->atge_l1_cmb != NULL) {
261*11353SSaurabh.Mishra@Sun.COM atge_free_a_dma_blk(l1->atge_l1_cmb);
262*11353SSaurabh.Mishra@Sun.COM l1->atge_l1_cmb = NULL;
263*11353SSaurabh.Mishra@Sun.COM }
264*11353SSaurabh.Mishra@Sun.COM
265*11353SSaurabh.Mishra@Sun.COM if (l1 && l1->atge_l1_rr != NULL) {
266*11353SSaurabh.Mishra@Sun.COM atge_free_a_dma_blk(l1->atge_l1_rr);
267*11353SSaurabh.Mishra@Sun.COM l1->atge_l1_rr = NULL;
268*11353SSaurabh.Mishra@Sun.COM }
269*11353SSaurabh.Mishra@Sun.COM
270*11353SSaurabh.Mishra@Sun.COM if (l1 && l1->atge_l1_smb != NULL) {
271*11353SSaurabh.Mishra@Sun.COM atge_free_a_dma_blk(l1->atge_l1_smb);
272*11353SSaurabh.Mishra@Sun.COM l1->atge_l1_smb = NULL;
273*11353SSaurabh.Mishra@Sun.COM }
274*11353SSaurabh.Mishra@Sun.COM
275*11353SSaurabh.Mishra@Sun.COM /*
276*11353SSaurabh.Mishra@Sun.COM * Free RX ring.
277*11353SSaurabh.Mishra@Sun.COM */
278*11353SSaurabh.Mishra@Sun.COM if (l1 && l1->atge_rx_ring != NULL) {
279*11353SSaurabh.Mishra@Sun.COM atge_free_buffers(l1->atge_rx_ring, L1_RX_RING_CNT);
280*11353SSaurabh.Mishra@Sun.COM
281*11353SSaurabh.Mishra@Sun.COM if (l1->atge_rx_ring->r_desc_ring != NULL) {
282*11353SSaurabh.Mishra@Sun.COM atge_free_a_dma_blk(l1->atge_rx_ring->r_desc_ring);
283*11353SSaurabh.Mishra@Sun.COM }
284*11353SSaurabh.Mishra@Sun.COM
285*11353SSaurabh.Mishra@Sun.COM kmem_free(l1->atge_rx_ring, sizeof (atge_ring_t));
286*11353SSaurabh.Mishra@Sun.COM l1->atge_rx_ring = NULL;
287*11353SSaurabh.Mishra@Sun.COM }
288*11353SSaurabh.Mishra@Sun.COM
289*11353SSaurabh.Mishra@Sun.COM /*
290*11353SSaurabh.Mishra@Sun.COM * Free the memory allocated for gathering hw stats.
291*11353SSaurabh.Mishra@Sun.COM */
292*11353SSaurabh.Mishra@Sun.COM if (atgep->atge_hw_stats != NULL) {
293*11353SSaurabh.Mishra@Sun.COM kmem_free(atgep->atge_hw_stats, sizeof (atge_l1_smb_t));
294*11353SSaurabh.Mishra@Sun.COM atgep->atge_hw_stats = NULL;
295*11353SSaurabh.Mishra@Sun.COM }
296*11353SSaurabh.Mishra@Sun.COM }
297*11353SSaurabh.Mishra@Sun.COM
298*11353SSaurabh.Mishra@Sun.COM void
atge_l1_init_rx_ring(atge_t * atgep)299*11353SSaurabh.Mishra@Sun.COM atge_l1_init_rx_ring(atge_t *atgep)
300*11353SSaurabh.Mishra@Sun.COM {
301*11353SSaurabh.Mishra@Sun.COM atge_l1_data_t *l1;
302*11353SSaurabh.Mishra@Sun.COM atge_dma_t *dma;
303*11353SSaurabh.Mishra@Sun.COM l1_rx_desc_t *rx;
304*11353SSaurabh.Mishra@Sun.COM int i;
305*11353SSaurabh.Mishra@Sun.COM
306*11353SSaurabh.Mishra@Sun.COM l1 = atgep->atge_private_data;
307*11353SSaurabh.Mishra@Sun.COM l1->atge_rx_ring->r_consumer = L1_RX_RING_CNT - 1;
308*11353SSaurabh.Mishra@Sun.COM dma = l1->atge_rx_ring->r_desc_ring;
309*11353SSaurabh.Mishra@Sun.COM bzero(dma->addr, L1_RX_RING_SZ);
310*11353SSaurabh.Mishra@Sun.COM
311*11353SSaurabh.Mishra@Sun.COM for (i = 0; i < L1_RX_RING_CNT; i++) {
312*11353SSaurabh.Mishra@Sun.COM rx = (l1_rx_desc_t *)(dma->addr + (i * sizeof (l1_rx_desc_t)));
313*11353SSaurabh.Mishra@Sun.COM
314*11353SSaurabh.Mishra@Sun.COM ATGE_PUT64(dma, &rx->addr,
315*11353SSaurabh.Mishra@Sun.COM l1->atge_rx_ring->r_buf_tbl[i]->cookie.dmac_laddress);
316*11353SSaurabh.Mishra@Sun.COM ATGE_PUT32(dma, &rx->len,
317*11353SSaurabh.Mishra@Sun.COM (l1->atge_rx_ring->r_buf_tbl[i]->len & L1_RD_LEN_MASK) <<
318*11353SSaurabh.Mishra@Sun.COM L1_RD_LEN_SHIFT);
319*11353SSaurabh.Mishra@Sun.COM }
320*11353SSaurabh.Mishra@Sun.COM
321*11353SSaurabh.Mishra@Sun.COM DMA_SYNC(dma, 0, L1_RX_RING_SZ, DDI_DMA_SYNC_FORDEV);
322*11353SSaurabh.Mishra@Sun.COM }
323*11353SSaurabh.Mishra@Sun.COM
324*11353SSaurabh.Mishra@Sun.COM void
atge_l1_init_tx_ring(atge_t * atgep)325*11353SSaurabh.Mishra@Sun.COM atge_l1_init_tx_ring(atge_t *atgep)
326*11353SSaurabh.Mishra@Sun.COM {
327*11353SSaurabh.Mishra@Sun.COM atgep->atge_tx_ring->r_producer = 0;
328*11353SSaurabh.Mishra@Sun.COM atgep->atge_tx_ring->r_consumer = 0;
329*11353SSaurabh.Mishra@Sun.COM atgep->atge_tx_ring->r_avail_desc = ATGE_TX_RING_CNT;
330*11353SSaurabh.Mishra@Sun.COM
331*11353SSaurabh.Mishra@Sun.COM bzero(atgep->atge_tx_ring->r_desc_ring->addr, ATGE_TX_RING_SZ);
332*11353SSaurabh.Mishra@Sun.COM DMA_SYNC(atgep->atge_tx_ring->r_desc_ring, 0, ATGE_TX_RING_SZ,
333*11353SSaurabh.Mishra@Sun.COM DDI_DMA_SYNC_FORDEV);
334*11353SSaurabh.Mishra@Sun.COM }
335*11353SSaurabh.Mishra@Sun.COM
336*11353SSaurabh.Mishra@Sun.COM void
atge_l1_init_rr_ring(atge_t * atgep)337*11353SSaurabh.Mishra@Sun.COM atge_l1_init_rr_ring(atge_t *atgep)
338*11353SSaurabh.Mishra@Sun.COM {
339*11353SSaurabh.Mishra@Sun.COM atge_l1_data_t *l1;
340*11353SSaurabh.Mishra@Sun.COM atge_dma_t *dma;
341*11353SSaurabh.Mishra@Sun.COM
342*11353SSaurabh.Mishra@Sun.COM l1 = atgep->atge_private_data;
343*11353SSaurabh.Mishra@Sun.COM l1->atge_l1_rr_consumers = 0;
344*11353SSaurabh.Mishra@Sun.COM
345*11353SSaurabh.Mishra@Sun.COM dma = l1->atge_l1_rr;
346*11353SSaurabh.Mishra@Sun.COM bzero(dma->addr, L1_RR_RING_SZ);
347*11353SSaurabh.Mishra@Sun.COM DMA_SYNC(dma, 0, L1_RR_RING_SZ, DDI_DMA_SYNC_FORDEV);
348*11353SSaurabh.Mishra@Sun.COM }
349*11353SSaurabh.Mishra@Sun.COM
350*11353SSaurabh.Mishra@Sun.COM void
atge_l1_init_smb(atge_t * atgep)351*11353SSaurabh.Mishra@Sun.COM atge_l1_init_smb(atge_t *atgep)
352*11353SSaurabh.Mishra@Sun.COM {
353*11353SSaurabh.Mishra@Sun.COM atge_l1_data_t *l1;
354*11353SSaurabh.Mishra@Sun.COM atge_dma_t *dma;
355*11353SSaurabh.Mishra@Sun.COM
356*11353SSaurabh.Mishra@Sun.COM l1 = atgep->atge_private_data;
357*11353SSaurabh.Mishra@Sun.COM dma = l1->atge_l1_smb;
358*11353SSaurabh.Mishra@Sun.COM bzero(dma->addr, L1_SMB_BLOCK_SZ);
359*11353SSaurabh.Mishra@Sun.COM DMA_SYNC(dma, 0, L1_SMB_BLOCK_SZ, DDI_DMA_SYNC_FORDEV);
360*11353SSaurabh.Mishra@Sun.COM }
361*11353SSaurabh.Mishra@Sun.COM
362*11353SSaurabh.Mishra@Sun.COM void
atge_l1_init_cmb(atge_t * atgep)363*11353SSaurabh.Mishra@Sun.COM atge_l1_init_cmb(atge_t *atgep)
364*11353SSaurabh.Mishra@Sun.COM {
365*11353SSaurabh.Mishra@Sun.COM atge_l1_data_t *l1;
366*11353SSaurabh.Mishra@Sun.COM atge_dma_t *dma;
367*11353SSaurabh.Mishra@Sun.COM
368*11353SSaurabh.Mishra@Sun.COM l1 = atgep->atge_private_data;
369*11353SSaurabh.Mishra@Sun.COM dma = l1->atge_l1_cmb;
370*11353SSaurabh.Mishra@Sun.COM bzero(dma->addr, L1_CMB_BLOCK_SZ);
371*11353SSaurabh.Mishra@Sun.COM DMA_SYNC(dma, 0, L1_CMB_BLOCK_SZ, DDI_DMA_SYNC_FORDEV);
372*11353SSaurabh.Mishra@Sun.COM }
373*11353SSaurabh.Mishra@Sun.COM
374*11353SSaurabh.Mishra@Sun.COM void
atge_l1_sync_mbox(atge_t * atgep)375*11353SSaurabh.Mishra@Sun.COM atge_l1_sync_mbox(atge_t *atgep)
376*11353SSaurabh.Mishra@Sun.COM {
377*11353SSaurabh.Mishra@Sun.COM atge_l1_data_t *l1;
378*11353SSaurabh.Mishra@Sun.COM
379*11353SSaurabh.Mishra@Sun.COM l1 = atgep->atge_private_data;
380*11353SSaurabh.Mishra@Sun.COM
381*11353SSaurabh.Mishra@Sun.COM mutex_enter(&atgep->atge_mbox_lock);
382*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_MBOX,
383*11353SSaurabh.Mishra@Sun.COM ((l1->atge_rx_ring->r_consumer << MBOX_RD_PROD_IDX_SHIFT) &
384*11353SSaurabh.Mishra@Sun.COM MBOX_RD_PROD_IDX_MASK) |
385*11353SSaurabh.Mishra@Sun.COM ((l1->atge_l1_rr_consumers <<
386*11353SSaurabh.Mishra@Sun.COM MBOX_RRD_CONS_IDX_SHIFT) & MBOX_RRD_CONS_IDX_MASK) |
387*11353SSaurabh.Mishra@Sun.COM ((atgep->atge_tx_ring->r_producer << MBOX_TD_PROD_IDX_SHIFT) &
388*11353SSaurabh.Mishra@Sun.COM MBOX_TD_PROD_IDX_MASK));
389*11353SSaurabh.Mishra@Sun.COM mutex_exit(&atgep->atge_mbox_lock);
390*11353SSaurabh.Mishra@Sun.COM }
391*11353SSaurabh.Mishra@Sun.COM
392*11353SSaurabh.Mishra@Sun.COM void
atge_l1_program_dma(atge_t * atgep)393*11353SSaurabh.Mishra@Sun.COM atge_l1_program_dma(atge_t *atgep)
394*11353SSaurabh.Mishra@Sun.COM {
395*11353SSaurabh.Mishra@Sun.COM atge_l1_data_t *l1;
396*11353SSaurabh.Mishra@Sun.COM atge_ring_t *r;
397*11353SSaurabh.Mishra@Sun.COM
398*11353SSaurabh.Mishra@Sun.COM l1 = atgep->atge_private_data;
399*11353SSaurabh.Mishra@Sun.COM
400*11353SSaurabh.Mishra@Sun.COM /* TX */
401*11353SSaurabh.Mishra@Sun.COM r = atgep->atge_tx_ring;
402*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_DESC_ADDR_HI,
403*11353SSaurabh.Mishra@Sun.COM ATGE_ADDR_HI(r->r_desc_ring->cookie.dmac_laddress));
404*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_DESC_TPD_ADDR_LO,
405*11353SSaurabh.Mishra@Sun.COM ATGE_ADDR_LO(r->r_desc_ring->cookie.dmac_laddress));
406*11353SSaurabh.Mishra@Sun.COM
407*11353SSaurabh.Mishra@Sun.COM /* RX */
408*11353SSaurabh.Mishra@Sun.COM r = l1->atge_rx_ring;
409*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_DESC_RD_ADDR_LO,
410*11353SSaurabh.Mishra@Sun.COM ATGE_ADDR_LO(r->r_desc_ring->cookie.dmac_laddress));
411*11353SSaurabh.Mishra@Sun.COM
412*11353SSaurabh.Mishra@Sun.COM /* RR Ring */
413*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_DESC_RRD_ADDR_LO,
414*11353SSaurabh.Mishra@Sun.COM ATGE_ADDR_LO(l1->atge_l1_rr->cookie.dmac_laddress));
415*11353SSaurabh.Mishra@Sun.COM
416*11353SSaurabh.Mishra@Sun.COM /* CMB */
417*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_DESC_CMB_ADDR_LO,
418*11353SSaurabh.Mishra@Sun.COM ATGE_ADDR_LO(l1->atge_l1_cmb->cookie.dmac_laddress));
419*11353SSaurabh.Mishra@Sun.COM
420*11353SSaurabh.Mishra@Sun.COM /* SMB */
421*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_DESC_SMB_ADDR_LO,
422*11353SSaurabh.Mishra@Sun.COM ATGE_ADDR_LO(l1->atge_l1_smb->cookie.dmac_laddress));
423*11353SSaurabh.Mishra@Sun.COM
424*11353SSaurabh.Mishra@Sun.COM /*
425*11353SSaurabh.Mishra@Sun.COM * Set RX return ring (RR) counter.
426*11353SSaurabh.Mishra@Sun.COM */
427*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_DESC_RRD_RD_CNT,
428*11353SSaurabh.Mishra@Sun.COM ((L1_RR_RING_CNT << DESC_RRD_CNT_SHIFT) &
429*11353SSaurabh.Mishra@Sun.COM DESC_RRD_CNT_MASK) |
430*11353SSaurabh.Mishra@Sun.COM ((L1_RX_RING_CNT << DESC_RD_CNT_SHIFT) & DESC_RD_CNT_MASK));
431*11353SSaurabh.Mishra@Sun.COM
432*11353SSaurabh.Mishra@Sun.COM /*
433*11353SSaurabh.Mishra@Sun.COM * Set TX descriptor counter.
434*11353SSaurabh.Mishra@Sun.COM */
435*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_DESC_TPD_CNT,
436*11353SSaurabh.Mishra@Sun.COM (ATGE_TX_RING_CNT << DESC_TPD_CNT_SHIFT) & DESC_TPD_CNT_MASK);
437*11353SSaurabh.Mishra@Sun.COM
438*11353SSaurabh.Mishra@Sun.COM /*
439*11353SSaurabh.Mishra@Sun.COM * Inform hardware that we have loaded DMA registers.
440*11353SSaurabh.Mishra@Sun.COM */
441*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_DMA_BLOCK, DMA_BLOCK_LOAD);
442*11353SSaurabh.Mishra@Sun.COM
443*11353SSaurabh.Mishra@Sun.COM /*
444*11353SSaurabh.Mishra@Sun.COM * Initialize mailbox register (mbox).
445*11353SSaurabh.Mishra@Sun.COM */
446*11353SSaurabh.Mishra@Sun.COM atge_l1_sync_mbox(atgep);
447*11353SSaurabh.Mishra@Sun.COM }
448*11353SSaurabh.Mishra@Sun.COM
449*11353SSaurabh.Mishra@Sun.COM void
atge_l1_gather_stats(atge_t * atgep)450*11353SSaurabh.Mishra@Sun.COM atge_l1_gather_stats(atge_t *atgep)
451*11353SSaurabh.Mishra@Sun.COM {
452*11353SSaurabh.Mishra@Sun.COM atge_l1_data_t *l1;
453*11353SSaurabh.Mishra@Sun.COM atge_dma_t *dma;
454*11353SSaurabh.Mishra@Sun.COM atge_l1_smb_t *stat;
455*11353SSaurabh.Mishra@Sun.COM atge_l1_smb_t *smb;
456*11353SSaurabh.Mishra@Sun.COM
457*11353SSaurabh.Mishra@Sun.COM ASSERT(atgep != NULL);
458*11353SSaurabh.Mishra@Sun.COM
459*11353SSaurabh.Mishra@Sun.COM l1 = atgep->atge_private_data;
460*11353SSaurabh.Mishra@Sun.COM dma = l1->atge_l1_smb;
461*11353SSaurabh.Mishra@Sun.COM DMA_SYNC(dma, 0, L1_SMB_BLOCK_SZ, DDI_DMA_SYNC_FORKERNEL);
462*11353SSaurabh.Mishra@Sun.COM stat = (atge_l1_smb_t *)atgep->atge_hw_stats;
463*11353SSaurabh.Mishra@Sun.COM smb = (atge_l1_smb_t *)dma->addr;
464*11353SSaurabh.Mishra@Sun.COM
465*11353SSaurabh.Mishra@Sun.COM /* Rx stats. */
466*11353SSaurabh.Mishra@Sun.COM stat->rx_frames += smb->rx_frames;
467*11353SSaurabh.Mishra@Sun.COM stat->rx_bcast_frames += smb->rx_bcast_frames;
468*11353SSaurabh.Mishra@Sun.COM stat->rx_mcast_frames += smb->rx_mcast_frames;
469*11353SSaurabh.Mishra@Sun.COM stat->rx_pause_frames += smb->rx_pause_frames;
470*11353SSaurabh.Mishra@Sun.COM stat->rx_control_frames += smb->rx_control_frames;
471*11353SSaurabh.Mishra@Sun.COM stat->rx_crcerrs += smb->rx_crcerrs;
472*11353SSaurabh.Mishra@Sun.COM stat->rx_lenerrs += smb->rx_lenerrs;
473*11353SSaurabh.Mishra@Sun.COM stat->rx_bytes += smb->rx_bytes;
474*11353SSaurabh.Mishra@Sun.COM stat->rx_runts += smb->rx_runts;
475*11353SSaurabh.Mishra@Sun.COM stat->rx_fragments += smb->rx_fragments;
476*11353SSaurabh.Mishra@Sun.COM stat->rx_pkts_64 += smb->rx_pkts_64;
477*11353SSaurabh.Mishra@Sun.COM stat->rx_pkts_65_127 += smb->rx_pkts_65_127;
478*11353SSaurabh.Mishra@Sun.COM stat->rx_pkts_128_255 += smb->rx_pkts_128_255;
479*11353SSaurabh.Mishra@Sun.COM stat->rx_pkts_256_511 += smb->rx_pkts_256_511;
480*11353SSaurabh.Mishra@Sun.COM stat->rx_pkts_512_1023 += smb->rx_pkts_512_1023;
481*11353SSaurabh.Mishra@Sun.COM stat->rx_pkts_1024_1518 += smb->rx_pkts_1024_1518;
482*11353SSaurabh.Mishra@Sun.COM stat->rx_pkts_1519_max += smb->rx_pkts_1519_max;
483*11353SSaurabh.Mishra@Sun.COM stat->rx_pkts_truncated += smb->rx_pkts_truncated;
484*11353SSaurabh.Mishra@Sun.COM stat->rx_fifo_oflows += smb->rx_fifo_oflows;
485*11353SSaurabh.Mishra@Sun.COM stat->rx_alignerrs += smb->rx_alignerrs;
486*11353SSaurabh.Mishra@Sun.COM stat->rx_bcast_bytes += smb->rx_bcast_bytes;
487*11353SSaurabh.Mishra@Sun.COM stat->rx_mcast_bytes += smb->rx_mcast_bytes;
488*11353SSaurabh.Mishra@Sun.COM stat->rx_pkts_filtered += smb->rx_pkts_filtered;
489*11353SSaurabh.Mishra@Sun.COM
490*11353SSaurabh.Mishra@Sun.COM /* Tx stats. */
491*11353SSaurabh.Mishra@Sun.COM stat->tx_frames += smb->tx_frames;
492*11353SSaurabh.Mishra@Sun.COM stat->tx_bcast_frames += smb->tx_bcast_frames;
493*11353SSaurabh.Mishra@Sun.COM stat->tx_mcast_frames += smb->tx_mcast_frames;
494*11353SSaurabh.Mishra@Sun.COM stat->tx_pause_frames += smb->tx_pause_frames;
495*11353SSaurabh.Mishra@Sun.COM stat->tx_excess_defer += smb->tx_excess_defer;
496*11353SSaurabh.Mishra@Sun.COM stat->tx_control_frames += smb->tx_control_frames;
497*11353SSaurabh.Mishra@Sun.COM stat->tx_deferred += smb->tx_deferred;
498*11353SSaurabh.Mishra@Sun.COM stat->tx_bytes += smb->tx_bytes;
499*11353SSaurabh.Mishra@Sun.COM stat->tx_pkts_64 += smb->tx_pkts_64;
500*11353SSaurabh.Mishra@Sun.COM stat->tx_pkts_65_127 += smb->tx_pkts_65_127;
501*11353SSaurabh.Mishra@Sun.COM stat->tx_pkts_128_255 += smb->tx_pkts_128_255;
502*11353SSaurabh.Mishra@Sun.COM stat->tx_pkts_256_511 += smb->tx_pkts_256_511;
503*11353SSaurabh.Mishra@Sun.COM stat->tx_pkts_512_1023 += smb->tx_pkts_512_1023;
504*11353SSaurabh.Mishra@Sun.COM stat->tx_pkts_1024_1518 += smb->tx_pkts_1024_1518;
505*11353SSaurabh.Mishra@Sun.COM stat->tx_pkts_1519_max += smb->tx_pkts_1519_max;
506*11353SSaurabh.Mishra@Sun.COM stat->tx_single_colls += smb->tx_single_colls;
507*11353SSaurabh.Mishra@Sun.COM stat->tx_multi_colls += smb->tx_multi_colls;
508*11353SSaurabh.Mishra@Sun.COM stat->tx_late_colls += smb->tx_late_colls;
509*11353SSaurabh.Mishra@Sun.COM stat->tx_excess_colls += smb->tx_excess_colls;
510*11353SSaurabh.Mishra@Sun.COM stat->tx_underrun += smb->tx_underrun;
511*11353SSaurabh.Mishra@Sun.COM stat->tx_desc_underrun += smb->tx_desc_underrun;
512*11353SSaurabh.Mishra@Sun.COM stat->tx_lenerrs += smb->tx_lenerrs;
513*11353SSaurabh.Mishra@Sun.COM stat->tx_pkts_truncated += smb->tx_pkts_truncated;
514*11353SSaurabh.Mishra@Sun.COM stat->tx_bcast_bytes += smb->tx_bcast_bytes;
515*11353SSaurabh.Mishra@Sun.COM stat->tx_mcast_bytes += smb->tx_mcast_bytes;
516*11353SSaurabh.Mishra@Sun.COM
517*11353SSaurabh.Mishra@Sun.COM /*
518*11353SSaurabh.Mishra@Sun.COM * Update global counters in atge_t.
519*11353SSaurabh.Mishra@Sun.COM */
520*11353SSaurabh.Mishra@Sun.COM atgep->atge_brdcstrcv += smb->rx_bcast_frames;
521*11353SSaurabh.Mishra@Sun.COM atgep->atge_multircv += smb->rx_mcast_frames;
522*11353SSaurabh.Mishra@Sun.COM atgep->atge_multixmt += smb->tx_mcast_frames;
523*11353SSaurabh.Mishra@Sun.COM atgep->atge_brdcstxmt += smb->tx_bcast_frames;
524*11353SSaurabh.Mishra@Sun.COM
525*11353SSaurabh.Mishra@Sun.COM atgep->atge_align_errors += smb->rx_alignerrs;
526*11353SSaurabh.Mishra@Sun.COM atgep->atge_fcs_errors += smb->rx_crcerrs;
527*11353SSaurabh.Mishra@Sun.COM atgep->atge_defer_xmts += smb->tx_deferred;
528*11353SSaurabh.Mishra@Sun.COM atgep->atge_first_collisions += smb->tx_single_colls;
529*11353SSaurabh.Mishra@Sun.COM atgep->atge_multi_collisions += smb->tx_multi_colls * 2;
530*11353SSaurabh.Mishra@Sun.COM atgep->atge_tx_late_collisions += smb->tx_late_colls;
531*11353SSaurabh.Mishra@Sun.COM atgep->atge_ex_collisions += smb->tx_excess_colls;
532*11353SSaurabh.Mishra@Sun.COM atgep->atge_toolong_errors += smb->rx_lenerrs;
533*11353SSaurabh.Mishra@Sun.COM atgep->atge_overflow += smb->rx_fifo_oflows;
534*11353SSaurabh.Mishra@Sun.COM atgep->atge_underflow += (smb->tx_underrun + smb->tx_desc_underrun);
535*11353SSaurabh.Mishra@Sun.COM atgep->atge_runt += smb->rx_runts;
536*11353SSaurabh.Mishra@Sun.COM
537*11353SSaurabh.Mishra@Sun.COM
538*11353SSaurabh.Mishra@Sun.COM atgep->atge_collisions += smb->tx_single_colls +
539*11353SSaurabh.Mishra@Sun.COM smb->tx_multi_colls * 2 + smb->tx_late_colls;
540*11353SSaurabh.Mishra@Sun.COM
541*11353SSaurabh.Mishra@Sun.COM /*
542*11353SSaurabh.Mishra@Sun.COM * tx_pkts_truncated counter looks suspicious. It constantly
543*11353SSaurabh.Mishra@Sun.COM * increments with no sign of Tx errors. Hence we don't factor it.
544*11353SSaurabh.Mishra@Sun.COM */
545*11353SSaurabh.Mishra@Sun.COM atgep->atge_macxmt_errors += smb->tx_late_colls + smb->tx_underrun;
546*11353SSaurabh.Mishra@Sun.COM
547*11353SSaurabh.Mishra@Sun.COM atgep->atge_macrcv_errors += smb->rx_crcerrs + smb->rx_lenerrs +
548*11353SSaurabh.Mishra@Sun.COM smb->rx_runts + smb->rx_pkts_truncated +
549*11353SSaurabh.Mishra@Sun.COM smb->rx_alignerrs;
550*11353SSaurabh.Mishra@Sun.COM
551*11353SSaurabh.Mishra@Sun.COM smb->updated = 0;
552*11353SSaurabh.Mishra@Sun.COM DMA_SYNC(dma, 0, L1_SMB_BLOCK_SZ, DDI_DMA_SYNC_FORDEV);
553*11353SSaurabh.Mishra@Sun.COM }
554*11353SSaurabh.Mishra@Sun.COM
555*11353SSaurabh.Mishra@Sun.COM void
atge_l1_stop_tx_mac(atge_t * atgep)556*11353SSaurabh.Mishra@Sun.COM atge_l1_stop_tx_mac(atge_t *atgep)
557*11353SSaurabh.Mishra@Sun.COM {
558*11353SSaurabh.Mishra@Sun.COM uint32_t reg;
559*11353SSaurabh.Mishra@Sun.COM int t;
560*11353SSaurabh.Mishra@Sun.COM
561*11353SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() called", atgep->atge_name, __func__));
562*11353SSaurabh.Mishra@Sun.COM
563*11353SSaurabh.Mishra@Sun.COM reg = INL(atgep, ATGE_MAC_CFG);
564*11353SSaurabh.Mishra@Sun.COM if ((reg & ATGE_CFG_TX_ENB) != 0) {
565*11353SSaurabh.Mishra@Sun.COM reg &= ~ATGE_CFG_TX_ENB;
566*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_MAC_CFG, reg);
567*11353SSaurabh.Mishra@Sun.COM }
568*11353SSaurabh.Mishra@Sun.COM
569*11353SSaurabh.Mishra@Sun.COM /* Stop TX DMA engine. */
570*11353SSaurabh.Mishra@Sun.COM reg = INL(atgep, ATGE_DMA_CFG);
571*11353SSaurabh.Mishra@Sun.COM if ((reg & DMA_CFG_RD_ENB) != 0) {
572*11353SSaurabh.Mishra@Sun.COM reg &= ~DMA_CFG_RD_ENB;
573*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_DMA_CFG, reg);
574*11353SSaurabh.Mishra@Sun.COM }
575*11353SSaurabh.Mishra@Sun.COM
576*11353SSaurabh.Mishra@Sun.COM for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
577*11353SSaurabh.Mishra@Sun.COM if ((INL(atgep, ATGE_IDLE_STATUS) &
578*11353SSaurabh.Mishra@Sun.COM (IDLE_STATUS_TXMAC | IDLE_STATUS_DMARD)) == 0)
579*11353SSaurabh.Mishra@Sun.COM break;
580*11353SSaurabh.Mishra@Sun.COM
581*11353SSaurabh.Mishra@Sun.COM drv_usecwait(10);
582*11353SSaurabh.Mishra@Sun.COM }
583*11353SSaurabh.Mishra@Sun.COM
584*11353SSaurabh.Mishra@Sun.COM if (t == 0) {
585*11353SSaurabh.Mishra@Sun.COM atge_error(atgep->atge_dip, "stopping TX DMA Engine timeout");
586*11353SSaurabh.Mishra@Sun.COM }
587*11353SSaurabh.Mishra@Sun.COM }
588*11353SSaurabh.Mishra@Sun.COM
589*11353SSaurabh.Mishra@Sun.COM void
atge_l1_stop_rx_mac(atge_t * atgep)590*11353SSaurabh.Mishra@Sun.COM atge_l1_stop_rx_mac(atge_t *atgep)
591*11353SSaurabh.Mishra@Sun.COM {
592*11353SSaurabh.Mishra@Sun.COM uint32_t reg;
593*11353SSaurabh.Mishra@Sun.COM int t;
594*11353SSaurabh.Mishra@Sun.COM
595*11353SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() called", atgep->atge_name, __func__));
596*11353SSaurabh.Mishra@Sun.COM
597*11353SSaurabh.Mishra@Sun.COM reg = INL(atgep, ATGE_MAC_CFG);
598*11353SSaurabh.Mishra@Sun.COM if ((reg & ATGE_CFG_RX_ENB) != 0) {
599*11353SSaurabh.Mishra@Sun.COM reg &= ~ATGE_CFG_RX_ENB;
600*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_MAC_CFG, reg);
601*11353SSaurabh.Mishra@Sun.COM }
602*11353SSaurabh.Mishra@Sun.COM
603*11353SSaurabh.Mishra@Sun.COM /* Stop RX DMA engine. */
604*11353SSaurabh.Mishra@Sun.COM reg = INL(atgep, ATGE_DMA_CFG);
605*11353SSaurabh.Mishra@Sun.COM if ((reg & DMA_CFG_WR_ENB) != 0) {
606*11353SSaurabh.Mishra@Sun.COM reg &= ~DMA_CFG_WR_ENB;
607*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_DMA_CFG, reg);
608*11353SSaurabh.Mishra@Sun.COM }
609*11353SSaurabh.Mishra@Sun.COM
610*11353SSaurabh.Mishra@Sun.COM for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
611*11353SSaurabh.Mishra@Sun.COM if ((INL(atgep, ATGE_IDLE_STATUS) &
612*11353SSaurabh.Mishra@Sun.COM (IDLE_STATUS_RXMAC | IDLE_STATUS_DMAWR)) == 0)
613*11353SSaurabh.Mishra@Sun.COM break;
614*11353SSaurabh.Mishra@Sun.COM drv_usecwait(10);
615*11353SSaurabh.Mishra@Sun.COM }
616*11353SSaurabh.Mishra@Sun.COM
617*11353SSaurabh.Mishra@Sun.COM if (t == 0) {
618*11353SSaurabh.Mishra@Sun.COM atge_error(atgep->atge_dip, " stopping RX DMA Engine timeout");
619*11353SSaurabh.Mishra@Sun.COM }
620*11353SSaurabh.Mishra@Sun.COM }
621*11353SSaurabh.Mishra@Sun.COM
622*11353SSaurabh.Mishra@Sun.COM /*
623*11353SSaurabh.Mishra@Sun.COM * Receives (consumes) packets.
624*11353SSaurabh.Mishra@Sun.COM */
625*11353SSaurabh.Mishra@Sun.COM static mblk_t *
atge_l1_rx(atge_t * atgep)626*11353SSaurabh.Mishra@Sun.COM atge_l1_rx(atge_t *atgep)
627*11353SSaurabh.Mishra@Sun.COM {
628*11353SSaurabh.Mishra@Sun.COM atge_l1_data_t *l1;
629*11353SSaurabh.Mishra@Sun.COM mblk_t *mp = NULL, *rx_head = NULL, *rx_tail = NULL;
630*11353SSaurabh.Mishra@Sun.COM l1_rx_rdesc_t *rx_rr;
631*11353SSaurabh.Mishra@Sun.COM l1_rx_desc_t *rxd;
632*11353SSaurabh.Mishra@Sun.COM uint32_t index, flags, totlen, pktlen, slotlen;
633*11353SSaurabh.Mishra@Sun.COM int nsegs, rx_cons = 0, cnt;
634*11353SSaurabh.Mishra@Sun.COM atge_dma_t *buf;
635*11353SSaurabh.Mishra@Sun.COM uchar_t *bufp;
636*11353SSaurabh.Mishra@Sun.COM int sync = 0;
637*11353SSaurabh.Mishra@Sun.COM
638*11353SSaurabh.Mishra@Sun.COM l1 = atgep->atge_private_data;
639*11353SSaurabh.Mishra@Sun.COM ASSERT(l1 != NULL);
640*11353SSaurabh.Mishra@Sun.COM
641*11353SSaurabh.Mishra@Sun.COM DMA_SYNC(l1->atge_l1_rr, 0, L1_RR_RING_SZ, DDI_DMA_SYNC_FORKERNEL);
642*11353SSaurabh.Mishra@Sun.COM
643*11353SSaurabh.Mishra@Sun.COM while (l1->atge_l1_rr_consumers != l1->atge_l1_rx_prod_cons) {
644*11353SSaurabh.Mishra@Sun.COM rx_rr = (l1_rx_rdesc_t *)(l1->atge_l1_rr->addr +
645*11353SSaurabh.Mishra@Sun.COM (l1->atge_l1_rr_consumers * sizeof (l1_rx_rdesc_t)));
646*11353SSaurabh.Mishra@Sun.COM
647*11353SSaurabh.Mishra@Sun.COM index = ATGE_GET32(l1->atge_l1_rr, &rx_rr->index);
648*11353SSaurabh.Mishra@Sun.COM flags = ATGE_GET32(l1->atge_l1_rr, &rx_rr->flags);
649*11353SSaurabh.Mishra@Sun.COM totlen = L1_RX_BYTES(ATGE_GET32(l1->atge_l1_rr, &rx_rr->len));
650*11353SSaurabh.Mishra@Sun.COM
651*11353SSaurabh.Mishra@Sun.COM rx_cons = L1_RX_CONS(index);
652*11353SSaurabh.Mishra@Sun.COM nsegs = L1_RX_NSEGS(index);
653*11353SSaurabh.Mishra@Sun.COM
654*11353SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() PKT -- index : %d, flags : %x, totlen : %d,"
655*11353SSaurabh.Mishra@Sun.COM " rx_cons : %d, nsegs : %d", atgep->atge_name, __func__,
656*11353SSaurabh.Mishra@Sun.COM index, flags, totlen, rx_cons, nsegs));
657*11353SSaurabh.Mishra@Sun.COM
658*11353SSaurabh.Mishra@Sun.COM if (nsegs == 0)
659*11353SSaurabh.Mishra@Sun.COM break;
660*11353SSaurabh.Mishra@Sun.COM
661*11353SSaurabh.Mishra@Sun.COM if ((flags & L1_RRD_ERROR) &&
662*11353SSaurabh.Mishra@Sun.COM (flags & (L1_RRD_CRC | L1_RRD_CODE | L1_RRD_DRIBBLE |
663*11353SSaurabh.Mishra@Sun.COM L1_RRD_RUNT | L1_RRD_OFLOW | L1_RRD_TRUNC)) != 0) {
664*11353SSaurabh.Mishra@Sun.COM atge_error(atgep->atge_dip, "errored pkt");
665*11353SSaurabh.Mishra@Sun.COM
666*11353SSaurabh.Mishra@Sun.COM l1->atge_rx_ring->r_consumer += nsegs;
667*11353SSaurabh.Mishra@Sun.COM l1->atge_rx_ring->r_consumer %= L1_RX_RING_CNT;
668*11353SSaurabh.Mishra@Sun.COM break;
669*11353SSaurabh.Mishra@Sun.COM }
670*11353SSaurabh.Mishra@Sun.COM
671*11353SSaurabh.Mishra@Sun.COM ASSERT(rx_cons >= 0 && rx_cons <= L1_RX_RING_CNT);
672*11353SSaurabh.Mishra@Sun.COM
673*11353SSaurabh.Mishra@Sun.COM mp = allocb(totlen + VLAN_TAGSZ, BPRI_MED);
674*11353SSaurabh.Mishra@Sun.COM if (mp != NULL) {
675*11353SSaurabh.Mishra@Sun.COM mp->b_rptr += VLAN_TAGSZ;
676*11353SSaurabh.Mishra@Sun.COM bufp = mp->b_rptr;
677*11353SSaurabh.Mishra@Sun.COM mp->b_wptr = bufp + totlen;
678*11353SSaurabh.Mishra@Sun.COM mp->b_next = NULL;
679*11353SSaurabh.Mishra@Sun.COM
680*11353SSaurabh.Mishra@Sun.COM atgep->atge_ipackets++;
681*11353SSaurabh.Mishra@Sun.COM atgep->atge_rbytes += totlen;
682*11353SSaurabh.Mishra@Sun.COM
683*11353SSaurabh.Mishra@Sun.COM /*
684*11353SSaurabh.Mishra@Sun.COM * If there are more than one segments, then the first
685*11353SSaurabh.Mishra@Sun.COM * segment should be of size MTU. We couldn't verify
686*11353SSaurabh.Mishra@Sun.COM * this as our driver does not support changing MTU
687*11353SSaurabh.Mishra@Sun.COM * or Jumbo Frames.
688*11353SSaurabh.Mishra@Sun.COM */
689*11353SSaurabh.Mishra@Sun.COM if (nsegs > 1) {
690*11353SSaurabh.Mishra@Sun.COM slotlen = atgep->atge_mtu;
691*11353SSaurabh.Mishra@Sun.COM } else {
692*11353SSaurabh.Mishra@Sun.COM slotlen = totlen;
693*11353SSaurabh.Mishra@Sun.COM }
694*11353SSaurabh.Mishra@Sun.COM } else {
695*11353SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() PKT mp == NULL totlen : %d",
696*11353SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__, totlen));
697*11353SSaurabh.Mishra@Sun.COM
698*11353SSaurabh.Mishra@Sun.COM if (slotlen > atgep->atge_rx_buf_len) {
699*11353SSaurabh.Mishra@Sun.COM atgep->atge_toolong_errors++;
700*11353SSaurabh.Mishra@Sun.COM } else if (mp == NULL) {
701*11353SSaurabh.Mishra@Sun.COM atgep->atge_norcvbuf++;
702*11353SSaurabh.Mishra@Sun.COM }
703*11353SSaurabh.Mishra@Sun.COM
704*11353SSaurabh.Mishra@Sun.COM rx_rr->index = 0;
705*11353SSaurabh.Mishra@Sun.COM break;
706*11353SSaurabh.Mishra@Sun.COM }
707*11353SSaurabh.Mishra@Sun.COM
708*11353SSaurabh.Mishra@Sun.COM for (cnt = 0, pktlen = 0; cnt < nsegs; cnt++) {
709*11353SSaurabh.Mishra@Sun.COM buf = l1->atge_rx_ring->r_buf_tbl[rx_cons];
710*11353SSaurabh.Mishra@Sun.COM rxd = (l1_rx_desc_t *)(
711*11353SSaurabh.Mishra@Sun.COM l1->atge_rx_ring->r_desc_ring->addr +
712*11353SSaurabh.Mishra@Sun.COM (rx_cons * sizeof (l1_rx_desc_t)));
713*11353SSaurabh.Mishra@Sun.COM
714*11353SSaurabh.Mishra@Sun.COM if (cnt != 0) {
715*11353SSaurabh.Mishra@Sun.COM slotlen = L1_RX_BYTES(ATGE_GET32(
716*11353SSaurabh.Mishra@Sun.COM l1->atge_rx_ring->r_desc_ring, &rxd->len));
717*11353SSaurabh.Mishra@Sun.COM }
718*11353SSaurabh.Mishra@Sun.COM
719*11353SSaurabh.Mishra@Sun.COM bcopy(buf->addr, (bufp + pktlen), slotlen);
720*11353SSaurabh.Mishra@Sun.COM pktlen += slotlen;
721*11353SSaurabh.Mishra@Sun.COM
722*11353SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() len : %d, rxcons : %d, pktlen : %d",
723*11353SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__, slotlen, rx_cons,
724*11353SSaurabh.Mishra@Sun.COM pktlen));
725*11353SSaurabh.Mishra@Sun.COM
726*11353SSaurabh.Mishra@Sun.COM ATGE_INC_SLOT(rx_cons, L1_RX_RING_CNT);
727*11353SSaurabh.Mishra@Sun.COM }
728*11353SSaurabh.Mishra@Sun.COM
729*11353SSaurabh.Mishra@Sun.COM if (rx_tail == NULL) {
730*11353SSaurabh.Mishra@Sun.COM rx_head = rx_tail = mp;
731*11353SSaurabh.Mishra@Sun.COM } else {
732*11353SSaurabh.Mishra@Sun.COM rx_tail->b_next = mp;
733*11353SSaurabh.Mishra@Sun.COM rx_tail = mp;
734*11353SSaurabh.Mishra@Sun.COM }
735*11353SSaurabh.Mishra@Sun.COM
736*11353SSaurabh.Mishra@Sun.COM if (cnt != nsegs) {
737*11353SSaurabh.Mishra@Sun.COM l1->atge_rx_ring->r_consumer += nsegs;
738*11353SSaurabh.Mishra@Sun.COM l1->atge_rx_ring->r_consumer %= L1_RX_RING_CNT;
739*11353SSaurabh.Mishra@Sun.COM } else {
740*11353SSaurabh.Mishra@Sun.COM l1->atge_rx_ring->r_consumer = rx_cons;
741*11353SSaurabh.Mishra@Sun.COM }
742*11353SSaurabh.Mishra@Sun.COM
743*11353SSaurabh.Mishra@Sun.COM /*
744*11353SSaurabh.Mishra@Sun.COM * Tell the chip that this RR can be reused.
745*11353SSaurabh.Mishra@Sun.COM */
746*11353SSaurabh.Mishra@Sun.COM rx_rr->index = 0;
747*11353SSaurabh.Mishra@Sun.COM
748*11353SSaurabh.Mishra@Sun.COM ATGE_INC_SLOT(l1->atge_l1_rr_consumers, L1_RR_RING_CNT);
749*11353SSaurabh.Mishra@Sun.COM sync++;
750*11353SSaurabh.Mishra@Sun.COM }
751*11353SSaurabh.Mishra@Sun.COM
752*11353SSaurabh.Mishra@Sun.COM if (sync) {
753*11353SSaurabh.Mishra@Sun.COM DMA_SYNC(l1->atge_rx_ring->r_desc_ring, 0, L1_RX_RING_SZ,
754*11353SSaurabh.Mishra@Sun.COM DDI_DMA_SYNC_FORDEV);
755*11353SSaurabh.Mishra@Sun.COM
756*11353SSaurabh.Mishra@Sun.COM DMA_SYNC(l1->atge_l1_rr, 0, L1_RR_RING_SZ, DDI_DMA_SYNC_FORDEV);
757*11353SSaurabh.Mishra@Sun.COM atge_l1_sync_mbox(atgep);
758*11353SSaurabh.Mishra@Sun.COM
759*11353SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() PKT Recved -> r_consumer : %d, rx_cons : %d"
760*11353SSaurabh.Mishra@Sun.COM " atge_l1_rr_consumers : %d",
761*11353SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__, l1->atge_rx_ring->r_consumer,
762*11353SSaurabh.Mishra@Sun.COM rx_cons, l1->atge_l1_rr_consumers));
763*11353SSaurabh.Mishra@Sun.COM }
764*11353SSaurabh.Mishra@Sun.COM
765*11353SSaurabh.Mishra@Sun.COM
766*11353SSaurabh.Mishra@Sun.COM return (rx_head);
767*11353SSaurabh.Mishra@Sun.COM }
768*11353SSaurabh.Mishra@Sun.COM
769*11353SSaurabh.Mishra@Sun.COM /*
770*11353SSaurabh.Mishra@Sun.COM * The interrupt handler for L1 chip.
771*11353SSaurabh.Mishra@Sun.COM */
772*11353SSaurabh.Mishra@Sun.COM /*ARGSUSED*/
773*11353SSaurabh.Mishra@Sun.COM uint_t
atge_l1_interrupt(caddr_t arg1,caddr_t arg2)774*11353SSaurabh.Mishra@Sun.COM atge_l1_interrupt(caddr_t arg1, caddr_t arg2)
775*11353SSaurabh.Mishra@Sun.COM {
776*11353SSaurabh.Mishra@Sun.COM atge_t *atgep = (void *)arg1;
777*11353SSaurabh.Mishra@Sun.COM mblk_t *rx_head = NULL, *rx_head1 = NULL;
778*11353SSaurabh.Mishra@Sun.COM uint32_t status;
779*11353SSaurabh.Mishra@Sun.COM int resched = 0;
780*11353SSaurabh.Mishra@Sun.COM
781*11353SSaurabh.Mishra@Sun.COM ASSERT(atgep != NULL);
782*11353SSaurabh.Mishra@Sun.COM
783*11353SSaurabh.Mishra@Sun.COM mutex_enter(&atgep->atge_intr_lock);
784*11353SSaurabh.Mishra@Sun.COM
785*11353SSaurabh.Mishra@Sun.COM if (atgep->atge_chip_state & ATGE_CHIP_SUSPENDED) {
786*11353SSaurabh.Mishra@Sun.COM mutex_exit(&atgep->atge_intr_lock);
787*11353SSaurabh.Mishra@Sun.COM return (DDI_INTR_UNCLAIMED);
788*11353SSaurabh.Mishra@Sun.COM }
789*11353SSaurabh.Mishra@Sun.COM
790*11353SSaurabh.Mishra@Sun.COM status = INL(atgep, ATGE_INTR_STATUS);
791*11353SSaurabh.Mishra@Sun.COM if (status == 0 || (status & atgep->atge_intrs) == 0) {
792*11353SSaurabh.Mishra@Sun.COM mutex_exit(&atgep->atge_intr_lock);
793*11353SSaurabh.Mishra@Sun.COM
794*11353SSaurabh.Mishra@Sun.COM if (atgep->atge_flags & ATGE_FIXED_TYPE)
795*11353SSaurabh.Mishra@Sun.COM return (DDI_INTR_UNCLAIMED);
796*11353SSaurabh.Mishra@Sun.COM
797*11353SSaurabh.Mishra@Sun.COM return (DDI_INTR_CLAIMED);
798*11353SSaurabh.Mishra@Sun.COM }
799*11353SSaurabh.Mishra@Sun.COM
800*11353SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() entry status : %x",
801*11353SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__, status));
802*11353SSaurabh.Mishra@Sun.COM
803*11353SSaurabh.Mishra@Sun.COM /*
804*11353SSaurabh.Mishra@Sun.COM * Disable interrupts.
805*11353SSaurabh.Mishra@Sun.COM */
806*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_INTR_STATUS, status | INTR_DIS_INT);
807*11353SSaurabh.Mishra@Sun.COM FLUSH(atgep, ATGE_INTR_STATUS);
808*11353SSaurabh.Mishra@Sun.COM
809*11353SSaurabh.Mishra@Sun.COM /*
810*11353SSaurabh.Mishra@Sun.COM * Check if chip is running, only then do the work.
811*11353SSaurabh.Mishra@Sun.COM */
812*11353SSaurabh.Mishra@Sun.COM if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) {
813*11353SSaurabh.Mishra@Sun.COM atge_l1_data_t *l1;
814*11353SSaurabh.Mishra@Sun.COM l1_cmb_t *cmb;
815*11353SSaurabh.Mishra@Sun.COM
816*11353SSaurabh.Mishra@Sun.COM l1 = atgep->atge_private_data;
817*11353SSaurabh.Mishra@Sun.COM
818*11353SSaurabh.Mishra@Sun.COM DMA_SYNC(l1->atge_l1_cmb, 0, L1_CMB_BLOCK_SZ,
819*11353SSaurabh.Mishra@Sun.COM DDI_DMA_SYNC_FORKERNEL);
820*11353SSaurabh.Mishra@Sun.COM
821*11353SSaurabh.Mishra@Sun.COM cmb = (l1_cmb_t *)l1->atge_l1_cmb->addr;
822*11353SSaurabh.Mishra@Sun.COM l1->atge_l1_intr_status =
823*11353SSaurabh.Mishra@Sun.COM ATGE_GET32(l1->atge_l1_cmb, &cmb->intr_status);
824*11353SSaurabh.Mishra@Sun.COM l1->atge_l1_rx_prod_cons =
825*11353SSaurabh.Mishra@Sun.COM (ATGE_GET32(l1->atge_l1_cmb, &cmb->rx_prod_cons) &
826*11353SSaurabh.Mishra@Sun.COM RRD_PROD_MASK) >> RRD_PROD_SHIFT;
827*11353SSaurabh.Mishra@Sun.COM l1->atge_l1_tx_prod_cons =
828*11353SSaurabh.Mishra@Sun.COM (ATGE_GET32(l1->atge_l1_cmb, &cmb->tx_prod_cons) &
829*11353SSaurabh.Mishra@Sun.COM TPD_CONS_MASK) >> TPD_CONS_SHIFT;
830*11353SSaurabh.Mishra@Sun.COM
831*11353SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() atge_l1_intr_status : %x, "
832*11353SSaurabh.Mishra@Sun.COM "atge_l1_rx_prod_cons : %d, atge_l1_tx_prod_cons : %d"
833*11353SSaurabh.Mishra@Sun.COM " atge_l1_rr_consumers : %d",
834*11353SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__, l1->atge_l1_intr_status,
835*11353SSaurabh.Mishra@Sun.COM l1->atge_l1_rx_prod_cons, l1->atge_l1_tx_prod_cons,
836*11353SSaurabh.Mishra@Sun.COM l1->atge_l1_rr_consumers));
837*11353SSaurabh.Mishra@Sun.COM
838*11353SSaurabh.Mishra@Sun.COM /*
839*11353SSaurabh.Mishra@Sun.COM * Inform the hardware that CMB was served.
840*11353SSaurabh.Mishra@Sun.COM */
841*11353SSaurabh.Mishra@Sun.COM cmb->intr_status = 0;
842*11353SSaurabh.Mishra@Sun.COM DMA_SYNC(l1->atge_l1_cmb, 0, L1_CMB_BLOCK_SZ,
843*11353SSaurabh.Mishra@Sun.COM DDI_DMA_SYNC_FORDEV);
844*11353SSaurabh.Mishra@Sun.COM
845*11353SSaurabh.Mishra@Sun.COM /*
846*11353SSaurabh.Mishra@Sun.COM * We must check for RX Overflow condition and restart the
847*11353SSaurabh.Mishra@Sun.COM * chip. This needs to be done only when producer and consumer
848*11353SSaurabh.Mishra@Sun.COM * counters are same for the RR ring (Return RX).
849*11353SSaurabh.Mishra@Sun.COM */
850*11353SSaurabh.Mishra@Sun.COM if ((l1->atge_l1_intr_status & (INTR_CMB_RX | INTR_MAC_RX)) &&
851*11353SSaurabh.Mishra@Sun.COM (l1->atge_l1_intr_status &
852*11353SSaurabh.Mishra@Sun.COM (INTR_RX_FIFO_OFLOW | INTR_RRD_OFLOW) &&
853*11353SSaurabh.Mishra@Sun.COM (l1->atge_l1_rr_consumers == l1->atge_l1_rx_prod_cons))) {
854*11353SSaurabh.Mishra@Sun.COM
855*11353SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() RX OVERFLOW :"
856*11353SSaurabh.Mishra@Sun.COM " atge_l1_rx_prod_cons : %d,"
857*11353SSaurabh.Mishra@Sun.COM " l1->atge_l1_rr_consumers : %d",
858*11353SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__,
859*11353SSaurabh.Mishra@Sun.COM l1->atge_l1_rx_prod_cons,
860*11353SSaurabh.Mishra@Sun.COM l1->atge_l1_rr_consumers));
861*11353SSaurabh.Mishra@Sun.COM
862*11353SSaurabh.Mishra@Sun.COM mutex_enter(&atgep->atge_tx_lock);
863*11353SSaurabh.Mishra@Sun.COM atge_device_restart(atgep);
864*11353SSaurabh.Mishra@Sun.COM mutex_exit(&atgep->atge_tx_lock);
865*11353SSaurabh.Mishra@Sun.COM goto done;
866*11353SSaurabh.Mishra@Sun.COM }
867*11353SSaurabh.Mishra@Sun.COM
868*11353SSaurabh.Mishra@Sun.COM rx_head = atge_l1_rx(atgep);
869*11353SSaurabh.Mishra@Sun.COM
870*11353SSaurabh.Mishra@Sun.COM if (l1->atge_l1_intr_status & INTR_SMB)
871*11353SSaurabh.Mishra@Sun.COM atge_l1_gather_stats(atgep);
872*11353SSaurabh.Mishra@Sun.COM
873*11353SSaurabh.Mishra@Sun.COM if (l1->atge_l1_intr_status & (INTR_CMB_TX | INTR_MAC_TX)) {
874*11353SSaurabh.Mishra@Sun.COM mutex_enter(&atgep->atge_tx_lock);
875*11353SSaurabh.Mishra@Sun.COM atge_tx_reclaim(atgep, l1->atge_l1_tx_prod_cons);
876*11353SSaurabh.Mishra@Sun.COM if (atgep->atge_tx_resched) {
877*11353SSaurabh.Mishra@Sun.COM atgep->atge_tx_resched = 0;
878*11353SSaurabh.Mishra@Sun.COM resched = 1;
879*11353SSaurabh.Mishra@Sun.COM }
880*11353SSaurabh.Mishra@Sun.COM
881*11353SSaurabh.Mishra@Sun.COM mutex_exit(&atgep->atge_tx_lock);
882*11353SSaurabh.Mishra@Sun.COM }
883*11353SSaurabh.Mishra@Sun.COM
884*11353SSaurabh.Mishra@Sun.COM if ((status & (INTR_DMA_RD_TO_RST | INTR_DMA_WR_TO_RST)) != 0) {
885*11353SSaurabh.Mishra@Sun.COM atge_error(atgep->atge_dip,
886*11353SSaurabh.Mishra@Sun.COM "DMA transfer error");
887*11353SSaurabh.Mishra@Sun.COM
888*11353SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() DMA transfer error",
889*11353SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__));
890*11353SSaurabh.Mishra@Sun.COM
891*11353SSaurabh.Mishra@Sun.COM atge_device_stop(atgep);
892*11353SSaurabh.Mishra@Sun.COM goto done;
893*11353SSaurabh.Mishra@Sun.COM }
894*11353SSaurabh.Mishra@Sun.COM }
895*11353SSaurabh.Mishra@Sun.COM
896*11353SSaurabh.Mishra@Sun.COM done:
897*11353SSaurabh.Mishra@Sun.COM
898*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_INTR_STATUS, INTR_DIS_DMA | INTR_DIS_SM);
899*11353SSaurabh.Mishra@Sun.COM mutex_exit(&atgep->atge_intr_lock);
900*11353SSaurabh.Mishra@Sun.COM
901*11353SSaurabh.Mishra@Sun.COM if (status & INTR_GPHY || atgep->atge_flags & ATGE_MII_CHECK) {
902*11353SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() MII_CHECK Requested",
903*11353SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__));
904*11353SSaurabh.Mishra@Sun.COM
905*11353SSaurabh.Mishra@Sun.COM if (status & INTR_GPHY) {
906*11353SSaurabh.Mishra@Sun.COM (void) atge_mii_read(atgep,
907*11353SSaurabh.Mishra@Sun.COM atgep->atge_phyaddr, ATGE_ISR_ACK_GPHY);
908*11353SSaurabh.Mishra@Sun.COM }
909*11353SSaurabh.Mishra@Sun.COM
910*11353SSaurabh.Mishra@Sun.COM atgep->atge_flags &= ~ATGE_MII_CHECK;
911*11353SSaurabh.Mishra@Sun.COM mii_reset(atgep->atge_mii);
912*11353SSaurabh.Mishra@Sun.COM }
913*11353SSaurabh.Mishra@Sun.COM
914*11353SSaurabh.Mishra@Sun.COM /*
915*11353SSaurabh.Mishra@Sun.COM * Pass the list of packets received from chip to MAC layer.
916*11353SSaurabh.Mishra@Sun.COM */
917*11353SSaurabh.Mishra@Sun.COM if (rx_head) {
918*11353SSaurabh.Mishra@Sun.COM mac_rx(atgep->atge_mh, 0, rx_head);
919*11353SSaurabh.Mishra@Sun.COM }
920*11353SSaurabh.Mishra@Sun.COM
921*11353SSaurabh.Mishra@Sun.COM if (rx_head1) {
922*11353SSaurabh.Mishra@Sun.COM mac_rx(atgep->atge_mh, 0, rx_head1);
923*11353SSaurabh.Mishra@Sun.COM }
924*11353SSaurabh.Mishra@Sun.COM
925*11353SSaurabh.Mishra@Sun.COM /*
926*11353SSaurabh.Mishra@Sun.COM * Let MAC start sending pkts if the downstream was asked to pause.
927*11353SSaurabh.Mishra@Sun.COM */
928*11353SSaurabh.Mishra@Sun.COM if (resched)
929*11353SSaurabh.Mishra@Sun.COM mac_tx_update(atgep->atge_mh);
930*11353SSaurabh.Mishra@Sun.COM
931*11353SSaurabh.Mishra@Sun.COM return (DDI_INTR_CLAIMED);
932*11353SSaurabh.Mishra@Sun.COM }
933*11353SSaurabh.Mishra@Sun.COM
934*11353SSaurabh.Mishra@Sun.COM void
atge_l1_send_packet(atge_ring_t * r)935*11353SSaurabh.Mishra@Sun.COM atge_l1_send_packet(atge_ring_t *r)
936*11353SSaurabh.Mishra@Sun.COM {
937*11353SSaurabh.Mishra@Sun.COM atge_l1_sync_mbox(r->r_atge);
938*11353SSaurabh.Mishra@Sun.COM }
939