4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2012 Gary Mills
25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
29 * Copyright (c) 2009, Pyun YongHyeon <yongari@FreeBSD.org>
30 * All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice unmodified, this list of conditions, and the following
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 #include <sys/types.h>
56 #include <sys/stream.h>
57 #include <sys/strsun.h>
59 #include <sys/modctl.h>
60 #include <sys/ethernet.h>
61 #include <sys/debug.h>
64 #include <sys/miiregs.h>
65 #include <sys/sysmacros.h>
66 #include <sys/dditypes.h>
68 #include <sys/sunddi.h>
69 #include <sys/byteorder.h>
72 #include <sys/stream.h>
75 #include "atge_l1c_reg.h"
76 #include "atge_cmn_reg.h"
78 static ddi_dma_attr_t atge_l1c_dma_attr_tx_desc
= {
79 DMA_ATTR_V0
, /* dma_attr_version */
80 0, /* dma_attr_addr_lo */
81 0x0000ffffffffull
, /* dma_attr_addr_hi */
82 0x0000ffffffffull
, /* dma_attr_count_max */
83 L1C_TX_RING_ALIGN
, /* dma_attr_align */
84 0x0000fffc, /* dma_attr_burstsizes */
85 1, /* dma_attr_minxfer */
86 0x0000ffffffffull
, /* dma_attr_maxxfer */
87 0x0000ffffffffull
, /* dma_attr_seg */
88 1, /* dma_attr_sgllen */
89 1, /* dma_attr_granular */
90 0 /* dma_attr_flags */
93 static ddi_dma_attr_t atge_l1c_dma_attr_rx_desc
= {
94 DMA_ATTR_V0
, /* dma_attr_version */
95 0, /* dma_attr_addr_lo */
96 0x0000ffffffffull
, /* dma_attr_addr_hi */
97 0x0000ffffffffull
, /* dma_attr_count_max */
98 L1C_RX_RING_ALIGN
, /* dma_attr_align */
99 0x0000fffc, /* dma_attr_burstsizes */
100 1, /* dma_attr_minxfer */
101 0x0000ffffffffull
, /* dma_attr_maxxfer */
102 0x0000ffffffffull
, /* dma_attr_seg */
103 1, /* dma_attr_sgllen */
104 1, /* dma_attr_granular */
105 0 /* dma_attr_flags */
108 static ddi_dma_attr_t atge_l1c_dma_attr_cmb
= {
109 DMA_ATTR_V0
, /* dma_attr_version */
110 0, /* dma_attr_addr_lo */
111 0x0000ffffffffull
, /* dma_attr_addr_hi */
112 0x0000ffffffffull
, /* dma_attr_count_max */
113 L1C_CMB_ALIGN
, /* dma_attr_align */
114 0x0000fffc, /* dma_attr_burstsizes */
115 1, /* dma_attr_minxfer */
116 0x0000ffffffffull
, /* dma_attr_maxxfer */
117 0x0000ffffffffull
, /* dma_attr_seg */
118 1, /* dma_attr_sgllen */
119 1, /* dma_attr_granular */
120 0 /* dma_attr_flags */
123 static ddi_dma_attr_t atge_l1c_dma_attr_smb
= {
124 DMA_ATTR_V0
, /* dma_attr_version */
125 0, /* dma_attr_addr_lo */
126 0x0000ffffffffull
, /* dma_attr_addr_hi */
127 0x0000ffffffffull
, /* dma_attr_count_max */
128 L1C_SMB_ALIGN
, /* dma_attr_align */
129 0x0000fffc, /* dma_attr_burstsizes */
130 1, /* dma_attr_minxfer */
131 0x0000ffffffffull
, /* dma_attr_maxxfer */
132 0x0000ffffffffull
, /* dma_attr_seg */
133 1, /* dma_attr_sgllen */
134 1, /* dma_attr_granular */
135 0 /* dma_attr_flags */
138 static ddi_dma_attr_t atge_l1c_dma_attr_rr
= {
139 DMA_ATTR_V0
, /* dma_attr_version */
140 0, /* dma_attr_addr_lo */
141 0x0000ffffffffull
, /* dma_attr_addr_hi */
142 0x0000ffffffffull
, /* dma_attr_count_max */
143 L1C_RR_RING_ALIGN
, /* dma_attr_align */
144 0x0000fffc, /* dma_attr_burstsizes */
145 1, /* dma_attr_minxfer */
146 0x0000ffffffffull
, /* dma_attr_maxxfer */
147 0x0000ffffffffull
, /* dma_attr_seg */
148 1, /* dma_attr_sgllen */
149 1, /* dma_attr_granular */
150 0 /* dma_attr_flags */
154 atge_l1c_alloc_dma(atge_t
*atgep
)
156 atge_l1c_data_t
*l1c
;
160 l1c
= kmem_zalloc(sizeof (atge_l1c_data_t
), KM_SLEEP
);
161 atgep
->atge_private_data
= l1c
;
164 * Allocate TX ring descriptor.
166 atgep
->atge_tx_buf_len
= atgep
->atge_mtu
+
167 sizeof (struct ether_header
) + VLAN_TAGSZ
+ ETHERFCSL
;
168 atgep
->atge_tx_ring
= kmem_alloc(sizeof (atge_ring_t
), KM_SLEEP
);
169 atgep
->atge_tx_ring
->r_atge
= atgep
;
170 atgep
->atge_tx_ring
->r_desc_ring
= NULL
;
171 dma
= atge_alloc_a_dma_blk(atgep
, &atge_l1c_dma_attr_tx_desc
,
172 ATGE_TX_RING_SZ
, DDI_DMA_RDWR
);
174 atge_error(atgep
->atge_dip
, "DMA allocation failed for TX"
176 return (DDI_FAILURE
);
178 atgep
->atge_tx_ring
->r_desc_ring
= dma
;
181 * Allocate DMA buffers for TX ring.
183 err
= atge_alloc_buffers(atgep
->atge_tx_ring
, ATGE_TX_RING_CNT
,
184 atgep
->atge_tx_buf_len
, DDI_DMA_WRITE
);
185 if (err
!= DDI_SUCCESS
) {
186 atge_error(atgep
->atge_dip
, "DMA allocation failed for"
194 atgep
->atge_rx_buf_len
= atgep
->atge_mtu
+
195 sizeof (struct ether_header
) + VLAN_TAGSZ
+ ETHERFCSL
;
196 l1c
->atge_rx_ring
= kmem_alloc(sizeof (atge_ring_t
), KM_SLEEP
);
197 l1c
->atge_rx_ring
->r_atge
= atgep
;
198 l1c
->atge_rx_ring
->r_desc_ring
= NULL
;
199 dma
= atge_alloc_a_dma_blk(atgep
, &atge_l1c_dma_attr_rx_desc
,
200 L1C_RX_RING_SZ
, DDI_DMA_RDWR
);
202 atge_error(atgep
->atge_dip
, "DMA allocation failed"
204 return (DDI_FAILURE
);
206 l1c
->atge_rx_ring
->r_desc_ring
= dma
;
209 * Allocate DMA buffers for RX ring.
211 err
= atge_alloc_buffers(l1c
->atge_rx_ring
, L1C_RX_RING_CNT
,
212 atgep
->atge_rx_buf_len
, DDI_DMA_READ
);
213 if (err
!= DDI_SUCCESS
) {
214 atge_error(atgep
->atge_dip
, "DMA allocation failed for"
220 * Allocate CMB used for fetching interrupt status data.
222 ATGE_DB(("%s: %s() L1C_CMB_BLOCK_SZ : 0x%x", atgep
->atge_name
,
223 __func__
, L1C_CMB_BLOCK_SZ
));
225 dma
= atge_alloc_a_dma_blk(atgep
, &atge_l1c_dma_attr_cmb
,
226 L1C_CMB_BLOCK_SZ
, DDI_DMA_RDWR
);
227 l1c
->atge_l1c_cmb
= dma
;
229 atge_error(atgep
->atge_dip
, "DMA allocation failed for CMB");
230 return (DDI_FAILURE
);
234 * RR ring (Return Ring for RX and TX).
236 ATGE_DB(("%s: %s() L1C_RR_RING_SZ : 0x%x", atgep
->atge_name
,
237 __func__
, L1C_RR_RING_SZ
));
239 dma
= atge_alloc_a_dma_blk(atgep
, &atge_l1c_dma_attr_rr
,
240 L1C_RR_RING_SZ
, DDI_DMA_RDWR
);
241 l1c
->atge_l1c_rr
= dma
;
243 atge_error(atgep
->atge_dip
, "DMA allocation failed"
245 return (DDI_FAILURE
);
249 * SMB for statistics.
251 ATGE_DB(("%s: %s() L1C_SMB_BLOCK_SZ : 0x%x", atgep
->atge_name
,
252 __func__
, L1C_SMB_BLOCK_SZ
));
254 dma
= atge_alloc_a_dma_blk(atgep
, &atge_l1c_dma_attr_smb
,
255 L1C_SMB_BLOCK_SZ
, DDI_DMA_RDWR
);
256 l1c
->atge_l1c_smb
= dma
;
258 atge_error(atgep
->atge_dip
, "DMA allocation failed for SMB");
259 return (DDI_FAILURE
);
262 atgep
->atge_hw_stats
= kmem_zalloc(sizeof (atge_l1c_smb_t
), KM_SLEEP
);
264 return (DDI_SUCCESS
);
268 atge_l1c_free_dma(atge_t
*atgep
)
270 atge_l1c_data_t
*l1c
;
272 l1c
= atgep
->atge_private_data
;
277 if (atgep
->atge_tx_ring
!= NULL
) {
278 atge_free_buffers(atgep
->atge_tx_ring
, ATGE_TX_RING_CNT
);
280 if (atgep
->atge_tx_ring
->r_desc_ring
!= NULL
) {
281 atge_free_a_dma_blk(atgep
->atge_tx_ring
->r_desc_ring
);
284 kmem_free(atgep
->atge_tx_ring
, sizeof (atge_ring_t
));
285 atgep
->atge_tx_ring
= NULL
;
288 if (l1c
&& l1c
->atge_l1c_cmb
!= NULL
) {
289 atge_free_a_dma_blk(l1c
->atge_l1c_cmb
);
290 l1c
->atge_l1c_cmb
= NULL
;
293 if (l1c
&& l1c
->atge_l1c_rr
!= NULL
) {
294 atge_free_a_dma_blk(l1c
->atge_l1c_rr
);
295 l1c
->atge_l1c_rr
= NULL
;
298 if (l1c
&& l1c
->atge_l1c_smb
!= NULL
) {
299 atge_free_a_dma_blk(l1c
->atge_l1c_smb
);
300 l1c
->atge_l1c_smb
= NULL
;
306 if (l1c
&& l1c
->atge_rx_ring
!= NULL
) {
307 atge_free_buffers(l1c
->atge_rx_ring
, L1C_RX_RING_CNT
);
309 if (l1c
->atge_rx_ring
->r_desc_ring
!= NULL
) {
310 atge_free_a_dma_blk(l1c
->atge_rx_ring
->r_desc_ring
);
313 kmem_free(l1c
->atge_rx_ring
, sizeof (atge_ring_t
));
314 l1c
->atge_rx_ring
= NULL
;
318 * Free the memory allocated for gathering hw stats.
320 if (atgep
->atge_hw_stats
!= NULL
) {
321 kmem_free(atgep
->atge_hw_stats
, sizeof (atge_l1c_smb_t
));
322 atgep
->atge_hw_stats
= NULL
;
326 * Free the private area.
329 kmem_free(l1c
, sizeof (atge_l1c_data_t
));
330 atgep
->atge_private_data
= NULL
;
335 atge_l1c_init_rx_ring(atge_t
*atgep
)
337 atge_l1c_data_t
*l1c
;
342 l1c
= atgep
->atge_private_data
;
343 l1c
->atge_rx_ring
->r_consumer
= L1C_RX_RING_CNT
- 1;
344 dma
= l1c
->atge_rx_ring
->r_desc_ring
;
345 bzero(dma
->addr
, L1C_RX_RING_SZ
);
347 for (i
= 0; i
< L1C_RX_RING_CNT
; i
++) {
348 rx
= (l1c_rx_desc_t
*)(dma
->addr
+
349 (i
* sizeof (l1c_rx_desc_t
)));
351 ATGE_PUT64(dma
, &rx
->addr
,
352 l1c
->atge_rx_ring
->r_buf_tbl
[i
]->cookie
.dmac_laddress
);
353 /* No length field. */
356 DMA_SYNC(dma
, 0, 0, DDI_DMA_SYNC_FORDEV
);
357 /* Let controller know availability of new Rx buffers. */
358 OUTL(atgep
, ATGE_MBOX_RD0_PROD_IDX
, l1c
->atge_rx_ring
->r_consumer
);
362 atge_l1c_init_tx_ring(atge_t
*atgep
)
364 atgep
->atge_tx_ring
->r_producer
= 0;
365 atgep
->atge_tx_ring
->r_consumer
= 0;
366 atgep
->atge_tx_ring
->r_avail_desc
= ATGE_TX_RING_CNT
;
368 bzero(atgep
->atge_tx_ring
->r_desc_ring
->addr
, ATGE_TX_RING_SZ
);
369 DMA_SYNC(atgep
->atge_tx_ring
->r_desc_ring
, 0, 0, DDI_DMA_SYNC_FORDEV
);
373 atge_l1c_init_rr_ring(atge_t
*atgep
)
375 atge_l1c_data_t
*l1c
;
378 l1c
= atgep
->atge_private_data
;
379 l1c
->atge_l1c_rr_consumers
= 0;
381 dma
= l1c
->atge_l1c_rr
;
382 bzero(dma
->addr
, L1C_RR_RING_SZ
);
383 DMA_SYNC(dma
, 0, 0, DDI_DMA_SYNC_FORDEV
);
387 atge_l1c_init_smb(atge_t
*atgep
)
389 atge_l1c_data_t
*l1c
;
392 l1c
= atgep
->atge_private_data
;
393 dma
= l1c
->atge_l1c_smb
;
394 bzero(dma
->addr
, L1C_SMB_BLOCK_SZ
);
395 DMA_SYNC(dma
, 0, 0, DDI_DMA_SYNC_FORDEV
);
399 atge_l1c_init_cmb(atge_t
*atgep
)
401 atge_l1c_data_t
*l1c
;
404 l1c
= atgep
->atge_private_data
;
405 dma
= l1c
->atge_l1c_cmb
;
406 bzero(dma
->addr
, L1C_CMB_BLOCK_SZ
);
407 DMA_SYNC(dma
, 0, 0, DDI_DMA_SYNC_FORDEV
);
411 atge_l1c_program_dma(atge_t
*atgep
)
413 atge_l1c_data_t
*l1c
;
417 l1c
= atgep
->atge_private_data
;
420 * Clear WOL status and disable all WOL feature as WOL
421 * would interfere Rx operation under normal environments.
423 (void) INL(atgep
, ATGE_WOL_CFG
);
424 OUTL(atgep
, ATGE_WOL_CFG
, 0);
427 r
= atgep
->atge_tx_ring
;
428 OUTL(atgep
, L1C_TX_BASE_ADDR_HI
,
429 ATGE_ADDR_HI(r
->r_desc_ring
->cookie
.dmac_laddress
));
430 OUTL(atgep
, L1C_TDL_HEAD_ADDR_LO
,
431 ATGE_ADDR_LO(r
->r_desc_ring
->cookie
.dmac_laddress
));
432 /* We don't use high priority ring. */
433 OUTL(atgep
, L1C_TDH_HEAD_ADDR_LO
, 0);
436 r
= l1c
->atge_rx_ring
;
437 OUTL(atgep
, L1C_RX_BASE_ADDR_HI
,
438 ATGE_ADDR_HI(r
->r_desc_ring
->cookie
.dmac_laddress
));
439 OUTL(atgep
, L1C_RD0_HEAD_ADDR_LO
,
440 ATGE_ADDR_LO(r
->r_desc_ring
->cookie
.dmac_laddress
));
441 /* We use one Rx ring. */
442 OUTL(atgep
, L1C_RD1_HEAD_ADDR_LO
, 0);
443 OUTL(atgep
, L1C_RD2_HEAD_ADDR_LO
, 0);
444 OUTL(atgep
, L1C_RD3_HEAD_ADDR_LO
, 0);
448 * Let hardware split jumbo frames into alc_max_buf_sized chunks.
449 * if it do not fit the buffer size. Rx return descriptor holds
450 * a counter that indicates how many fragments were made by the
451 * hardware. The buffer size should be multiple of 8 bytes.
452 * Since hardware has limit on the size of buffer size, always
453 * use the maximum value.
454 * For strict-alignment architectures make sure to reduce buffer
455 * size by 8 bytes to make room for alignment fixup.
457 OUTL(atgep
, L1C_RX_BUF_SIZE
, RX_BUF_SIZE_MAX
); /* XXX */
459 /* Set Rx return descriptor base addresses. */
460 OUTL(atgep
, L1C_RRD0_HEAD_ADDR_LO
,
461 ATGE_ADDR_LO(l1c
->atge_l1c_rr
->cookie
.dmac_laddress
));
462 /* We use one Rx return ring. */
463 OUTL(atgep
, L1C_RRD1_HEAD_ADDR_LO
, 0);
464 OUTL(atgep
, L1C_RRD2_HEAD_ADDR_LO
, 0);
465 OUTL(atgep
, L1C_RRD3_HEAD_ADDR_LO
, 0);
468 OUTL(atgep
, L1C_CMB_BASE_ADDR_LO
,
469 ATGE_ADDR_LO(l1c
->atge_l1c_cmb
->cookie
.dmac_laddress
));
472 OUTL(atgep
, L1C_SMB_BASE_ADDR_HI
,
473 ATGE_ADDR_HI(l1c
->atge_l1c_smb
->cookie
.dmac_laddress
));
474 OUTL(atgep
, L1C_SMB_BASE_ADDR_LO
,
475 ATGE_ADDR_LO(l1c
->atge_l1c_smb
->cookie
.dmac_laddress
));
478 * Set RX return ring (RR) counter.
480 /* Set Rx descriptor counter. */
481 OUTL(atgep
, L1C_RD_RING_CNT
,
482 (L1C_RX_RING_CNT
<< RD_RING_CNT_SHIFT
) & RD_RING_CNT_MASK
);
483 /* Set Rx return descriptor counter. */
484 OUTL(atgep
, L1C_RRD_RING_CNT
,
485 (L1C_RR_RING_CNT
<< RRD_RING_CNT_SHIFT
) & RRD_RING_CNT_MASK
);
488 * Set TX descriptor counter.
490 OUTL(atgep
, L1C_TD_RING_CNT
,
491 (ATGE_TX_RING_CNT
<< TD_RING_CNT_SHIFT
) & TD_RING_CNT_MASK
);
493 switch (ATGE_DID(atgep
)) {
494 case ATGE_CHIP_AR8152V1_DEV_ID
:
495 /* Reconfigure SRAM - Vendor magic. */
496 OUTL(atgep
, L1C_SRAM_RX_FIFO_LEN
, 0x000002A0);
497 OUTL(atgep
, L1C_SRAM_TX_FIFO_LEN
, 0x00000100);
498 OUTL(atgep
, L1C_SRAM_RX_FIFO_ADDR
, 0x029F0000);
499 OUTL(atgep
, L1C_SRAM_RD_ADDR
, 0x02BF02A0);
500 OUTL(atgep
, L1C_SRAM_TX_FIFO_ADDR
, 0x03BF02C0);
501 OUTL(atgep
, L1C_SRAM_TRD_ADDR
, 0x03DF03C0);
502 OUTL(atgep
, L1C_TXF_WATER_MARK
, 0x00000000);
503 OUTL(atgep
, L1C_RD_DMA_CFG
, 0x00000000);
508 * Inform hardware that we have loaded DMA registers.
510 OUTL(atgep
, ATGE_DMA_BLOCK
, DMA_BLOCK_LOAD
);
512 /* Configure interrupt moderation timer. */
513 reg
= ATGE_USECS(atgep
->atge_int_rx_mod
) << IM_TIMER_RX_SHIFT
;
514 reg
|= ATGE_USECS(atgep
->atge_int_tx_mod
) << IM_TIMER_TX_SHIFT
;
515 OUTL(atgep
, ATGE_IM_TIMER
, reg
);
517 * We don't want to automatic interrupt clear as task queue
518 * for the interrupt should know interrupt status.
521 if (ATGE_USECS(atgep
->atge_int_rx_mod
) != 0)
522 reg
|= MASTER_IM_RX_TIMER_ENB
;
523 if (ATGE_USECS(atgep
->atge_int_tx_mod
) != 0)
524 reg
|= MASTER_IM_TX_TIMER_ENB
;
525 OUTL(atgep
, ATGE_MASTER_CFG
, reg
);
529 atge_l1c_clear_stats(atge_t
*atgep
)
536 * Clear RX stats first.
539 reg
= &smb
.rx_frames
;
540 while (reg
++ <= &smb
.rx_pkts_filtered
) {
541 (void) INL(atgep
, ATGE_RX_MIB_BASE
+ i
);
542 i
+= sizeof (uint32_t);
549 reg
= &smb
.tx_frames
;
550 while (reg
++ <= &smb
.tx_mcast_bytes
) {
551 (void) INL(atgep
, ATGE_TX_MIB_BASE
+ i
);
552 i
+= sizeof (uint32_t);
557 atge_l1c_gather_stats(atge_t
*atgep
)
559 atge_l1c_data_t
*l1c
;
561 atge_l1c_smb_t
*stat
;
564 ASSERT(atgep
!= NULL
);
566 l1c
= atgep
->atge_private_data
;
567 dma
= l1c
->atge_l1c_smb
;
568 DMA_SYNC(dma
, 0, 0, DDI_DMA_SYNC_FORKERNEL
);
569 stat
= (atge_l1c_smb_t
*)atgep
->atge_hw_stats
;
570 smb
= (atge_l1c_smb_t
*)dma
->addr
;
573 stat
->rx_frames
+= smb
->rx_frames
;
574 stat
->rx_bcast_frames
+= smb
->rx_bcast_frames
;
575 stat
->rx_mcast_frames
+= smb
->rx_mcast_frames
;
576 stat
->rx_pause_frames
+= smb
->rx_pause_frames
;
577 stat
->rx_control_frames
+= smb
->rx_control_frames
;
578 stat
->rx_crcerrs
+= smb
->rx_crcerrs
;
579 stat
->rx_lenerrs
+= smb
->rx_lenerrs
;
580 stat
->rx_bytes
+= smb
->rx_bytes
;
581 stat
->rx_runts
+= smb
->rx_runts
;
582 stat
->rx_fragments
+= smb
->rx_fragments
;
583 stat
->rx_pkts_64
+= smb
->rx_pkts_64
;
584 stat
->rx_pkts_65_127
+= smb
->rx_pkts_65_127
;
585 stat
->rx_pkts_128_255
+= smb
->rx_pkts_128_255
;
586 stat
->rx_pkts_256_511
+= smb
->rx_pkts_256_511
;
587 stat
->rx_pkts_512_1023
+= smb
->rx_pkts_512_1023
;
588 stat
->rx_pkts_1024_1518
+= smb
->rx_pkts_1024_1518
;
589 stat
->rx_pkts_1519_max
+= smb
->rx_pkts_1519_max
;
590 stat
->rx_pkts_truncated
+= smb
->rx_pkts_truncated
;
591 stat
->rx_fifo_oflows
+= smb
->rx_fifo_oflows
;
592 stat
->rx_alignerrs
+= smb
->rx_alignerrs
;
593 stat
->rx_bcast_bytes
+= smb
->rx_bcast_bytes
;
594 stat
->rx_mcast_bytes
+= smb
->rx_mcast_bytes
;
595 stat
->rx_pkts_filtered
+= smb
->rx_pkts_filtered
;
598 stat
->tx_frames
+= smb
->tx_frames
;
599 stat
->tx_bcast_frames
+= smb
->tx_bcast_frames
;
600 stat
->tx_mcast_frames
+= smb
->tx_mcast_frames
;
601 stat
->tx_pause_frames
+= smb
->tx_pause_frames
;
602 stat
->tx_excess_defer
+= smb
->tx_excess_defer
;
603 stat
->tx_control_frames
+= smb
->tx_control_frames
;
604 stat
->tx_deferred
+= smb
->tx_deferred
;
605 stat
->tx_bytes
+= smb
->tx_bytes
;
606 stat
->tx_pkts_64
+= smb
->tx_pkts_64
;
607 stat
->tx_pkts_65_127
+= smb
->tx_pkts_65_127
;
608 stat
->tx_pkts_128_255
+= smb
->tx_pkts_128_255
;
609 stat
->tx_pkts_256_511
+= smb
->tx_pkts_256_511
;
610 stat
->tx_pkts_512_1023
+= smb
->tx_pkts_512_1023
;
611 stat
->tx_pkts_1024_1518
+= smb
->tx_pkts_1024_1518
;
612 stat
->tx_pkts_1519_max
+= smb
->tx_pkts_1519_max
;
613 stat
->tx_single_colls
+= smb
->tx_single_colls
;
614 stat
->tx_multi_colls
+= smb
->tx_multi_colls
;
615 stat
->tx_late_colls
+= smb
->tx_late_colls
;
616 stat
->tx_excess_colls
+= smb
->tx_excess_colls
;
617 stat
->tx_underrun
+= smb
->tx_underrun
;
618 stat
->tx_desc_underrun
+= smb
->tx_desc_underrun
;
619 stat
->tx_lenerrs
+= smb
->tx_lenerrs
;
620 stat
->tx_pkts_truncated
+= smb
->tx_pkts_truncated
;
621 stat
->tx_bcast_bytes
+= smb
->tx_bcast_bytes
;
622 stat
->tx_mcast_bytes
+= smb
->tx_mcast_bytes
;
625 * Update global counters in atge_t.
627 atgep
->atge_brdcstrcv
+= smb
->rx_bcast_frames
;
628 atgep
->atge_multircv
+= smb
->rx_mcast_frames
;
629 atgep
->atge_multixmt
+= smb
->tx_mcast_frames
;
630 atgep
->atge_brdcstxmt
+= smb
->tx_bcast_frames
;
632 atgep
->atge_align_errors
+= smb
->rx_alignerrs
;
633 atgep
->atge_fcs_errors
+= smb
->rx_crcerrs
;
634 atgep
->atge_defer_xmts
+= smb
->tx_deferred
;
635 atgep
->atge_first_collisions
+= smb
->tx_single_colls
;
636 atgep
->atge_multi_collisions
+= smb
->tx_multi_colls
* 2;
637 atgep
->atge_tx_late_collisions
+= smb
->tx_late_colls
;
638 atgep
->atge_ex_collisions
+= smb
->tx_excess_colls
;
639 atgep
->atge_toolong_errors
+= smb
->rx_lenerrs
;
640 atgep
->atge_overflow
+= smb
->rx_fifo_oflows
;
641 atgep
->atge_underflow
+= (smb
->tx_underrun
+ smb
->tx_desc_underrun
);
642 atgep
->atge_runt
+= smb
->rx_runts
;
645 atgep
->atge_collisions
+= smb
->tx_single_colls
+
646 smb
->tx_multi_colls
* 2 + smb
->tx_late_colls
;
649 * tx_pkts_truncated counter looks suspicious. It constantly
650 * increments with no sign of Tx errors. Hence we don't factor it.
652 atgep
->atge_macxmt_errors
+= smb
->tx_late_colls
+ smb
->tx_underrun
;
654 atgep
->atge_macrcv_errors
+= smb
->rx_crcerrs
+ smb
->rx_lenerrs
+
655 smb
->rx_runts
+ smb
->rx_pkts_truncated
+
659 DMA_SYNC(dma
, 0, 0, DDI_DMA_SYNC_FORDEV
);
663 atge_l1c_stop_tx_mac(atge_t
*atgep
)
668 ATGE_DB(("%s: %s() called", atgep
->atge_name
, __func__
));
670 reg
= INL(atgep
, ATGE_MAC_CFG
);
671 if ((reg
& ATGE_CFG_TX_ENB
) != 0) {
672 reg
&= ~ATGE_CFG_TX_ENB
;
673 OUTL(atgep
, ATGE_MAC_CFG
, reg
);
676 /* Stop TX DMA engine. */
677 reg
= INL(atgep
, ATGE_DMA_CFG
);
678 if ((reg
& DMA_CFG_RD_ENB
) != 0) {
679 reg
&= ~DMA_CFG_RD_ENB
;
680 OUTL(atgep
, ATGE_DMA_CFG
, reg
);
683 for (t
= ATGE_RESET_TIMEOUT
; t
> 0; t
--) {
684 if ((INL(atgep
, ATGE_IDLE_STATUS
) &
685 (IDLE_STATUS_TXMAC
| IDLE_STATUS_DMARD
)) == 0)
692 /* This should be an FMA event. */
693 atge_error(atgep
->atge_dip
, "stopping TX DMA Engine timeout");
698 atge_l1c_stop_rx_mac(atge_t
*atgep
)
703 ATGE_DB(("%s: %s() called", atgep
->atge_name
, __func__
));
705 reg
= INL(atgep
, ATGE_MAC_CFG
);
706 if ((reg
& ATGE_CFG_RX_ENB
) != 0) {
707 reg
&= ~ATGE_CFG_RX_ENB
;
708 OUTL(atgep
, ATGE_MAC_CFG
, reg
);
711 /* Stop RX DMA engine. */
712 reg
= INL(atgep
, ATGE_DMA_CFG
);
713 if ((reg
& DMA_CFG_WR_ENB
) != 0) {
714 reg
&= ~DMA_CFG_WR_ENB
;
715 OUTL(atgep
, ATGE_DMA_CFG
, reg
);
718 for (t
= ATGE_RESET_TIMEOUT
; t
> 0; t
--) {
719 if ((INL(atgep
, ATGE_IDLE_STATUS
) &
720 (IDLE_STATUS_RXMAC
| IDLE_STATUS_DMAWR
)) == 0)
726 /* This should be an FMA event. */
727 atge_error(atgep
->atge_dip
, " stopping RX DMA Engine timeout");
732 * Receives (consumes) packets.
735 atge_l1c_rx(atge_t
*atgep
)
737 atge_l1c_data_t
*l1c
;
738 mblk_t
*mp
= NULL
, *rx_head
= NULL
, *rx_tail
= NULL
;
739 l1c_rx_rdesc_t
*rx_rr
;
740 uint32_t rdinfo
, status
, totlen
, pktlen
, slotlen
;
741 int nsegs
, rx_cons
= 0, cnt
;
746 l1c
= atgep
->atge_private_data
;
749 DMA_SYNC(l1c
->atge_l1c_rr
, 0, 0, DDI_DMA_SYNC_FORKERNEL
);
751 rx_rr
= (l1c_rx_rdesc_t
*)(l1c
->atge_l1c_rr
->addr
+
752 (l1c
->atge_l1c_rr_consumers
* sizeof (l1c_rx_rdesc_t
)));
754 rdinfo
= ATGE_GET32(l1c
->atge_l1c_rr
, &rx_rr
->rdinfo
);
755 status
= ATGE_GET32(l1c
->atge_l1c_rr
, &rx_rr
->status
);
757 rx_cons
= L1C_RRD_RD_IDX(rdinfo
);
758 nsegs
= L1C_RRD_RD_CNT(rdinfo
);
759 totlen
= L1C_RRD_BYTES(status
);
761 ATGE_DB(("%s: %s() PKT -- rdinfo : 0x%x,"
762 "status : 0x%x, totlen : %d,"
763 " rx_cons : %d, nsegs : %d", atgep
->atge_name
, __func__
,
764 rdinfo
, status
, totlen
, rx_cons
, nsegs
));
766 if ((status
& L1C_RRD_VALID
) == 0) {
770 if ((status
& (L1C_RRD_ERR_CRC
| L1C_RRD_ERR_ALIGN
|
771 L1C_RRD_ERR_TRUNC
| L1C_RRD_ERR_RUNT
|
772 L1C_RRD_ERR_ICMP
| L1C_RRD_ERR_LENGTH
)) != 0) {
773 atge_error(atgep
->atge_dip
, "errored pkt");
775 l1c
->atge_rx_ring
->r_consumer
+= nsegs
;
776 l1c
->atge_rx_ring
->r_consumer
%= L1C_RX_RING_CNT
;
780 ASSERT(rx_cons
>= 0 && rx_cons
<= L1C_RX_RING_CNT
);
782 mp
= allocb(totlen
+ L1C_HEADROOM
, BPRI_MED
);
784 mp
->b_rptr
+= L1C_HEADROOM
;
786 mp
->b_wptr
= bufp
+ totlen
;
789 atgep
->atge_ipackets
++;
790 atgep
->atge_rbytes
+= totlen
;
793 * If there are more than one segments, then the first
794 * segment should be of size MTU. We couldn't verify
795 * this as our driver does not support changing MTU
799 slotlen
= atgep
->atge_mtu
;
804 ATGE_DB(("%s: %s() PKT mp == NULL totlen : %d",
805 atgep
->atge_name
, __func__
, totlen
));
807 if (slotlen
> atgep
->atge_rx_buf_len
) {
808 atgep
->atge_toolong_errors
++;
809 } else if (mp
== NULL
) {
810 atgep
->atge_norcvbuf
++;
817 for (cnt
= 0, pktlen
= 0; cnt
< nsegs
; cnt
++) {
818 buf
= l1c
->atge_rx_ring
->r_buf_tbl
[rx_cons
];
820 slotlen
= min(atgep
->atge_max_frame_size
, totlen
);
822 bcopy(buf
->addr
, (bufp
+ pktlen
), slotlen
);
826 ATGE_DB(("%s: %s() len : %d, rxcons : %d, pktlen : %d",
827 atgep
->atge_name
, __func__
, slotlen
, rx_cons
,
830 ATGE_INC_SLOT(rx_cons
, L1C_RX_RING_CNT
);
833 if (rx_tail
== NULL
) {
834 rx_head
= rx_tail
= mp
;
836 rx_tail
->b_next
= mp
;
841 l1c
->atge_rx_ring
->r_consumer
+= nsegs
;
842 l1c
->atge_rx_ring
->r_consumer
%= L1C_RX_RING_CNT
;
844 l1c
->atge_rx_ring
->r_consumer
= rx_cons
;
848 * Tell the chip that this RR can be reused.
852 ATGE_INC_SLOT(l1c
->atge_l1c_rr_consumers
, L1C_RR_RING_CNT
);
857 DMA_SYNC(l1c
->atge_rx_ring
->r_desc_ring
, 0, 0,
858 DDI_DMA_SYNC_FORDEV
);
860 DMA_SYNC(l1c
->atge_l1c_rr
, 0, 0, DDI_DMA_SYNC_FORDEV
);
862 * Let controller know availability of new Rx buffers.
864 OUTL(atgep
, ATGE_MBOX_RD0_PROD_IDX
,
865 l1c
->atge_rx_ring
->r_consumer
);
867 ATGE_DB(("%s: %s() PKT Recved -> r_consumer : %d, rx_cons : %d"
868 " atge_l1c_rr_consumers : %d",
869 atgep
->atge_name
, __func__
, l1c
->atge_rx_ring
->r_consumer
,
870 rx_cons
, l1c
->atge_l1c_rr_consumers
));
878 * The interrupt handler for L1C chip.
882 atge_l1c_interrupt(caddr_t arg1
, caddr_t arg2
)
884 atge_t
*atgep
= (void *)arg1
;
885 mblk_t
*rx_head
= NULL
;
889 ASSERT(atgep
!= NULL
);
891 mutex_enter(&atgep
->atge_intr_lock
);
893 if (atgep
->atge_chip_state
& ATGE_CHIP_SUSPENDED
) {
894 mutex_exit(&atgep
->atge_intr_lock
);
895 return (DDI_INTR_UNCLAIMED
);
898 status
= INL(atgep
, ATGE_INTR_STATUS
);
899 if (status
== 0 || (status
& atgep
->atge_intrs
) == 0) {
900 mutex_exit(&atgep
->atge_intr_lock
);
902 if (atgep
->atge_flags
& ATGE_FIXED_TYPE
)
903 return (DDI_INTR_UNCLAIMED
);
905 return (DDI_INTR_CLAIMED
);
908 ATGE_DB(("%s: %s() entry status : %x",
909 atgep
->atge_name
, __func__
, status
));
912 * Disable interrupts.
914 if (status
& L1C_INTR_GPHY
) {
915 /* clear PHY interrupt source before we ack interrupts */
916 (void) atge_mii_read(atgep
,
917 atgep
->atge_phyaddr
, ATGE_ISR_ACK_GPHY
);
920 OUTL(atgep
, ATGE_INTR_STATUS
, status
| L1C_INTR_DIS_INT
);
921 FLUSH(atgep
, ATGE_INTR_STATUS
);
924 * Check if chip is running, only then do the work.
926 if (atgep
->atge_chip_state
& ATGE_CHIP_RUNNING
) {
927 atge_l1c_data_t
*l1c
;
929 l1c
= atgep
->atge_private_data
;
931 ATGE_DB(("%s: %s() atge_l1c_intr_status : %x, "
932 "atge_l1c_rx_prod_cons : %d, atge_l1c_tx_prod_cons : %d"
933 " atge_l1c_rr_consumers : %d",
934 atgep
->atge_name
, __func__
, l1c
->atge_l1c_intr_status
,
935 l1c
->atge_l1c_rx_prod_cons
, l1c
->atge_l1c_tx_prod_cons
,
936 l1c
->atge_l1c_rr_consumers
));
938 if (status
& L1C_INTR_SMB
)
939 atge_l1c_gather_stats(atgep
);
944 if (status
& (L1C_INTR_DMA_RD_TO_RST
|
945 L1C_INTR_DMA_WR_TO_RST
| L1C_INTR_TXQ_TO_RST
)) {
946 /* This should be an FMA event. */
947 atge_error(atgep
->atge_dip
,
948 "L1C chip detected a fatal error, "
949 "interrupt status: %x", status
);
951 if (status
& L1C_INTR_DMA_RD_TO_RST
) {
952 atge_error(atgep
->atge_dip
,
955 if (status
& L1C_INTR_DMA_WR_TO_RST
) {
956 atge_error(atgep
->atge_dip
,
959 if (status
& L1C_INTR_TXQ_TO_RST
) {
960 atge_error(atgep
->atge_dip
,
961 "Transmit queue error");
964 /* This should be an FMA event. */
965 atge_device_stop(atgep
);
967 * Device has failed fatally.
968 * It will not be restarted by the driver.
974 rx_head
= atge_l1c_rx(atgep
);
975 if (status
& L1C_INTR_TX_PKT
) {
978 mutex_enter(&atgep
->atge_tx_lock
);
979 cons
= INL(atgep
, ATGE_MBOX_TD_CONS_IDX
) >> 16;
980 atge_tx_reclaim(atgep
, cons
);
981 if (atgep
->atge_tx_resched
) {
982 atgep
->atge_tx_resched
= 0;
986 mutex_exit(&atgep
->atge_tx_lock
);
990 /* Re-enable interrupts. */
991 OUTL(atgep
, ATGE_INTR_STATUS
, 0);
994 mutex_exit(&atgep
->atge_intr_lock
);
996 if (status
& L1C_INTR_GPHY
) {
998 ATGE_DB(("%s: %s() MII_CHECK Performed",
999 atgep
->atge_name
, __func__
));
1000 mii_check(atgep
->atge_mii
);
1004 * Pass the list of packets received from chip to MAC layer.
1007 mac_rx(atgep
->atge_mh
, 0, rx_head
);
1011 * Let MAC start sending pkts if the downstream was asked to pause.
1014 mac_tx_update(atgep
->atge_mh
);
1016 return (DDI_INTR_CLAIMED
);
1020 atge_l1c_send_packet(atge_ring_t
*r
)
1026 mutex_enter(&atgep
->atge_mbox_lock
);
1027 /* Sync descriptors. */
1028 DMA_SYNC(atgep
->atge_tx_ring
->r_desc_ring
, 0, 0, DDI_DMA_SYNC_FORDEV
);
1029 /* Kick. Assume we're using normal Tx priority queue. */
1030 OUTL(atgep
, ATGE_MBOX_TD_PROD_IDX
,
1031 (atgep
->atge_tx_ring
->r_producer
<< MBOX_TD_PROD_LO_IDX_SHIFT
) &
1032 MBOX_TD_PROD_LO_IDX_MASK
);
1033 mutex_exit(&atgep
->atge_mbox_lock
);