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 #include <sys/types.h>
30 #include <sys/stream.h>
31 #include <sys/strsun.h>
33 #include <sys/modctl.h>
34 #include <sys/ethernet.h>
35 #include <sys/debug.h>
38 #include <sys/miiregs.h>
39 #include <sys/sysmacros.h>
40 #include <sys/dditypes.h>
42 #include <sys/sunddi.h>
43 #include <sys/byteorder.h>
46 #include <sys/stream.h>
49 #include "atge_l1e_reg.h"
50 #include "atge_cmn_reg.h"
53 * L1E specfic functions.
55 void atge_l1e_device_reset(atge_t
*);
56 void atge_l1e_stop_rx_mac(atge_t
*);
57 void atge_l1e_stop_tx_mac(atge_t
*);
59 static ddi_dma_attr_t atge_l1e_dma_attr_tx_desc
= {
60 DMA_ATTR_V0
, /* dma_attr_version */
61 0, /* dma_attr_addr_lo */
62 0x0000ffffffffull
, /* dma_attr_addr_hi */
63 0x0000ffffffffull
, /* dma_attr_count_max */
64 L1E_TX_RING_ALIGN
, /* dma_attr_align */
65 0x0000fffc, /* dma_attr_burstsizes */
66 1, /* dma_attr_minxfer */
67 0x0000ffffffffull
, /* dma_attr_maxxfer */
68 0x0000ffffffffull
, /* dma_attr_seg */
69 1, /* dma_attr_sgllen */
70 1, /* dma_attr_granular */
71 0 /* dma_attr_flags */
74 static ddi_dma_attr_t atge_l1e_dma_attr_rx_desc
= {
75 DMA_ATTR_V0
, /* dma_attr_version */
76 0, /* dma_attr_addr_lo */
77 0x0000ffffffffull
, /* dma_attr_addr_hi */
78 0x0000ffffffffull
, /* dma_attr_count_max */
79 L1E_RX_PAGE_ALIGN
, /* dma_attr_align */
80 0x0000fffc, /* dma_attr_burstsizes */
81 1, /* dma_attr_minxfer */
82 0x0000ffffffffull
, /* dma_attr_maxxfer */
83 0x0000ffffffffull
, /* dma_attr_seg */
84 1, /* dma_attr_sgllen */
85 1, /* dma_attr_granular */
86 0 /* dma_attr_flags */
89 static ddi_dma_attr_t atge_l1e_dma_attr_cmb
= {
90 DMA_ATTR_V0
, /* dma_attr_version */
91 0, /* dma_attr_addr_lo */
92 0x0000ffffffffull
, /* dma_attr_addr_hi */
93 0x0000ffffffffull
, /* dma_attr_count_max */
94 L1E_CMB_ALIGN
, /* dma_attr_align */
95 0x0000fffc, /* dma_attr_burstsizes */
96 1, /* dma_attr_minxfer */
97 0x0000ffffffffull
, /* dma_attr_maxxfer */
98 0x0000ffffffffull
, /* dma_attr_seg */
99 1, /* dma_attr_sgllen */
100 1, /* dma_attr_granular */
101 0 /* dma_attr_flags */
104 void atge_l1e_rx_next_pkt(atge_t
*, uint32_t);
107 atge_rx_desc_free(atge_t
*atgep
)
109 atge_l1e_data_t
*l1e
;
113 l1e
= (atge_l1e_data_t
*)atgep
->atge_private_data
;
117 if (l1e
->atge_l1e_rx_page
== NULL
)
120 for (pages
= 0; pages
< L1E_RX_PAGES
; pages
++) {
121 dma
= l1e
->atge_l1e_rx_page
[pages
];
123 (void) ddi_dma_unbind_handle(dma
->hdl
);
124 ddi_dma_mem_free(&dma
->acchdl
);
125 ddi_dma_free_handle(&dma
->hdl
);
126 kmem_free(dma
, sizeof (atge_dma_t
));
130 kmem_free(l1e
->atge_l1e_rx_page
, L1E_RX_PAGES
* sizeof (atge_dma_t
*));
131 l1e
->atge_l1e_rx_page
= NULL
;
135 atge_l1e_alloc_dma(atge_t
*atgep
)
138 atge_l1e_data_t
*l1e
;
143 l1e
= kmem_zalloc(sizeof (atge_l1e_data_t
), KM_SLEEP
);
144 atgep
->atge_private_data
= l1e
;
147 * Allocate TX ring descriptor.
149 atgep
->atge_tx_buf_len
= atgep
->atge_mtu
+
150 sizeof (struct ether_header
) + VLAN_TAGSZ
+ ETHERFCSL
;
151 atgep
->atge_tx_ring
= kmem_alloc(sizeof (atge_ring_t
), KM_SLEEP
);
152 atgep
->atge_tx_ring
->r_atge
= atgep
;
153 atgep
->atge_tx_ring
->r_desc_ring
= NULL
;
154 dma
= atge_alloc_a_dma_blk(atgep
, &atge_l1e_dma_attr_tx_desc
,
155 ATGE_TX_RING_SZ
, DDI_DMA_RDWR
);
157 ATGE_DB(("%s :%s failed",
158 atgep
->atge_name
, __func__
));
159 return (DDI_FAILURE
);
161 atgep
->atge_tx_ring
->r_desc_ring
= dma
;
164 * Allocate DMA buffers for TX ring.
166 err
= atge_alloc_buffers(atgep
->atge_tx_ring
, ATGE_TX_RING_CNT
,
167 atgep
->atge_tx_buf_len
, DDI_DMA_WRITE
);
168 if (err
!= DDI_SUCCESS
) {
169 ATGE_DB(("%s :%s() TX buffers failed",
170 atgep
->atge_name
, __func__
));
177 atgep
->atge_rx_buf_len
= atgep
->atge_mtu
+
178 sizeof (struct ether_header
) + VLAN_TAGSZ
+ ETHERFCSL
;
180 if (atgep
->atge_flags
& ATGE_FLAG_JUMBO
)
181 guard_size
= L1E_JUMBO_FRAMELEN
;
183 guard_size
= L1E_MAX_FRAMELEN
;
185 l1e
->atge_l1e_pagesize
= ROUNDUP(guard_size
+ L1E_RX_PAGE_SZ
,
187 l1e
->atge_l1e_rx_page
=
188 kmem_zalloc(L1E_RX_PAGES
* sizeof (atge_dma_t
*), KM_SLEEP
);
190 ATGE_DB(("%s: %s() atge_l1e_pagesize : %d, L1E_RX_PAGE_SZ : %d",
191 atgep
->atge_name
, __func__
, l1e
->atge_l1e_pagesize
,
195 for (pages
= 0; pages
< L1E_RX_PAGES
; pages
++) {
196 dma
= atge_alloc_a_dma_blk(atgep
, &atge_l1e_dma_attr_rx_desc
,
197 l1e
->atge_l1e_pagesize
, DDI_DMA_READ
);
204 l1e
->atge_l1e_rx_page
[pages
] = dma
;
207 if (err
== DDI_FAILURE
) {
208 ATGE_DB(("%s :%s RX pages failed",
209 atgep
->atge_name
, __func__
));
210 return (DDI_FAILURE
);
214 * Allocate CMB used for fetching interrupt status data.
216 ATGE_DB(("%s: %s() L1E_RX_CMB_SZ : %x", atgep
->atge_name
,
217 __func__
, L1E_RX_CMB_SZ
));
220 dma
= atge_alloc_a_dma_blk(atgep
, &atge_l1e_dma_attr_cmb
,
221 L1E_RX_CMB_SZ
* L1E_RX_PAGES
, DDI_DMA_RDWR
);
223 ATGE_DB(("%s :%s() RX CMB failed",
224 atgep
->atge_name
, __func__
));
225 return (DDI_FAILURE
);
227 l1e
->atge_l1e_rx_cmb
= dma
;
229 if (err
== DDI_FAILURE
) {
230 ATGE_DB(("%s :%s() RX CMB failed",
231 atgep
->atge_name
, __func__
));
232 return (DDI_FAILURE
);
235 atgep
->atge_hw_stats
= kmem_zalloc(sizeof (atge_l1e_smb_t
), KM_SLEEP
);
237 return (DDI_SUCCESS
);
241 atge_l1e_free_dma(atge_t
*atgep
)
243 atge_l1e_data_t
*l1e
;
248 if (atgep
->atge_tx_ring
!= NULL
) {
249 atge_free_buffers(atgep
->atge_tx_ring
, ATGE_TX_RING_CNT
);
251 if (atgep
->atge_tx_ring
->r_desc_ring
!= NULL
) {
252 atge_free_a_dma_blk(atgep
->atge_tx_ring
->r_desc_ring
);
255 kmem_free(atgep
->atge_tx_ring
, sizeof (atge_ring_t
));
256 atgep
->atge_tx_ring
= NULL
;
259 l1e
= atgep
->atge_private_data
;
266 if (l1e
->atge_l1e_rx_cmb
!= NULL
) {
267 atge_free_a_dma_blk(l1e
->atge_l1e_rx_cmb
);
268 l1e
->atge_l1e_rx_cmb
= NULL
;
272 * Free RX buffers and RX ring.
274 atge_rx_desc_free(atgep
);
277 * Free the memory allocated for gathering hw stats.
279 if (atgep
->atge_hw_stats
!= NULL
) {
280 kmem_free(atgep
->atge_hw_stats
, sizeof (atge_l1e_smb_t
));
281 atgep
->atge_hw_stats
= NULL
;
286 atge_l1e_init_rx_pages(atge_t
*atgep
)
288 atge_l1e_data_t
*l1e
;
292 ASSERT(atgep
!= NULL
);
293 l1e
= atgep
->atge_private_data
;
297 l1e
->atge_l1e_proc_max
= L1E_RX_PAGE_SZ
/ ETHERMIN
;
298 l1e
->atge_l1e_rx_curp
= 0;
299 l1e
->atge_l1e_rx_seqno
= 0;
301 for (pages
= 0; pages
< L1E_RX_PAGES
; pages
++) {
302 l1e
->atge_l1e_rx_page_cons
= 0;
303 l1e
->atge_l1e_rx_page_prods
[pages
] = 0;
306 dma
= l1e
->atge_l1e_rx_page
[pages
];
308 bzero(dma
->addr
, l1e
->atge_l1e_pagesize
);
309 DMA_SYNC(dma
, 0, l1e
->atge_l1e_pagesize
, DDI_DMA_SYNC_FORDEV
);
312 dma
= l1e
->atge_l1e_rx_cmb
;
314 bzero(dma
->addr
, L1E_RX_CMB_SZ
* L1E_RX_PAGES
);
315 DMA_SYNC(dma
, 0, L1E_RX_CMB_SZ
* L1E_RX_PAGES
, DDI_DMA_SYNC_FORDEV
);
319 atge_l1e_init_tx_ring(atge_t
*atgep
)
321 ASSERT(atgep
!= NULL
);
322 ASSERT(atgep
->atge_tx_ring
!= NULL
);
323 ASSERT(atgep
->atge_tx_ring
->r_desc_ring
!= NULL
);
325 atgep
->atge_tx_ring
->r_producer
= 0;
326 atgep
->atge_tx_ring
->r_consumer
= 0;
327 atgep
->atge_tx_ring
->r_avail_desc
= ATGE_TX_RING_CNT
;
329 bzero(atgep
->atge_tx_ring
->r_desc_ring
->addr
, ATGE_TX_RING_SZ
);
331 DMA_SYNC(atgep
->atge_tx_ring
->r_desc_ring
, 0, ATGE_TX_RING_SZ
,
332 DDI_DMA_SYNC_FORDEV
);
336 atge_l1e_program_dma(atge_t
*atgep
)
338 atge_l1e_data_t
*l1e
;
342 l1e
= (atge_l1e_data_t
*)atgep
->atge_private_data
;
345 * Clear WOL status and disable all WOL feature as WOL
346 * would interfere Rx operation under normal environments.
348 (void) INL(atgep
, ATGE_WOL_CFG
);
349 OUTL(atgep
, ATGE_WOL_CFG
, 0);
352 * Set Tx descriptor/RXF0/CMB base addresses. They share
353 * the same high address part of DMAable region.
355 paddr
= atgep
->atge_tx_ring
->r_desc_ring
->cookie
.dmac_laddress
;
356 OUTL(atgep
, ATGE_DESC_ADDR_HI
, ATGE_ADDR_HI(paddr
));
357 OUTL(atgep
, ATGE_DESC_TPD_ADDR_LO
, ATGE_ADDR_LO(paddr
));
358 OUTL(atgep
, ATGE_DESC_TPD_CNT
,
359 (ATGE_TX_RING_CNT
<< DESC_TPD_CNT_SHIFT
) & DESC_TPD_CNT_MASK
);
361 /* Set Rx page base address, note we use single queue. */
362 paddr
= l1e
->atge_l1e_rx_page
[0]->cookie
.dmac_laddress
;
363 OUTL(atgep
, L1E_RXF0_PAGE0_ADDR_LO
, ATGE_ADDR_LO(paddr
));
364 paddr
= l1e
->atge_l1e_rx_page
[1]->cookie
.dmac_laddress
;
365 OUTL(atgep
, L1E_RXF0_PAGE1_ADDR_LO
, ATGE_ADDR_LO(paddr
));
367 /* Set Tx/Rx CMB addresses. */
368 paddr
= l1e
->atge_l1e_rx_cmb
->cookie
.dmac_laddress
;
369 OUTL(atgep
, L1E_RXF0_CMB0_ADDR_LO
, ATGE_ADDR_LO(paddr
));
370 paddr
= l1e
->atge_l1e_rx_cmb
->cookie
.dmac_laddress
+ sizeof (uint32_t);
371 OUTL(atgep
, L1E_RXF0_CMB1_ADDR_LO
, ATGE_ADDR_LO(paddr
));
373 /* Mark RXF0 valid. */
374 OUTB(atgep
, L1E_RXF0_PAGE0
, RXF_VALID
); /* 0 */
375 OUTB(atgep
, L1E_RXF0_PAGE1
, RXF_VALID
); /* 1 */
376 OUTB(atgep
, L1E_RXF0_PAGE0
+ 2, 0);
377 OUTB(atgep
, L1E_RXF0_PAGE0
+ 3, 0);
378 OUTB(atgep
, L1E_RXF0_PAGE0
+ 4, 0);
379 OUTB(atgep
, L1E_RXF0_PAGE0
+ 5, 0);
380 OUTB(atgep
, L1E_RXF0_PAGE0
+ 6, 0);
381 OUTB(atgep
, L1E_RXF0_PAGE0
+ 6, 0);
383 /* Set Rx page size, excluding guard frame size. */
384 OUTL(atgep
, L1E_RXF_PAGE_SIZE
, L1E_RX_PAGE_SZ
);
386 /* Tell hardware that we're ready to load DMA blocks. */
387 OUTL(atgep
, ATGE_DMA_BLOCK
, DMA_BLOCK_LOAD
);
389 /* Set Rx/Tx interrupt trigger threshold. */
390 OUTL(atgep
, L1E_INT_TRIG_THRESH
, (1 << INT_TRIG_RX_THRESH_SHIFT
) |
391 (4 << INT_TRIG_TX_THRESH_SHIFT
));
394 * Set interrupt trigger timer, its purpose and relation
395 * with interrupt moderation mechanism is not clear yet.
397 OUTL(atgep
, L1E_INT_TRIG_TIMER
,
398 ((ATGE_USECS(10) << INT_TRIG_RX_TIMER_SHIFT
) |
399 (ATGE_USECS(1000) << INT_TRIG_TX_TIMER_SHIFT
)));
401 reg
= ATGE_USECS(ATGE_IM_RX_TIMER_DEFAULT
) << IM_TIMER_RX_SHIFT
;
402 reg
|= ATGE_USECS(ATGE_IM_TX_TIMER_DEFAULT
) << IM_TIMER_TX_SHIFT
;
403 OUTL(atgep
, ATGE_IM_TIMER
, reg
);
405 reg
= INL(atgep
, ATGE_MASTER_CFG
);
406 reg
&= ~(L1E_MASTER_CHIP_REV_MASK
| L1E_MASTER_CHIP_ID_MASK
);
407 reg
&= ~(L1E_MASTER_IM_RX_TIMER_ENB
| L1E_MASTER_IM_TX_TIMER_ENB
);
408 reg
|= L1E_MASTER_IM_RX_TIMER_ENB
;
409 reg
|= L1E_MASTER_IM_TX_TIMER_ENB
;
410 OUTL(atgep
, ATGE_MASTER_CFG
, reg
);
412 OUTW(atgep
, RX_COALSC_PKT_1e
, 0);
413 OUTW(atgep
, RX_COALSC_TO_1e
, 0);
414 OUTW(atgep
, TX_COALSC_PKT_1e
, 1);
415 OUTW(atgep
, TX_COALSC_TO_1e
, 4000/2); /* 4mS */
419 atge_l1e_receive(atge_t
*atgep
)
421 atge_l1e_data_t
*l1e
;
422 atge_dma_t
*dma_rx_page
;
423 atge_dma_t
*dma_rx_cmb
;
425 uint32_t cons
, current_page
;
426 uchar_t
*pageaddr
, *bufp
;
429 uint32_t seqno
, len
, flags
;
430 mblk_t
*mp
= NULL
, *rx_head
, *rx_tail
;
431 static uint32_t gen
= 0;
433 l1e
= atgep
->atge_private_data
;
435 ASSERT(MUTEX_HELD(&atgep
->atge_intr_lock
));
441 current_page
= l1e
->atge_l1e_rx_curp
;
444 dma_rx_cmb
= l1e
->atge_l1e_rx_cmb
;
445 DMA_SYNC(dma_rx_cmb
, 0, L1E_RX_CMB_SZ
* L1E_RX_PAGES
,
446 DDI_DMA_SYNC_FORKERNEL
);
448 dma_rx_page
= l1e
->atge_l1e_rx_page
[current_page
];
451 * Get the producer offset from CMB.
453 ptr
= (void *)dma_rx_cmb
->addr
;
455 l1e
->atge_l1e_rx_page_prods
[current_page
] =
456 ATGE_GET32(dma_rx_cmb
, ptr
+ current_page
);
458 /* Sync current RX Page as well */
459 DMA_SYNC(dma_rx_page
, l1e
->atge_l1e_rx_page_cons
,
460 l1e
->atge_l1e_rx_page_prods
[current_page
], DDI_DMA_SYNC_FORKERNEL
);
462 ATGE_DB(("%s: %s() prod : %d, cons : %d, curr page : %d, gen : (%d)"
463 " cmb[0,1] : %d, %d",
464 atgep
->atge_name
, __func__
,
465 l1e
->atge_l1e_rx_page_prods
[current_page
],
466 l1e
->atge_l1e_rx_page_cons
, l1e
->atge_l1e_rx_curp
, gen
,
467 ATGE_GET32(dma_rx_cmb
, ptr
), ATGE_GET32(dma_rx_cmb
, ptr
+ 1)));
469 for (prog
= 0; prog
<= l1e
->atge_l1e_proc_max
; prog
++) {
470 cons
= l1e
->atge_l1e_rx_page_cons
;
471 if (cons
>= l1e
->atge_l1e_rx_page_prods
[l1e
->atge_l1e_rx_curp
])
474 dma_rx_page
= l1e
->atge_l1e_rx_page
[l1e
->atge_l1e_rx_curp
];
475 pageaddr
= (uchar_t
*)dma_rx_page
->addr
;
476 pageaddr
= pageaddr
+ cons
;
477 rs
= (rx_rs_t
*)pageaddr
;
479 seqno
= ATGE_GET32(dma_rx_page
, &(rs
->seqno
));
480 seqno
= L1E_RX_SEQNO(seqno
);
482 len
= ATGE_GET32(dma_rx_page
, &(rs
->length
));
483 len
= L1E_RX_BYTES(len
);
485 flags
= ATGE_GET32(dma_rx_page
, &(rs
->flags
));
487 if (seqno
!= l1e
->atge_l1e_rx_seqno
) {
489 * We have not seen this happening but we
490 * must restart the chip if that happens.
492 ATGE_DB(("%s: %s() MISS-MATCH in seqno :%d,"
493 " atge_l1e_rx_seqno : %d, length : %d, flags : %x",
494 atgep
->atge_name
, __func__
, seqno
,
495 l1e
->atge_l1e_rx_seqno
, len
, flags
));
497 mutex_enter(&atgep
->atge_tx_lock
);
498 atge_device_restart(atgep
);
499 mutex_exit(&atgep
->atge_tx_lock
);
502 * Return all the pkts received before restarting
507 l1e
->atge_l1e_rx_seqno
++;
511 * We will pass the pkt to upper layer provided it's clear
514 if ((flags
& L1E_RD_ERROR
) != 0) {
515 if ((flags
& (L1E_RD_CRC
| L1E_RD_CODE
|
516 L1E_RD_DRIBBLE
| L1E_RD_RUNT
| L1E_RD_OFLOW
|
517 L1E_RD_TRUNC
)) != 0) {
518 ATGE_DB(("%s: %s() ERRORED PKT : %x",
519 atgep
->atge_name
, __func__
, flags
));
520 atge_l1e_rx_next_pkt(atgep
, len
);
521 atgep
->atge_errrcv
++;
527 * So we have received a frame/pkt.
529 if (len
== 0 || len
> atgep
->atge_rx_buf_len
) {
530 ATGE_DB(("%s: %s() PKT len > error : %d",
531 atgep
->atge_name
, __func__
, len
));
532 atge_l1e_rx_next_pkt(atgep
, len
);
536 mp
= allocb(len
+ VLAN_TAGSZ
, BPRI_MED
);
538 mp
->b_rptr
+= VLAN_TAGSZ
;
540 mp
->b_wptr
= bufp
+ len
;
543 bcopy(pageaddr
+ sizeof (rx_rs_t
), bufp
, len
);
546 rx_head
= rx_tail
= mp
;
548 rx_tail
->b_next
= mp
;
552 atgep
->atge_ipackets
++;
553 atgep
->atge_rbytes
+= len
;
555 ATGE_DB(("%s: %s() PKT mp == NULL len : %d",
556 atgep
->atge_name
, __func__
, len
));
558 if (len
> atgep
->atge_rx_buf_len
) {
559 atgep
->atge_toolong_errors
++;
560 } else if (mp
== NULL
) {
561 atgep
->atge_norcvbuf
++;
565 atge_l1e_rx_next_pkt(atgep
, len
);
567 ATGE_DB(("%s: %s() seqno :%d, atge_l1e_rx_seqno :"
569 " flags : %x, cons : %d, prod : %d",
570 atgep
->atge_name
, __func__
, seqno
,
571 l1e
->atge_l1e_rx_seqno
, len
, flags
,
572 l1e
->atge_l1e_rx_page_cons
,
573 l1e
->atge_l1e_rx_page_prods
[l1e
->atge_l1e_rx_curp
]));
576 ATGE_DB(("%s: %s() receive completed (gen : %d) : cons : %d,"
577 " prod :%d, L1E_RX_PAGE_SZ : %d (prog:%d)",
578 atgep
->atge_name
, __func__
, gen
,
579 l1e
->atge_l1e_rx_page_cons
,
580 l1e
->atge_l1e_rx_page_prods
[l1e
->atge_l1e_rx_curp
],
581 L1E_RX_PAGE_SZ
, prog
));
588 atge_l1e_rx_next_pkt(atge_t
*atgep
, uint32_t len
)
590 atge_l1e_data_t
*l1e
= atgep
->atge_private_data
;
591 atge_dma_t
*dma_rx_page
;
592 atge_dma_t
*dma_rx_cmb
;
593 int curr
= l1e
->atge_l1e_rx_curp
;
597 * Update consumer position.
599 l1e
->atge_l1e_rx_page_cons
+=
600 ROUNDUP(len
+ sizeof (rx_rs_t
), L1E_RX_PAGE_ALIGN
);
603 * If we need to flip to the other page. Note that we use only two
606 if (l1e
->atge_l1e_rx_page_cons
>= L1E_RX_PAGE_SZ
) {
607 ATGE_DB(("%s: %s() cons : %d, prod :%d, L1E_RX_PAGE_SZ : %d",
608 atgep
->atge_name
, __func__
, l1e
->atge_l1e_rx_page_cons
,
609 l1e
->atge_l1e_rx_page_prods
[curr
], L1E_RX_PAGE_SZ
));
612 * Clear the producer.
614 dma_rx_cmb
= l1e
->atge_l1e_rx_cmb
;
615 p
= (void *)dma_rx_cmb
->addr
;
618 DMA_SYNC(dma_rx_cmb
, curr
* L1E_RX_CMB_SZ
,
619 L1E_RX_CMB_SZ
, DDI_DMA_SYNC_FORDEV
);
622 * Notify the NIC that the current RX page is available again.
624 OUTB(atgep
, L1E_RXF0_PAGE0
+ curr
, RXF_VALID
);
627 * End of Rx page reached, let hardware reuse this page.
629 l1e
->atge_l1e_rx_page_cons
= 0;
630 l1e
->atge_l1e_rx_page_prods
[curr
] = 0;
633 * Switch to alternate Rx page.
636 l1e
->atge_l1e_rx_curp
= curr
;
639 * Page flipped, sync CMB and then Rx page.
641 DMA_SYNC(dma_rx_cmb
, 0, L1E_RX_PAGES
* L1E_RX_CMB_SZ
,
642 DDI_DMA_SYNC_FORKERNEL
);
643 p
= (void *)dma_rx_cmb
->addr
;
644 l1e
->atge_l1e_rx_page_prods
[curr
] =
645 ATGE_GET32(dma_rx_cmb
, p
+ curr
);
647 dma_rx_page
= l1e
->atge_l1e_rx_page
[curr
];
648 DMA_SYNC(dma_rx_page
, 0, l1e
->atge_l1e_rx_page_prods
[curr
],
649 DDI_DMA_SYNC_FORKERNEL
);
651 ATGE_DB(("%s: %s() PAGE FLIPPED -> %d, producer[0,1]: %d, %d",
652 atgep
->atge_name
, __func__
, curr
,
653 ATGE_GET32(dma_rx_cmb
, p
), ATGE_GET32(dma_rx_cmb
, p
+ 1)));
658 atge_l1e_send_packet(atge_ring_t
*r
)
661 * Ask chip to send the packet now.
663 OUTL(r
->r_atge
, ATGE_MBOX
, r
->r_producer
);
667 atge_l1e_clear_stats(atge_t
*atgep
)
674 * Clear RX stats first.
677 reg
= &smb
.rx_frames
;
678 while (reg
++ <= &smb
.rx_pkts_filtered
) {
679 (void) INL(atgep
, L1E_RX_MIB_BASE
+ i
);
680 i
+= sizeof (uint32_t);
687 reg
= &smb
.tx_frames
;
688 while (reg
++ <= &smb
.tx_mcast_bytes
) {
689 (void) INL(atgep
, L1E_TX_MIB_BASE
+ i
);
690 i
+= sizeof (uint32_t);
695 atge_l1e_gather_stats(atge_t
*atgep
)
697 atge_l1e_smb_t
*stat
;
699 atge_l1e_smb_t local_smb
;
703 ASSERT(atgep
!= NULL
);
705 stat
= (atge_l1e_smb_t
*)atgep
->atge_hw_stats
;
707 bzero(&local_smb
, sizeof (atge_l1e_smb_t
));
710 /* Read Rx statistics. */
712 reg
= &smb
->rx_frames
;
713 while (reg
++ <= &smb
->rx_pkts_filtered
) {
714 *reg
= INL(atgep
, L1E_RX_MIB_BASE
+ i
);
715 i
+= sizeof (uint32_t);
718 /* Read Tx statistics. */
720 reg
= &smb
->tx_frames
;
721 while (reg
++ <= &smb
->tx_mcast_bytes
) {
722 *reg
= INL(atgep
, L1E_TX_MIB_BASE
+ i
);
723 i
+= sizeof (uint32_t);
727 * SMB is cleared everytime we read; hence we always do '+='.
731 stat
->rx_frames
+= smb
->rx_frames
;
732 stat
->rx_bcast_frames
+= smb
->rx_bcast_frames
;
733 stat
->rx_mcast_frames
+= smb
->rx_mcast_frames
;
734 stat
->rx_pause_frames
+= smb
->rx_pause_frames
;
735 stat
->rx_control_frames
+= smb
->rx_control_frames
;
736 stat
->rx_crcerrs
+= smb
->rx_crcerrs
;
737 stat
->rx_lenerrs
+= smb
->rx_lenerrs
;
738 stat
->rx_bytes
+= smb
->rx_bytes
;
739 stat
->rx_runts
+= smb
->rx_runts
;
740 stat
->rx_fragments
+= smb
->rx_fragments
;
741 stat
->rx_pkts_64
+= smb
->rx_pkts_64
;
742 stat
->rx_pkts_65_127
+= smb
->rx_pkts_65_127
;
743 stat
->rx_pkts_128_255
+= smb
->rx_pkts_128_255
;
744 stat
->rx_pkts_256_511
+= smb
->rx_pkts_256_511
;
745 stat
->rx_pkts_512_1023
+= smb
->rx_pkts_512_1023
;
746 stat
->rx_pkts_1024_1518
+= smb
->rx_pkts_1024_1518
;
747 stat
->rx_pkts_1519_max
+= smb
->rx_pkts_1519_max
;
748 stat
->rx_pkts_truncated
+= smb
->rx_pkts_truncated
;
749 stat
->rx_fifo_oflows
+= smb
->rx_fifo_oflows
;
750 stat
->rx_rrs_errs
+= smb
->rx_rrs_errs
;
751 stat
->rx_alignerrs
+= smb
->rx_alignerrs
;
752 stat
->rx_bcast_bytes
+= smb
->rx_bcast_bytes
;
753 stat
->rx_mcast_bytes
+= smb
->rx_mcast_bytes
;
754 stat
->rx_pkts_filtered
+= smb
->rx_pkts_filtered
;
757 stat
->tx_frames
+= smb
->tx_frames
;
758 stat
->tx_bcast_frames
+= smb
->tx_bcast_frames
;
759 stat
->tx_mcast_frames
+= smb
->tx_mcast_frames
;
760 stat
->tx_pause_frames
+= smb
->tx_pause_frames
;
761 stat
->tx_excess_defer
+= smb
->tx_excess_defer
;
762 stat
->tx_control_frames
+= smb
->tx_control_frames
;
763 stat
->tx_deferred
+= smb
->tx_deferred
;
764 stat
->tx_bytes
+= smb
->tx_bytes
;
765 stat
->tx_pkts_64
+= smb
->tx_pkts_64
;
766 stat
->tx_pkts_65_127
+= smb
->tx_pkts_65_127
;
767 stat
->tx_pkts_128_255
+= smb
->tx_pkts_128_255
;
768 stat
->tx_pkts_256_511
+= smb
->tx_pkts_256_511
;
769 stat
->tx_pkts_512_1023
+= smb
->tx_pkts_512_1023
;
770 stat
->tx_pkts_1024_1518
+= smb
->tx_pkts_1024_1518
;
771 stat
->tx_pkts_1519_max
+= smb
->tx_pkts_1519_max
;
772 stat
->tx_single_colls
+= smb
->tx_single_colls
;
773 stat
->tx_multi_colls
+= smb
->tx_multi_colls
;
774 stat
->tx_late_colls
+= smb
->tx_late_colls
;
775 stat
->tx_excess_colls
+= smb
->tx_excess_colls
;
776 stat
->tx_abort
+= smb
->tx_abort
;
777 stat
->tx_underrun
+= smb
->tx_underrun
;
778 stat
->tx_desc_underrun
+= smb
->tx_desc_underrun
;
779 stat
->tx_lenerrs
+= smb
->tx_lenerrs
;
780 stat
->tx_pkts_truncated
+= smb
->tx_pkts_truncated
;
781 stat
->tx_bcast_bytes
+= smb
->tx_bcast_bytes
;
782 stat
->tx_mcast_bytes
+= smb
->tx_mcast_bytes
;
785 * Update global counters in atge_t.
787 atgep
->atge_brdcstrcv
+= smb
->rx_bcast_frames
;
788 atgep
->atge_multircv
+= smb
->rx_mcast_frames
;
789 atgep
->atge_multixmt
+= smb
->tx_mcast_frames
;
790 atgep
->atge_brdcstxmt
+= smb
->tx_bcast_frames
;
792 atgep
->atge_align_errors
+= smb
->rx_alignerrs
;
793 atgep
->atge_fcs_errors
+= smb
->rx_crcerrs
;
794 atgep
->atge_sqe_errors
+= smb
->rx_rrs_errs
;
795 atgep
->atge_defer_xmts
+= smb
->tx_deferred
;
796 atgep
->atge_first_collisions
+= smb
->tx_single_colls
;
797 atgep
->atge_multi_collisions
+= smb
->tx_multi_colls
* 2;
798 atgep
->atge_tx_late_collisions
+= smb
->tx_late_colls
;
799 atgep
->atge_ex_collisions
+= smb
->tx_excess_colls
;
800 atgep
->atge_macxmt_errors
+= smb
->tx_abort
;
801 atgep
->atge_toolong_errors
+= smb
->rx_lenerrs
;
802 atgep
->atge_overflow
+= smb
->rx_fifo_oflows
;
803 atgep
->atge_underflow
+= (smb
->tx_underrun
+ smb
->tx_desc_underrun
);
804 atgep
->atge_runt
+= smb
->rx_runts
;
807 atgep
->atge_collisions
+= smb
->tx_single_colls
+
808 smb
->tx_multi_colls
* 2 + smb
->tx_late_colls
+
809 smb
->tx_abort
* HDPX_CFG_RETRY_DEFAULT
;
812 * tx_pkts_truncated counter looks suspicious. It constantly
813 * increments with no sign of Tx errors. Hence we don't factor it.
815 atgep
->atge_macxmt_errors
+= smb
->tx_abort
+ smb
->tx_late_colls
+
818 atgep
->atge_macrcv_errors
+= smb
->rx_crcerrs
+ smb
->rx_lenerrs
+
819 smb
->rx_runts
+ smb
->rx_pkts_truncated
+
820 smb
->rx_fifo_oflows
+ smb
->rx_rrs_errs
+
825 atge_l1e_stop_mac(atge_t
*atgep
)
829 reg
= INL(atgep
, ATGE_MAC_CFG
);
830 ATGE_DB(("%s: %s() reg : %x", atgep
->atge_name
, __func__
, reg
));
832 if ((reg
& (ATGE_CFG_TX_ENB
| ATGE_CFG_RX_ENB
)) != 0) {
833 reg
&= ~ATGE_CFG_TX_ENB
| ATGE_CFG_RX_ENB
;
834 OUTL(atgep
, ATGE_MAC_CFG
, reg
);
835 ATGE_DB(("%s: %s() mac stopped", atgep
->atge_name
, __func__
));
840 * The interrupt handler for L1E/L2E
844 atge_l1e_interrupt(caddr_t arg1
, caddr_t arg2
)
846 atge_t
*atgep
= (void *)arg1
;
847 mblk_t
*rx_head
= NULL
;
851 ASSERT(atgep
!= NULL
);
853 mutex_enter(&atgep
->atge_intr_lock
);
855 if (atgep
->atge_chip_state
& ATGE_CHIP_SUSPENDED
) {
856 mutex_exit(&atgep
->atge_intr_lock
);
857 return (DDI_INTR_UNCLAIMED
);
860 status
= INL(atgep
, ATGE_INTR_STATUS
);
861 if (status
== 0 || (status
& atgep
->atge_intrs
) == 0) {
862 mutex_exit(&atgep
->atge_intr_lock
);
864 if (atgep
->atge_flags
& ATGE_FIXED_TYPE
)
865 return (DDI_INTR_UNCLAIMED
);
867 return (DDI_INTR_CLAIMED
);
870 ATGE_DB(("%s: %s() entry status : %x",
871 atgep
->atge_name
, __func__
, status
));
875 * Disable interrupts.
877 OUTL(atgep
, ATGE_INTR_STATUS
, status
| INTR_DIS_INT
);
878 FLUSH(atgep
, ATGE_INTR_STATUS
);
881 * Check if chip is running, only then do the work.
883 if (atgep
->atge_chip_state
& ATGE_CHIP_RUNNING
) {
884 if (status
& INTR_SMB
) {
885 atge_l1e_gather_stats(atgep
);
891 if (status
& L1E_INTR_ERRORS
) {
892 atge_error(atgep
->atge_dip
,
893 "L1E chip found an error intr status : %x",
897 (INTR_DMA_RD_TO_RST
| INTR_DMA_WR_TO_RST
)) {
898 atge_error(atgep
->atge_dip
, "DMA transfer err");
900 atge_device_stop(atgep
);
904 if (status
& INTR_TX_FIFO_UNDERRUN
) {
905 atge_error(atgep
->atge_dip
, "TX FIFO underrun");
909 rx_head
= atge_l1e_receive(atgep
);
911 if (status
& INTR_TX_PKT
) {
914 mutex_enter(&atgep
->atge_tx_lock
);
915 cons
= INW(atgep
, L1E_TPD_CONS_IDX
);
916 atge_tx_reclaim(atgep
, cons
);
917 if (atgep
->atge_tx_resched
) {
918 atgep
->atge_tx_resched
= 0;
922 mutex_exit(&atgep
->atge_tx_lock
);
929 OUTL(atgep
, ATGE_INTR_STATUS
, 0);
933 mutex_exit(&atgep
->atge_intr_lock
);
935 if (status
& INTR_GPHY
) {
937 * Ack interrupts from PHY
939 (void) atge_mii_read(atgep
,
940 atgep
->atge_phyaddr
, ATGE_ISR_ACK_GPHY
);
942 mii_check(atgep
->atge_mii
);
946 * Pass the list of packets received from chip to MAC layer.
949 mac_rx(atgep
->atge_mh
, 0, rx_head
);
953 * Let MAC start sending pkts if the downstream was asked to pause.
956 mac_tx_update(atgep
->atge_mh
);
958 return (DDI_INTR_CLAIMED
);