110393SSaurabh.Mishra@Sun.COM /*
210393SSaurabh.Mishra@Sun.COM * CDDL HEADER START
310393SSaurabh.Mishra@Sun.COM *
410393SSaurabh.Mishra@Sun.COM * The contents of this file are subject to the terms of the
510393SSaurabh.Mishra@Sun.COM * Common Development and Distribution License (the "License").
610393SSaurabh.Mishra@Sun.COM * You may not use this file except in compliance with the License.
710393SSaurabh.Mishra@Sun.COM *
810393SSaurabh.Mishra@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910393SSaurabh.Mishra@Sun.COM * or http://www.opensolaris.org/os/licensing.
1010393SSaurabh.Mishra@Sun.COM * See the License for the specific language governing permissions
1110393SSaurabh.Mishra@Sun.COM * and limitations under the License.
1210393SSaurabh.Mishra@Sun.COM *
1310393SSaurabh.Mishra@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1410393SSaurabh.Mishra@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510393SSaurabh.Mishra@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1610393SSaurabh.Mishra@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1710393SSaurabh.Mishra@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1810393SSaurabh.Mishra@Sun.COM *
1910393SSaurabh.Mishra@Sun.COM * CDDL HEADER END
2010393SSaurabh.Mishra@Sun.COM */
2110393SSaurabh.Mishra@Sun.COM
2210393SSaurabh.Mishra@Sun.COM /*
2310393SSaurabh.Mishra@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
2410393SSaurabh.Mishra@Sun.COM * Use is subject to license terms.
2510393SSaurabh.Mishra@Sun.COM */
2610393SSaurabh.Mishra@Sun.COM
2710393SSaurabh.Mishra@Sun.COM #include <sys/types.h>
2810393SSaurabh.Mishra@Sun.COM #include <sys/stream.h>
2910393SSaurabh.Mishra@Sun.COM #include <sys/strsun.h>
3010393SSaurabh.Mishra@Sun.COM #include <sys/stat.h>
3110393SSaurabh.Mishra@Sun.COM #include <sys/modctl.h>
3210393SSaurabh.Mishra@Sun.COM #include <sys/ethernet.h>
3310393SSaurabh.Mishra@Sun.COM #include <sys/debug.h>
3410393SSaurabh.Mishra@Sun.COM #include <sys/conf.h>
3510393SSaurabh.Mishra@Sun.COM #include <sys/mii.h>
3610393SSaurabh.Mishra@Sun.COM #include <sys/miiregs.h>
3710393SSaurabh.Mishra@Sun.COM #include <sys/sysmacros.h>
3810393SSaurabh.Mishra@Sun.COM #include <sys/dditypes.h>
3910393SSaurabh.Mishra@Sun.COM #include <sys/ddi.h>
4010393SSaurabh.Mishra@Sun.COM #include <sys/sunddi.h>
4110393SSaurabh.Mishra@Sun.COM #include <sys/byteorder.h>
4210393SSaurabh.Mishra@Sun.COM #include <sys/note.h>
4310393SSaurabh.Mishra@Sun.COM #include <sys/vlan.h>
4410393SSaurabh.Mishra@Sun.COM #include <sys/stream.h>
4510393SSaurabh.Mishra@Sun.COM
4610393SSaurabh.Mishra@Sun.COM #include "atge.h"
4710393SSaurabh.Mishra@Sun.COM #include "atge_l1e_reg.h"
4810393SSaurabh.Mishra@Sun.COM #include "atge_cmn_reg.h"
4910393SSaurabh.Mishra@Sun.COM
5010393SSaurabh.Mishra@Sun.COM /*
5110393SSaurabh.Mishra@Sun.COM * L1E specfic functions.
5210393SSaurabh.Mishra@Sun.COM */
5310393SSaurabh.Mishra@Sun.COM void atge_l1e_device_reset(atge_t *);
5410393SSaurabh.Mishra@Sun.COM void atge_l1e_stop_rx_mac(atge_t *);
5510393SSaurabh.Mishra@Sun.COM void atge_l1e_stop_tx_mac(atge_t *);
5610393SSaurabh.Mishra@Sun.COM
5710393SSaurabh.Mishra@Sun.COM static ddi_dma_attr_t atge_l1e_dma_attr_tx_desc = {
5810393SSaurabh.Mishra@Sun.COM DMA_ATTR_V0, /* dma_attr_version */
5910393SSaurabh.Mishra@Sun.COM 0, /* dma_attr_addr_lo */
6010393SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_addr_hi */
6110393SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_count_max */
6210393SSaurabh.Mishra@Sun.COM L1E_TX_RING_ALIGN, /* dma_attr_align */
6310393SSaurabh.Mishra@Sun.COM 0x0000fffc, /* dma_attr_burstsizes */
6410393SSaurabh.Mishra@Sun.COM 1, /* dma_attr_minxfer */
6510393SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_maxxfer */
6610393SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_seg */
6710393SSaurabh.Mishra@Sun.COM 1, /* dma_attr_sgllen */
6810393SSaurabh.Mishra@Sun.COM 1, /* dma_attr_granular */
6910393SSaurabh.Mishra@Sun.COM 0 /* dma_attr_flags */
7010393SSaurabh.Mishra@Sun.COM };
7110393SSaurabh.Mishra@Sun.COM
7210393SSaurabh.Mishra@Sun.COM static ddi_dma_attr_t atge_l1e_dma_attr_rx_desc = {
7310393SSaurabh.Mishra@Sun.COM DMA_ATTR_V0, /* dma_attr_version */
7410393SSaurabh.Mishra@Sun.COM 0, /* dma_attr_addr_lo */
7510393SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_addr_hi */
7610393SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_count_max */
7710393SSaurabh.Mishra@Sun.COM L1E_RX_PAGE_ALIGN, /* dma_attr_align */
7810393SSaurabh.Mishra@Sun.COM 0x0000fffc, /* dma_attr_burstsizes */
7910393SSaurabh.Mishra@Sun.COM 1, /* dma_attr_minxfer */
8010393SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_maxxfer */
8110393SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_seg */
8210393SSaurabh.Mishra@Sun.COM 1, /* dma_attr_sgllen */
8310393SSaurabh.Mishra@Sun.COM 1, /* dma_attr_granular */
8410393SSaurabh.Mishra@Sun.COM 0 /* dma_attr_flags */
8510393SSaurabh.Mishra@Sun.COM };
8610393SSaurabh.Mishra@Sun.COM
8710393SSaurabh.Mishra@Sun.COM static ddi_dma_attr_t atge_l1e_dma_attr_cmb = {
8810393SSaurabh.Mishra@Sun.COM DMA_ATTR_V0, /* dma_attr_version */
8910393SSaurabh.Mishra@Sun.COM 0, /* dma_attr_addr_lo */
9010393SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_addr_hi */
9110393SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_count_max */
9210393SSaurabh.Mishra@Sun.COM L1E_CMB_ALIGN, /* dma_attr_align */
9310393SSaurabh.Mishra@Sun.COM 0x0000fffc, /* dma_attr_burstsizes */
9410393SSaurabh.Mishra@Sun.COM 1, /* dma_attr_minxfer */
9510393SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_maxxfer */
9610393SSaurabh.Mishra@Sun.COM 0x0000ffffffffull, /* dma_attr_seg */
9710393SSaurabh.Mishra@Sun.COM 1, /* dma_attr_sgllen */
9810393SSaurabh.Mishra@Sun.COM 1, /* dma_attr_granular */
9910393SSaurabh.Mishra@Sun.COM 0 /* dma_attr_flags */
10010393SSaurabh.Mishra@Sun.COM };
10110393SSaurabh.Mishra@Sun.COM
10210393SSaurabh.Mishra@Sun.COM void atge_l1e_rx_next_pkt(atge_t *, uint32_t);
10310393SSaurabh.Mishra@Sun.COM
10410393SSaurabh.Mishra@Sun.COM void
atge_rx_desc_free(atge_t * atgep)10510393SSaurabh.Mishra@Sun.COM atge_rx_desc_free(atge_t *atgep)
10610393SSaurabh.Mishra@Sun.COM {
10710393SSaurabh.Mishra@Sun.COM atge_l1e_data_t *l1e;
10810393SSaurabh.Mishra@Sun.COM atge_dma_t *dma;
10910393SSaurabh.Mishra@Sun.COM int pages;
11010393SSaurabh.Mishra@Sun.COM
11110393SSaurabh.Mishra@Sun.COM l1e = (atge_l1e_data_t *)atgep->atge_private_data;
11210393SSaurabh.Mishra@Sun.COM if (l1e == NULL)
11310393SSaurabh.Mishra@Sun.COM return;
11410393SSaurabh.Mishra@Sun.COM
11510393SSaurabh.Mishra@Sun.COM if (l1e->atge_l1e_rx_page == NULL)
11610393SSaurabh.Mishra@Sun.COM return;
11710393SSaurabh.Mishra@Sun.COM
11810393SSaurabh.Mishra@Sun.COM for (pages = 0; pages < L1E_RX_PAGES; pages++) {
11910393SSaurabh.Mishra@Sun.COM dma = l1e->atge_l1e_rx_page[pages];
12010393SSaurabh.Mishra@Sun.COM if (dma != NULL) {
12110393SSaurabh.Mishra@Sun.COM (void) ddi_dma_unbind_handle(dma->hdl);
12210393SSaurabh.Mishra@Sun.COM ddi_dma_mem_free(&dma->acchdl);
12310393SSaurabh.Mishra@Sun.COM ddi_dma_free_handle(&dma->hdl);
12410393SSaurabh.Mishra@Sun.COM kmem_free(dma, sizeof (atge_dma_t));
12510393SSaurabh.Mishra@Sun.COM }
12610393SSaurabh.Mishra@Sun.COM }
12710393SSaurabh.Mishra@Sun.COM
12810393SSaurabh.Mishra@Sun.COM kmem_free(l1e->atge_l1e_rx_page, L1E_RX_PAGES * sizeof (atge_dma_t *));
12910393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_page = NULL;
13010393SSaurabh.Mishra@Sun.COM }
13110393SSaurabh.Mishra@Sun.COM
13210393SSaurabh.Mishra@Sun.COM int
atge_l1e_alloc_dma(atge_t * atgep)13310393SSaurabh.Mishra@Sun.COM atge_l1e_alloc_dma(atge_t *atgep)
13410393SSaurabh.Mishra@Sun.COM {
13510393SSaurabh.Mishra@Sun.COM atge_dma_t *dma;
13610393SSaurabh.Mishra@Sun.COM atge_l1e_data_t *l1e;
13710393SSaurabh.Mishra@Sun.COM int err;
13810393SSaurabh.Mishra@Sun.COM int pages;
13910393SSaurabh.Mishra@Sun.COM int guard_size;
14010393SSaurabh.Mishra@Sun.COM
14110393SSaurabh.Mishra@Sun.COM l1e = kmem_zalloc(sizeof (atge_l1e_data_t), KM_SLEEP);
14210393SSaurabh.Mishra@Sun.COM atgep->atge_private_data = l1e;
14310393SSaurabh.Mishra@Sun.COM
14410393SSaurabh.Mishra@Sun.COM /*
14510393SSaurabh.Mishra@Sun.COM * Allocate TX ring descriptor.
14610393SSaurabh.Mishra@Sun.COM */
14710393SSaurabh.Mishra@Sun.COM atgep->atge_tx_buf_len = atgep->atge_mtu +
14810393SSaurabh.Mishra@Sun.COM sizeof (struct ether_header) + VLAN_TAGSZ + ETHERFCSL;
14910393SSaurabh.Mishra@Sun.COM atgep->atge_tx_ring = kmem_alloc(sizeof (atge_ring_t), KM_SLEEP);
15010393SSaurabh.Mishra@Sun.COM atgep->atge_tx_ring->r_atge = atgep;
15110393SSaurabh.Mishra@Sun.COM atgep->atge_tx_ring->r_desc_ring = NULL;
15210393SSaurabh.Mishra@Sun.COM dma = atge_alloc_a_dma_blk(atgep, &atge_l1e_dma_attr_tx_desc,
153*11353SSaurabh.Mishra@Sun.COM ATGE_TX_RING_SZ, DDI_DMA_RDWR);
15410393SSaurabh.Mishra@Sun.COM if (dma == NULL) {
15510393SSaurabh.Mishra@Sun.COM ATGE_DB(("%s :%s failed",
15610393SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__));
157*11353SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
15810393SSaurabh.Mishra@Sun.COM }
15910393SSaurabh.Mishra@Sun.COM atgep->atge_tx_ring->r_desc_ring = dma;
16010393SSaurabh.Mishra@Sun.COM
16110393SSaurabh.Mishra@Sun.COM /*
16210393SSaurabh.Mishra@Sun.COM * Allocate DMA buffers for TX ring.
16310393SSaurabh.Mishra@Sun.COM */
164*11353SSaurabh.Mishra@Sun.COM err = atge_alloc_buffers(atgep->atge_tx_ring, ATGE_TX_RING_CNT,
16510393SSaurabh.Mishra@Sun.COM atgep->atge_tx_buf_len, DDI_DMA_WRITE);
166*11353SSaurabh.Mishra@Sun.COM if (err != DDI_SUCCESS) {
16710393SSaurabh.Mishra@Sun.COM ATGE_DB(("%s :%s() TX buffers failed",
16810393SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__));
16910393SSaurabh.Mishra@Sun.COM return (err);
17010393SSaurabh.Mishra@Sun.COM }
17110393SSaurabh.Mishra@Sun.COM
17210393SSaurabh.Mishra@Sun.COM /*
17310393SSaurabh.Mishra@Sun.COM * Allocate RX pages.
17410393SSaurabh.Mishra@Sun.COM */
17510393SSaurabh.Mishra@Sun.COM atgep->atge_rx_buf_len = atgep->atge_mtu +
17610393SSaurabh.Mishra@Sun.COM sizeof (struct ether_header) + VLAN_TAGSZ + ETHERFCSL;
17710393SSaurabh.Mishra@Sun.COM
17810393SSaurabh.Mishra@Sun.COM if (atgep->atge_flags & ATGE_FLAG_JUMBO)
17910393SSaurabh.Mishra@Sun.COM guard_size = L1E_JUMBO_FRAMELEN;
18010393SSaurabh.Mishra@Sun.COM else
18110393SSaurabh.Mishra@Sun.COM guard_size = L1E_MAX_FRAMELEN;
18210393SSaurabh.Mishra@Sun.COM
18310393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_pagesize = ROUNDUP(guard_size + L1E_RX_PAGE_SZ,
18410393SSaurabh.Mishra@Sun.COM L1E_RX_PAGE_ALIGN);
18510393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_page =
18610393SSaurabh.Mishra@Sun.COM kmem_zalloc(L1E_RX_PAGES * sizeof (atge_dma_t *), KM_SLEEP);
18710393SSaurabh.Mishra@Sun.COM
18810393SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() atge_l1e_pagesize : %d, L1E_RX_PAGE_SZ : %d",
18910393SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__, l1e->atge_l1e_pagesize,
19010393SSaurabh.Mishra@Sun.COM L1E_RX_PAGE_SZ));
19110393SSaurabh.Mishra@Sun.COM
192*11353SSaurabh.Mishra@Sun.COM err = DDI_SUCCESS;
19310393SSaurabh.Mishra@Sun.COM for (pages = 0; pages < L1E_RX_PAGES; pages++) {
19410393SSaurabh.Mishra@Sun.COM dma = atge_alloc_a_dma_blk(atgep, &atge_l1e_dma_attr_rx_desc,
19510393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_pagesize, DDI_DMA_READ);
19610393SSaurabh.Mishra@Sun.COM
19710393SSaurabh.Mishra@Sun.COM if (dma == NULL) {
198*11353SSaurabh.Mishra@Sun.COM err = DDI_FAILURE;
19910393SSaurabh.Mishra@Sun.COM break;
20010393SSaurabh.Mishra@Sun.COM }
20110393SSaurabh.Mishra@Sun.COM
20210393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_page[pages] = dma;
20310393SSaurabh.Mishra@Sun.COM }
20410393SSaurabh.Mishra@Sun.COM
205*11353SSaurabh.Mishra@Sun.COM if (err == DDI_FAILURE) {
20610393SSaurabh.Mishra@Sun.COM ATGE_DB(("%s :%s RX pages failed",
20710393SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__));
208*11353SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
20910393SSaurabh.Mishra@Sun.COM }
21010393SSaurabh.Mishra@Sun.COM
21110393SSaurabh.Mishra@Sun.COM /*
21210393SSaurabh.Mishra@Sun.COM * Allocate CMB used for fetching interrupt status data.
21310393SSaurabh.Mishra@Sun.COM */
21410393SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() L1E_RX_CMB_SZ : %x", atgep->atge_name,
21510393SSaurabh.Mishra@Sun.COM __func__, L1E_RX_CMB_SZ));
21610393SSaurabh.Mishra@Sun.COM
217*11353SSaurabh.Mishra@Sun.COM err = DDI_SUCCESS;
21810393SSaurabh.Mishra@Sun.COM dma = atge_alloc_a_dma_blk(atgep, &atge_l1e_dma_attr_cmb,
21910393SSaurabh.Mishra@Sun.COM L1E_RX_CMB_SZ * L1E_RX_PAGES, DDI_DMA_RDWR);
22010393SSaurabh.Mishra@Sun.COM if (dma == NULL) {
22110393SSaurabh.Mishra@Sun.COM ATGE_DB(("%s :%s() RX CMB failed",
22210393SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__));
223*11353SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
22410393SSaurabh.Mishra@Sun.COM }
22510393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_cmb = dma;
22610393SSaurabh.Mishra@Sun.COM
227*11353SSaurabh.Mishra@Sun.COM if (err == DDI_FAILURE) {
22810393SSaurabh.Mishra@Sun.COM ATGE_DB(("%s :%s() RX CMB failed",
22910393SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__));
230*11353SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
23110393SSaurabh.Mishra@Sun.COM }
23210393SSaurabh.Mishra@Sun.COM
23310393SSaurabh.Mishra@Sun.COM atgep->atge_hw_stats = kmem_zalloc(sizeof (atge_l1e_smb_t), KM_SLEEP);
23410393SSaurabh.Mishra@Sun.COM
235*11353SSaurabh.Mishra@Sun.COM return (DDI_SUCCESS);
23610393SSaurabh.Mishra@Sun.COM }
23710393SSaurabh.Mishra@Sun.COM
23810393SSaurabh.Mishra@Sun.COM void
atge_l1e_free_dma(atge_t * atgep)23910393SSaurabh.Mishra@Sun.COM atge_l1e_free_dma(atge_t *atgep)
24010393SSaurabh.Mishra@Sun.COM {
24110393SSaurabh.Mishra@Sun.COM atge_l1e_data_t *l1e;
24210393SSaurabh.Mishra@Sun.COM
24310393SSaurabh.Mishra@Sun.COM /*
24410393SSaurabh.Mishra@Sun.COM * Free TX ring.
24510393SSaurabh.Mishra@Sun.COM */
24610393SSaurabh.Mishra@Sun.COM if (atgep->atge_tx_ring != NULL) {
247*11353SSaurabh.Mishra@Sun.COM atge_free_buffers(atgep->atge_tx_ring, ATGE_TX_RING_CNT);
24810393SSaurabh.Mishra@Sun.COM
24910393SSaurabh.Mishra@Sun.COM if (atgep->atge_tx_ring->r_desc_ring != NULL) {
25010393SSaurabh.Mishra@Sun.COM atge_free_a_dma_blk(atgep->atge_tx_ring->r_desc_ring);
25110393SSaurabh.Mishra@Sun.COM }
25210393SSaurabh.Mishra@Sun.COM
25310393SSaurabh.Mishra@Sun.COM kmem_free(atgep->atge_tx_ring, sizeof (atge_ring_t));
25410393SSaurabh.Mishra@Sun.COM atgep->atge_tx_ring = NULL;
25510393SSaurabh.Mishra@Sun.COM }
25610393SSaurabh.Mishra@Sun.COM
25710393SSaurabh.Mishra@Sun.COM l1e = atgep->atge_private_data;
25810393SSaurabh.Mishra@Sun.COM if (l1e == NULL)
25910393SSaurabh.Mishra@Sun.COM return;
26010393SSaurabh.Mishra@Sun.COM
26110393SSaurabh.Mishra@Sun.COM /*
26210393SSaurabh.Mishra@Sun.COM * Free RX CMB.
26310393SSaurabh.Mishra@Sun.COM */
26410393SSaurabh.Mishra@Sun.COM if (l1e->atge_l1e_rx_cmb != NULL) {
26510393SSaurabh.Mishra@Sun.COM atge_free_a_dma_blk(l1e->atge_l1e_rx_cmb);
26610393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_cmb = NULL;
26710393SSaurabh.Mishra@Sun.COM }
26810393SSaurabh.Mishra@Sun.COM
26910393SSaurabh.Mishra@Sun.COM /*
27010393SSaurabh.Mishra@Sun.COM * Free RX buffers and RX ring.
27110393SSaurabh.Mishra@Sun.COM */
27210393SSaurabh.Mishra@Sun.COM atge_rx_desc_free(atgep);
27310393SSaurabh.Mishra@Sun.COM
27410393SSaurabh.Mishra@Sun.COM /*
27510393SSaurabh.Mishra@Sun.COM * Free the memory allocated for gathering hw stats.
27610393SSaurabh.Mishra@Sun.COM */
27710393SSaurabh.Mishra@Sun.COM if (atgep->atge_hw_stats != NULL) {
27810393SSaurabh.Mishra@Sun.COM kmem_free(atgep->atge_hw_stats, sizeof (atge_l1e_smb_t));
27910393SSaurabh.Mishra@Sun.COM atgep->atge_hw_stats = NULL;
28010393SSaurabh.Mishra@Sun.COM }
28110393SSaurabh.Mishra@Sun.COM }
28210393SSaurabh.Mishra@Sun.COM
28310393SSaurabh.Mishra@Sun.COM void
atge_l1e_init_rx_pages(atge_t * atgep)28410393SSaurabh.Mishra@Sun.COM atge_l1e_init_rx_pages(atge_t *atgep)
28510393SSaurabh.Mishra@Sun.COM {
28610393SSaurabh.Mishra@Sun.COM atge_l1e_data_t *l1e;
28710393SSaurabh.Mishra@Sun.COM atge_dma_t *dma;
28810393SSaurabh.Mishra@Sun.COM int pages;
28910393SSaurabh.Mishra@Sun.COM
29010393SSaurabh.Mishra@Sun.COM ASSERT(atgep != NULL);
29110393SSaurabh.Mishra@Sun.COM l1e = atgep->atge_private_data;
29210393SSaurabh.Mishra@Sun.COM
29310393SSaurabh.Mishra@Sun.COM ASSERT(l1e != NULL);
29410393SSaurabh.Mishra@Sun.COM
29510393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_proc_max = L1E_RX_PAGE_SZ / ETHERMIN;
29610393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_curp = 0;
29710393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_seqno = 0;
29810393SSaurabh.Mishra@Sun.COM
29910393SSaurabh.Mishra@Sun.COM for (pages = 0; pages < L1E_RX_PAGES; pages++) {
30010393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_page_cons = 0;
30110393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_page_prods[pages] = 0;
30210393SSaurabh.Mishra@Sun.COM
30310393SSaurabh.Mishra@Sun.COM
30410393SSaurabh.Mishra@Sun.COM dma = l1e->atge_l1e_rx_page[pages];
30510393SSaurabh.Mishra@Sun.COM ASSERT(dma != NULL);
30610393SSaurabh.Mishra@Sun.COM bzero(dma->addr, l1e->atge_l1e_pagesize);
30710393SSaurabh.Mishra@Sun.COM DMA_SYNC(dma, 0, l1e->atge_l1e_pagesize, DDI_DMA_SYNC_FORDEV);
30810393SSaurabh.Mishra@Sun.COM }
30910393SSaurabh.Mishra@Sun.COM
31010393SSaurabh.Mishra@Sun.COM dma = l1e->atge_l1e_rx_cmb;
31110393SSaurabh.Mishra@Sun.COM ASSERT(dma != NULL);
31210393SSaurabh.Mishra@Sun.COM bzero(dma->addr, L1E_RX_CMB_SZ * L1E_RX_PAGES);
31310393SSaurabh.Mishra@Sun.COM DMA_SYNC(dma, 0, L1E_RX_CMB_SZ * L1E_RX_PAGES, DDI_DMA_SYNC_FORDEV);
31410393SSaurabh.Mishra@Sun.COM }
31510393SSaurabh.Mishra@Sun.COM
31610393SSaurabh.Mishra@Sun.COM void
atge_l1e_init_tx_ring(atge_t * atgep)31710393SSaurabh.Mishra@Sun.COM atge_l1e_init_tx_ring(atge_t *atgep)
31810393SSaurabh.Mishra@Sun.COM {
31910393SSaurabh.Mishra@Sun.COM ASSERT(atgep != NULL);
32010393SSaurabh.Mishra@Sun.COM ASSERT(atgep->atge_tx_ring != NULL);
32110393SSaurabh.Mishra@Sun.COM ASSERT(atgep->atge_tx_ring->r_desc_ring != NULL);
32210393SSaurabh.Mishra@Sun.COM
32310393SSaurabh.Mishra@Sun.COM atgep->atge_tx_ring->r_producer = 0;
32410393SSaurabh.Mishra@Sun.COM atgep->atge_tx_ring->r_consumer = 0;
325*11353SSaurabh.Mishra@Sun.COM atgep->atge_tx_ring->r_avail_desc = ATGE_TX_RING_CNT;
32610393SSaurabh.Mishra@Sun.COM
327*11353SSaurabh.Mishra@Sun.COM bzero(atgep->atge_tx_ring->r_desc_ring->addr, ATGE_TX_RING_SZ);
32810393SSaurabh.Mishra@Sun.COM
329*11353SSaurabh.Mishra@Sun.COM DMA_SYNC(atgep->atge_tx_ring->r_desc_ring, 0, ATGE_TX_RING_SZ,
33010393SSaurabh.Mishra@Sun.COM DDI_DMA_SYNC_FORDEV);
33110393SSaurabh.Mishra@Sun.COM }
33210393SSaurabh.Mishra@Sun.COM
33310393SSaurabh.Mishra@Sun.COM void
atge_l1e_program_dma(atge_t * atgep)33410393SSaurabh.Mishra@Sun.COM atge_l1e_program_dma(atge_t *atgep)
33510393SSaurabh.Mishra@Sun.COM {
33610393SSaurabh.Mishra@Sun.COM atge_l1e_data_t *l1e;
33710393SSaurabh.Mishra@Sun.COM uint64_t paddr;
33810393SSaurabh.Mishra@Sun.COM uint32_t reg;
33910393SSaurabh.Mishra@Sun.COM
34010393SSaurabh.Mishra@Sun.COM l1e = (atge_l1e_data_t *)atgep->atge_private_data;
34110393SSaurabh.Mishra@Sun.COM
34210393SSaurabh.Mishra@Sun.COM /*
34310393SSaurabh.Mishra@Sun.COM * Clear WOL status and disable all WOL feature as WOL
34410393SSaurabh.Mishra@Sun.COM * would interfere Rx operation under normal environments.
34510393SSaurabh.Mishra@Sun.COM */
34610393SSaurabh.Mishra@Sun.COM (void) INL(atgep, ATGE_WOL_CFG);
34710393SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_WOL_CFG, 0);
34810393SSaurabh.Mishra@Sun.COM
34910393SSaurabh.Mishra@Sun.COM /*
35010393SSaurabh.Mishra@Sun.COM * Set Tx descriptor/RXF0/CMB base addresses. They share
35110393SSaurabh.Mishra@Sun.COM * the same high address part of DMAable region.
35210393SSaurabh.Mishra@Sun.COM */
35310393SSaurabh.Mishra@Sun.COM paddr = atgep->atge_tx_ring->r_desc_ring->cookie.dmac_laddress;
35410393SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_DESC_ADDR_HI, ATGE_ADDR_HI(paddr));
35510393SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_DESC_TPD_ADDR_LO, ATGE_ADDR_LO(paddr));
35610393SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_DESC_TPD_CNT,
357*11353SSaurabh.Mishra@Sun.COM (ATGE_TX_RING_CNT << DESC_TPD_CNT_SHIFT) & DESC_TPD_CNT_MASK);
35810393SSaurabh.Mishra@Sun.COM
35910393SSaurabh.Mishra@Sun.COM /* Set Rx page base address, note we use single queue. */
36010393SSaurabh.Mishra@Sun.COM paddr = l1e->atge_l1e_rx_page[0]->cookie.dmac_laddress;
36110393SSaurabh.Mishra@Sun.COM OUTL(atgep, L1E_RXF0_PAGE0_ADDR_LO, ATGE_ADDR_LO(paddr));
36210393SSaurabh.Mishra@Sun.COM paddr = l1e->atge_l1e_rx_page[1]->cookie.dmac_laddress;
36310393SSaurabh.Mishra@Sun.COM OUTL(atgep, L1E_RXF0_PAGE1_ADDR_LO, ATGE_ADDR_LO(paddr));
36410393SSaurabh.Mishra@Sun.COM
36510393SSaurabh.Mishra@Sun.COM /* Set Tx/Rx CMB addresses. */
36610393SSaurabh.Mishra@Sun.COM paddr = l1e->atge_l1e_rx_cmb->cookie.dmac_laddress;
36710393SSaurabh.Mishra@Sun.COM OUTL(atgep, L1E_RXF0_CMB0_ADDR_LO, ATGE_ADDR_LO(paddr));
36810393SSaurabh.Mishra@Sun.COM paddr = l1e->atge_l1e_rx_cmb->cookie.dmac_laddress + sizeof (uint32_t);
36910393SSaurabh.Mishra@Sun.COM OUTL(atgep, L1E_RXF0_CMB1_ADDR_LO, ATGE_ADDR_LO(paddr));
37010393SSaurabh.Mishra@Sun.COM
37110393SSaurabh.Mishra@Sun.COM /* Mark RXF0 valid. */
37210393SSaurabh.Mishra@Sun.COM OUTB(atgep, L1E_RXF0_PAGE0, RXF_VALID); /* 0 */
37310393SSaurabh.Mishra@Sun.COM OUTB(atgep, L1E_RXF0_PAGE1, RXF_VALID); /* 1 */
37410393SSaurabh.Mishra@Sun.COM OUTB(atgep, L1E_RXF0_PAGE0 + 2, 0);
37510393SSaurabh.Mishra@Sun.COM OUTB(atgep, L1E_RXF0_PAGE0 + 3, 0);
37610393SSaurabh.Mishra@Sun.COM OUTB(atgep, L1E_RXF0_PAGE0 + 4, 0);
37710393SSaurabh.Mishra@Sun.COM OUTB(atgep, L1E_RXF0_PAGE0 + 5, 0);
37810393SSaurabh.Mishra@Sun.COM OUTB(atgep, L1E_RXF0_PAGE0 + 6, 0);
37910393SSaurabh.Mishra@Sun.COM OUTB(atgep, L1E_RXF0_PAGE0 + 6, 0);
38010393SSaurabh.Mishra@Sun.COM
38110393SSaurabh.Mishra@Sun.COM /* Set Rx page size, excluding guard frame size. */
38210393SSaurabh.Mishra@Sun.COM OUTL(atgep, L1E_RXF_PAGE_SIZE, L1E_RX_PAGE_SZ);
38310393SSaurabh.Mishra@Sun.COM
38410393SSaurabh.Mishra@Sun.COM /* Tell hardware that we're ready to load DMA blocks. */
38510393SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_DMA_BLOCK, DMA_BLOCK_LOAD);
38610393SSaurabh.Mishra@Sun.COM
38710393SSaurabh.Mishra@Sun.COM /* Set Rx/Tx interrupt trigger threshold. */
38810393SSaurabh.Mishra@Sun.COM OUTL(atgep, L1E_INT_TRIG_THRESH, (1 << INT_TRIG_RX_THRESH_SHIFT) |
38910393SSaurabh.Mishra@Sun.COM (4 << INT_TRIG_TX_THRESH_SHIFT));
39010393SSaurabh.Mishra@Sun.COM
39110393SSaurabh.Mishra@Sun.COM /*
39210393SSaurabh.Mishra@Sun.COM * Set interrupt trigger timer, its purpose and relation
39310393SSaurabh.Mishra@Sun.COM * with interrupt moderation mechanism is not clear yet.
39410393SSaurabh.Mishra@Sun.COM */
39510393SSaurabh.Mishra@Sun.COM OUTL(atgep, L1E_INT_TRIG_TIMER,
39610393SSaurabh.Mishra@Sun.COM ((ATGE_USECS(10) << INT_TRIG_RX_TIMER_SHIFT) |
39710393SSaurabh.Mishra@Sun.COM (ATGE_USECS(1000) << INT_TRIG_TX_TIMER_SHIFT)));
39810393SSaurabh.Mishra@Sun.COM
39910393SSaurabh.Mishra@Sun.COM reg = ATGE_USECS(ATGE_IM_RX_TIMER_DEFAULT) << IM_TIMER_RX_SHIFT;
40010393SSaurabh.Mishra@Sun.COM reg |= ATGE_USECS(ATGE_IM_TX_TIMER_DEFAULT) << IM_TIMER_TX_SHIFT;
40110393SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_IM_TIMER, reg);
40210393SSaurabh.Mishra@Sun.COM
40310393SSaurabh.Mishra@Sun.COM reg = INL(atgep, ATGE_MASTER_CFG);
40410393SSaurabh.Mishra@Sun.COM reg &= ~(MASTER_CHIP_REV_MASK | MASTER_CHIP_ID_MASK);
40510393SSaurabh.Mishra@Sun.COM reg &= ~(MASTER_IM_RX_TIMER_ENB | MASTER_IM_TX_TIMER_ENB);
40610393SSaurabh.Mishra@Sun.COM reg |= MASTER_IM_RX_TIMER_ENB;
40710393SSaurabh.Mishra@Sun.COM reg |= MASTER_IM_TX_TIMER_ENB;
40810393SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_MASTER_CFG, reg);
40910393SSaurabh.Mishra@Sun.COM
41010393SSaurabh.Mishra@Sun.COM OUTW(atgep, RX_COALSC_PKT_1e, 0);
41110393SSaurabh.Mishra@Sun.COM OUTW(atgep, RX_COALSC_TO_1e, 0);
41210393SSaurabh.Mishra@Sun.COM OUTW(atgep, TX_COALSC_PKT_1e, 1);
41310393SSaurabh.Mishra@Sun.COM OUTW(atgep, TX_COALSC_TO_1e, 4000/2); /* 4mS */
41410393SSaurabh.Mishra@Sun.COM }
41510393SSaurabh.Mishra@Sun.COM
41610393SSaurabh.Mishra@Sun.COM mblk_t *
atge_l1e_receive(atge_t * atgep)41710393SSaurabh.Mishra@Sun.COM atge_l1e_receive(atge_t *atgep)
41810393SSaurabh.Mishra@Sun.COM {
41910393SSaurabh.Mishra@Sun.COM atge_l1e_data_t *l1e;
42010393SSaurabh.Mishra@Sun.COM atge_dma_t *dma_rx_page;
42110393SSaurabh.Mishra@Sun.COM atge_dma_t *dma_rx_cmb;
42210393SSaurabh.Mishra@Sun.COM uint32_t *ptr;
42310393SSaurabh.Mishra@Sun.COM uint32_t cons, current_page;
42410393SSaurabh.Mishra@Sun.COM uchar_t *pageaddr, *bufp;
42510393SSaurabh.Mishra@Sun.COM rx_rs_t *rs;
42610393SSaurabh.Mishra@Sun.COM int prog;
42710393SSaurabh.Mishra@Sun.COM uint32_t seqno, len, flags;
42810393SSaurabh.Mishra@Sun.COM mblk_t *mp = NULL, *rx_head, *rx_tail;
42910393SSaurabh.Mishra@Sun.COM static uint32_t gen = 0;
43010393SSaurabh.Mishra@Sun.COM
43110393SSaurabh.Mishra@Sun.COM l1e = atgep->atge_private_data;
43210393SSaurabh.Mishra@Sun.COM
43310393SSaurabh.Mishra@Sun.COM ASSERT(MUTEX_HELD(&atgep->atge_intr_lock));
43410393SSaurabh.Mishra@Sun.COM ASSERT(l1e != NULL);
43510393SSaurabh.Mishra@Sun.COM
43610393SSaurabh.Mishra@Sun.COM rx_tail = NULL;
43710393SSaurabh.Mishra@Sun.COM rx_head = NULL;
43810393SSaurabh.Mishra@Sun.COM
43910393SSaurabh.Mishra@Sun.COM current_page = l1e->atge_l1e_rx_curp;
44010393SSaurabh.Mishra@Sun.COM
44110393SSaurabh.Mishra@Sun.COM /* Sync CMB first */
44210393SSaurabh.Mishra@Sun.COM dma_rx_cmb = l1e->atge_l1e_rx_cmb;
44310393SSaurabh.Mishra@Sun.COM DMA_SYNC(dma_rx_cmb, 0, L1E_RX_CMB_SZ * L1E_RX_PAGES,
44410393SSaurabh.Mishra@Sun.COM DDI_DMA_SYNC_FORKERNEL);
44510393SSaurabh.Mishra@Sun.COM
44610393SSaurabh.Mishra@Sun.COM dma_rx_page = l1e->atge_l1e_rx_page[current_page];
44710393SSaurabh.Mishra@Sun.COM
44810393SSaurabh.Mishra@Sun.COM /*
44910393SSaurabh.Mishra@Sun.COM * Get the producer offset from CMB.
45010393SSaurabh.Mishra@Sun.COM */
45110393SSaurabh.Mishra@Sun.COM ptr = (void *)dma_rx_cmb->addr;
45210393SSaurabh.Mishra@Sun.COM
45310393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_page_prods[current_page] =
45410393SSaurabh.Mishra@Sun.COM ATGE_GET32(dma_rx_cmb, ptr + current_page);
45510393SSaurabh.Mishra@Sun.COM
45610393SSaurabh.Mishra@Sun.COM /* Sync current RX Page as well */
45710393SSaurabh.Mishra@Sun.COM DMA_SYNC(dma_rx_page, l1e->atge_l1e_rx_page_cons,
45810393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_page_prods[current_page], DDI_DMA_SYNC_FORKERNEL);
45910393SSaurabh.Mishra@Sun.COM
46010393SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() prod : %d, cons : %d, curr page : %d, gen : (%d)"
46110393SSaurabh.Mishra@Sun.COM " cmb[0,1] : %d, %d",
46210393SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__,
46310393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_page_prods[current_page],
46410393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_page_cons, l1e->atge_l1e_rx_curp, gen,
46510393SSaurabh.Mishra@Sun.COM ATGE_GET32(dma_rx_cmb, ptr), ATGE_GET32(dma_rx_cmb, ptr + 1)));
46610393SSaurabh.Mishra@Sun.COM
46710393SSaurabh.Mishra@Sun.COM for (prog = 0; prog <= l1e->atge_l1e_proc_max; prog++) {
46810393SSaurabh.Mishra@Sun.COM cons = l1e->atge_l1e_rx_page_cons;
46910393SSaurabh.Mishra@Sun.COM if (cons >= l1e->atge_l1e_rx_page_prods[l1e->atge_l1e_rx_curp])
47010393SSaurabh.Mishra@Sun.COM break;
47110393SSaurabh.Mishra@Sun.COM
47210393SSaurabh.Mishra@Sun.COM dma_rx_page = l1e->atge_l1e_rx_page[l1e->atge_l1e_rx_curp];
47310393SSaurabh.Mishra@Sun.COM pageaddr = (uchar_t *)dma_rx_page->addr;
47410393SSaurabh.Mishra@Sun.COM pageaddr = pageaddr + cons;
47510393SSaurabh.Mishra@Sun.COM rs = (rx_rs_t *)pageaddr;
47610393SSaurabh.Mishra@Sun.COM
47710393SSaurabh.Mishra@Sun.COM seqno = ATGE_GET32(dma_rx_page, &(rs->seqno));
47810393SSaurabh.Mishra@Sun.COM seqno = L1E_RX_SEQNO(seqno);
47910393SSaurabh.Mishra@Sun.COM
48010393SSaurabh.Mishra@Sun.COM len = ATGE_GET32(dma_rx_page, &(rs->length));
48110393SSaurabh.Mishra@Sun.COM len = L1E_RX_BYTES(len);
48210393SSaurabh.Mishra@Sun.COM
48310393SSaurabh.Mishra@Sun.COM flags = ATGE_GET32(dma_rx_page, &(rs->flags));
48410393SSaurabh.Mishra@Sun.COM
48510393SSaurabh.Mishra@Sun.COM if (seqno != l1e->atge_l1e_rx_seqno) {
48610393SSaurabh.Mishra@Sun.COM /*
48710393SSaurabh.Mishra@Sun.COM * We have not seen this happening but we
48810393SSaurabh.Mishra@Sun.COM * must restart the chip if that happens.
48910393SSaurabh.Mishra@Sun.COM */
49010393SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() MISS-MATCH in seqno :%d,"
49110393SSaurabh.Mishra@Sun.COM " atge_l1e_rx_seqno : %d, length : %d, flags : %x",
49210393SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__, seqno,
49310393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_seqno, len, flags));
49410393SSaurabh.Mishra@Sun.COM
49510393SSaurabh.Mishra@Sun.COM mutex_enter(&atgep->atge_tx_lock);
49610393SSaurabh.Mishra@Sun.COM atge_device_restart(atgep);
49710393SSaurabh.Mishra@Sun.COM mutex_exit(&atgep->atge_tx_lock);
49810393SSaurabh.Mishra@Sun.COM
49910393SSaurabh.Mishra@Sun.COM /*
50010393SSaurabh.Mishra@Sun.COM * Return all the pkts received before restarting
50110393SSaurabh.Mishra@Sun.COM * the chip.
50210393SSaurabh.Mishra@Sun.COM */
50310393SSaurabh.Mishra@Sun.COM return (rx_head);
50410393SSaurabh.Mishra@Sun.COM } else {
50510393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_seqno++;
50610393SSaurabh.Mishra@Sun.COM }
50710393SSaurabh.Mishra@Sun.COM
50810393SSaurabh.Mishra@Sun.COM /*
50910393SSaurabh.Mishra@Sun.COM * We will pass the pkt to upper layer provided it's clear
51010393SSaurabh.Mishra@Sun.COM * from any error.
51110393SSaurabh.Mishra@Sun.COM */
51210393SSaurabh.Mishra@Sun.COM if ((flags & L1E_RD_ERROR) != 0) {
51310393SSaurabh.Mishra@Sun.COM if ((flags & (L1E_RD_CRC | L1E_RD_CODE |
51410393SSaurabh.Mishra@Sun.COM L1E_RD_DRIBBLE | L1E_RD_RUNT | L1E_RD_OFLOW |
51510393SSaurabh.Mishra@Sun.COM L1E_RD_TRUNC)) != 0) {
51610393SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() ERRORED PKT : %x",
51710393SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__, flags));
51810393SSaurabh.Mishra@Sun.COM atge_l1e_rx_next_pkt(atgep, len);
51910393SSaurabh.Mishra@Sun.COM atgep->atge_errrcv++;
52010393SSaurabh.Mishra@Sun.COM continue;
52110393SSaurabh.Mishra@Sun.COM }
52210393SSaurabh.Mishra@Sun.COM }
52310393SSaurabh.Mishra@Sun.COM
52410393SSaurabh.Mishra@Sun.COM /*
52510393SSaurabh.Mishra@Sun.COM * So we have received a frame/pkt.
52610393SSaurabh.Mishra@Sun.COM */
52710393SSaurabh.Mishra@Sun.COM if (len == 0 || len > atgep->atge_rx_buf_len) {
52810393SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() PKT len > error : %d",
52910393SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__, len));
53010393SSaurabh.Mishra@Sun.COM atge_l1e_rx_next_pkt(atgep, len);
53110393SSaurabh.Mishra@Sun.COM continue;
53210393SSaurabh.Mishra@Sun.COM }
53310393SSaurabh.Mishra@Sun.COM
53410393SSaurabh.Mishra@Sun.COM mp = allocb(len + VLAN_TAGSZ, BPRI_MED);
53510393SSaurabh.Mishra@Sun.COM if (mp != NULL) {
53610393SSaurabh.Mishra@Sun.COM mp->b_rptr += VLAN_TAGSZ;
53710393SSaurabh.Mishra@Sun.COM bufp = mp->b_rptr;
53810393SSaurabh.Mishra@Sun.COM mp->b_wptr = bufp + len;
53910393SSaurabh.Mishra@Sun.COM mp->b_next = NULL;
54010393SSaurabh.Mishra@Sun.COM
54110393SSaurabh.Mishra@Sun.COM bcopy(pageaddr + sizeof (rx_rs_t), bufp, len);
54210393SSaurabh.Mishra@Sun.COM
54310393SSaurabh.Mishra@Sun.COM if (rx_tail == NULL)
54410393SSaurabh.Mishra@Sun.COM rx_head = rx_tail = mp;
54510393SSaurabh.Mishra@Sun.COM else {
54610393SSaurabh.Mishra@Sun.COM rx_tail->b_next = mp;
54710393SSaurabh.Mishra@Sun.COM rx_tail = mp;
54810393SSaurabh.Mishra@Sun.COM }
54910393SSaurabh.Mishra@Sun.COM
55010393SSaurabh.Mishra@Sun.COM atgep->atge_ipackets++;
55110393SSaurabh.Mishra@Sun.COM atgep->atge_rbytes += len;
55210393SSaurabh.Mishra@Sun.COM } else {
55310393SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() PKT mp == NULL len : %d",
55410393SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__, len));
55510393SSaurabh.Mishra@Sun.COM
55610393SSaurabh.Mishra@Sun.COM if (len > atgep->atge_rx_buf_len) {
55710393SSaurabh.Mishra@Sun.COM atgep->atge_toolong_errors++;
55810393SSaurabh.Mishra@Sun.COM } else if (mp == NULL) {
55910393SSaurabh.Mishra@Sun.COM atgep->atge_norcvbuf++;
56010393SSaurabh.Mishra@Sun.COM }
56110393SSaurabh.Mishra@Sun.COM }
56210393SSaurabh.Mishra@Sun.COM
56310393SSaurabh.Mishra@Sun.COM atge_l1e_rx_next_pkt(atgep, len);
56410393SSaurabh.Mishra@Sun.COM
56510393SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() seqno :%d, atge_l1e_rx_seqno :"
56610393SSaurabh.Mishra@Sun.COM " %d, length : %d,"
56710393SSaurabh.Mishra@Sun.COM " flags : %x, cons : %d, prod : %d",
56810393SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__, seqno,
56910393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_seqno, len, flags,
57010393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_page_cons,
57110393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_page_prods[l1e->atge_l1e_rx_curp]));
57210393SSaurabh.Mishra@Sun.COM }
57310393SSaurabh.Mishra@Sun.COM
57410393SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() receive completed (gen : %d) : cons : %d,"
57510393SSaurabh.Mishra@Sun.COM " prod :%d, L1E_RX_PAGE_SZ : %d (prog:%d)",
57610393SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__, gen,
57710393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_page_cons,
57810393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_page_prods[l1e->atge_l1e_rx_curp],
57910393SSaurabh.Mishra@Sun.COM L1E_RX_PAGE_SZ, prog));
58010393SSaurabh.Mishra@Sun.COM
58110393SSaurabh.Mishra@Sun.COM gen++;
58210393SSaurabh.Mishra@Sun.COM return (rx_head);
58310393SSaurabh.Mishra@Sun.COM }
58410393SSaurabh.Mishra@Sun.COM
58510393SSaurabh.Mishra@Sun.COM void
atge_l1e_rx_next_pkt(atge_t * atgep,uint32_t len)58610393SSaurabh.Mishra@Sun.COM atge_l1e_rx_next_pkt(atge_t *atgep, uint32_t len)
58710393SSaurabh.Mishra@Sun.COM {
58810393SSaurabh.Mishra@Sun.COM atge_l1e_data_t *l1e = atgep->atge_private_data;
58910393SSaurabh.Mishra@Sun.COM atge_dma_t *dma_rx_page;
59010393SSaurabh.Mishra@Sun.COM atge_dma_t *dma_rx_cmb;
59110393SSaurabh.Mishra@Sun.COM int curr = l1e->atge_l1e_rx_curp;
59210393SSaurabh.Mishra@Sun.COM uint32_t *p;
59310393SSaurabh.Mishra@Sun.COM
59410393SSaurabh.Mishra@Sun.COM /*
59510393SSaurabh.Mishra@Sun.COM * Update consumer position.
59610393SSaurabh.Mishra@Sun.COM */
59710393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_page_cons +=
59810393SSaurabh.Mishra@Sun.COM ROUNDUP(len + sizeof (rx_rs_t), L1E_RX_PAGE_ALIGN);
59910393SSaurabh.Mishra@Sun.COM
60010393SSaurabh.Mishra@Sun.COM /*
60110393SSaurabh.Mishra@Sun.COM * If we need to flip to the other page. Note that we use only two
60210393SSaurabh.Mishra@Sun.COM * pages.
60310393SSaurabh.Mishra@Sun.COM */
60410393SSaurabh.Mishra@Sun.COM if (l1e->atge_l1e_rx_page_cons >= L1E_RX_PAGE_SZ) {
60510393SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() cons : %d, prod :%d, L1E_RX_PAGE_SZ : %d",
60610393SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__, l1e->atge_l1e_rx_page_cons,
60710393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_page_prods[curr], L1E_RX_PAGE_SZ));
60810393SSaurabh.Mishra@Sun.COM
60910393SSaurabh.Mishra@Sun.COM /*
61010393SSaurabh.Mishra@Sun.COM * Clear the producer.
61110393SSaurabh.Mishra@Sun.COM */
61210393SSaurabh.Mishra@Sun.COM dma_rx_cmb = l1e->atge_l1e_rx_cmb;
61310393SSaurabh.Mishra@Sun.COM p = (void *)dma_rx_cmb->addr;
61410393SSaurabh.Mishra@Sun.COM p = p + curr;
61510393SSaurabh.Mishra@Sun.COM *p = 0;
61610393SSaurabh.Mishra@Sun.COM DMA_SYNC(dma_rx_cmb, curr * L1E_RX_CMB_SZ,
61710393SSaurabh.Mishra@Sun.COM L1E_RX_CMB_SZ, DDI_DMA_SYNC_FORDEV);
61810393SSaurabh.Mishra@Sun.COM
61910393SSaurabh.Mishra@Sun.COM /*
62010393SSaurabh.Mishra@Sun.COM * Notify the NIC that the current RX page is available again.
62110393SSaurabh.Mishra@Sun.COM */
62210393SSaurabh.Mishra@Sun.COM OUTB(atgep, L1E_RXF0_PAGE0 + curr, RXF_VALID);
62310393SSaurabh.Mishra@Sun.COM
62410393SSaurabh.Mishra@Sun.COM /*
62510393SSaurabh.Mishra@Sun.COM * End of Rx page reached, let hardware reuse this page.
62610393SSaurabh.Mishra@Sun.COM */
62710393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_page_cons = 0;
62810393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_page_prods[curr] = 0;
62910393SSaurabh.Mishra@Sun.COM
63010393SSaurabh.Mishra@Sun.COM /*
63110393SSaurabh.Mishra@Sun.COM * Switch to alternate Rx page.
63210393SSaurabh.Mishra@Sun.COM */
63310393SSaurabh.Mishra@Sun.COM curr ^= 1;
63410393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_curp = curr;
63510393SSaurabh.Mishra@Sun.COM
63610393SSaurabh.Mishra@Sun.COM /*
63710393SSaurabh.Mishra@Sun.COM * Page flipped, sync CMB and then Rx page.
63810393SSaurabh.Mishra@Sun.COM */
63910393SSaurabh.Mishra@Sun.COM DMA_SYNC(dma_rx_cmb, 0, L1E_RX_PAGES * L1E_RX_CMB_SZ,
64010393SSaurabh.Mishra@Sun.COM DDI_DMA_SYNC_FORKERNEL);
64110393SSaurabh.Mishra@Sun.COM p = (void *)dma_rx_cmb->addr;
64210393SSaurabh.Mishra@Sun.COM l1e->atge_l1e_rx_page_prods[curr] =
64310393SSaurabh.Mishra@Sun.COM ATGE_GET32(dma_rx_cmb, p + curr);
64410393SSaurabh.Mishra@Sun.COM
64510393SSaurabh.Mishra@Sun.COM dma_rx_page = l1e->atge_l1e_rx_page[curr];
64610393SSaurabh.Mishra@Sun.COM DMA_SYNC(dma_rx_page, 0, l1e->atge_l1e_rx_page_prods[curr],
64710393SSaurabh.Mishra@Sun.COM DDI_DMA_SYNC_FORKERNEL);
64810393SSaurabh.Mishra@Sun.COM
64910393SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() PAGE FLIPPED -> %d, producer[0,1]: %d, %d",
65010393SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__, curr,
65110393SSaurabh.Mishra@Sun.COM ATGE_GET32(dma_rx_cmb, p), ATGE_GET32(dma_rx_cmb, p + 1)));
65210393SSaurabh.Mishra@Sun.COM }
65310393SSaurabh.Mishra@Sun.COM }
65410393SSaurabh.Mishra@Sun.COM
65510393SSaurabh.Mishra@Sun.COM void
atge_l1e_send_packet(atge_ring_t * r)656*11353SSaurabh.Mishra@Sun.COM atge_l1e_send_packet(atge_ring_t *r)
65710393SSaurabh.Mishra@Sun.COM {
65810393SSaurabh.Mishra@Sun.COM /*
65910393SSaurabh.Mishra@Sun.COM * Ask chip to send the packet now.
66010393SSaurabh.Mishra@Sun.COM */
66110393SSaurabh.Mishra@Sun.COM OUTL(r->r_atge, ATGE_MBOX, r->r_producer);
66210393SSaurabh.Mishra@Sun.COM }
66310393SSaurabh.Mishra@Sun.COM
66410393SSaurabh.Mishra@Sun.COM void
atge_l1e_clear_stats(atge_t * atgep)66510393SSaurabh.Mishra@Sun.COM atge_l1e_clear_stats(atge_t *atgep)
66610393SSaurabh.Mishra@Sun.COM {
66710393SSaurabh.Mishra@Sun.COM atge_l1e_smb_t smb;
66810393SSaurabh.Mishra@Sun.COM uint32_t *reg;
66910393SSaurabh.Mishra@Sun.COM int i;
67010393SSaurabh.Mishra@Sun.COM
67110393SSaurabh.Mishra@Sun.COM /*
67210393SSaurabh.Mishra@Sun.COM * Clear RX stats first.
67310393SSaurabh.Mishra@Sun.COM */
67410393SSaurabh.Mishra@Sun.COM i = 0;
67510393SSaurabh.Mishra@Sun.COM reg = &smb.rx_frames;
67610393SSaurabh.Mishra@Sun.COM while (reg++ <= &smb.rx_pkts_filtered) {
67710393SSaurabh.Mishra@Sun.COM (void) INL(atgep, L1E_RX_MIB_BASE + i);
67810393SSaurabh.Mishra@Sun.COM i += sizeof (uint32_t);
67910393SSaurabh.Mishra@Sun.COM }
68010393SSaurabh.Mishra@Sun.COM
68110393SSaurabh.Mishra@Sun.COM /*
68210393SSaurabh.Mishra@Sun.COM * Clear TX stats.
68310393SSaurabh.Mishra@Sun.COM */
68410393SSaurabh.Mishra@Sun.COM i = 0;
68510393SSaurabh.Mishra@Sun.COM reg = &smb.tx_frames;
68610393SSaurabh.Mishra@Sun.COM while (reg++ <= &smb.tx_mcast_bytes) {
68710393SSaurabh.Mishra@Sun.COM (void) INL(atgep, L1E_TX_MIB_BASE + i);
68810393SSaurabh.Mishra@Sun.COM i += sizeof (uint32_t);
68910393SSaurabh.Mishra@Sun.COM }
69010393SSaurabh.Mishra@Sun.COM }
69110393SSaurabh.Mishra@Sun.COM
69210393SSaurabh.Mishra@Sun.COM void
atge_l1e_gather_stats(atge_t * atgep)69310393SSaurabh.Mishra@Sun.COM atge_l1e_gather_stats(atge_t *atgep)
69410393SSaurabh.Mishra@Sun.COM {
69510393SSaurabh.Mishra@Sun.COM atge_l1e_smb_t *stat;
69610393SSaurabh.Mishra@Sun.COM atge_l1e_smb_t *smb;
69710393SSaurabh.Mishra@Sun.COM atge_l1e_smb_t local_smb;
69810393SSaurabh.Mishra@Sun.COM uint32_t *reg;
69910393SSaurabh.Mishra@Sun.COM int i;
70010393SSaurabh.Mishra@Sun.COM
70110393SSaurabh.Mishra@Sun.COM ASSERT(atgep != NULL);
70210393SSaurabh.Mishra@Sun.COM
70310393SSaurabh.Mishra@Sun.COM stat = (atge_l1e_smb_t *)atgep->atge_hw_stats;
70410393SSaurabh.Mishra@Sun.COM
70510393SSaurabh.Mishra@Sun.COM bzero(&local_smb, sizeof (atge_l1e_smb_t));
70610393SSaurabh.Mishra@Sun.COM smb = &local_smb;
70710393SSaurabh.Mishra@Sun.COM
70810393SSaurabh.Mishra@Sun.COM /* Read Rx statistics. */
70910393SSaurabh.Mishra@Sun.COM i = 0;
71010393SSaurabh.Mishra@Sun.COM reg = &smb->rx_frames;
71110393SSaurabh.Mishra@Sun.COM while (reg++ <= &smb->rx_pkts_filtered) {
71210393SSaurabh.Mishra@Sun.COM *reg = INL(atgep, L1E_RX_MIB_BASE + i);
71310393SSaurabh.Mishra@Sun.COM i += sizeof (uint32_t);
71410393SSaurabh.Mishra@Sun.COM }
71510393SSaurabh.Mishra@Sun.COM
71610393SSaurabh.Mishra@Sun.COM /* Read Tx statistics. */
71710393SSaurabh.Mishra@Sun.COM i = 0;
71810393SSaurabh.Mishra@Sun.COM reg = &smb->tx_frames;
71910393SSaurabh.Mishra@Sun.COM while (reg++ <= &smb->tx_mcast_bytes) {
72010393SSaurabh.Mishra@Sun.COM *reg = INL(atgep, L1E_TX_MIB_BASE + i);
72110393SSaurabh.Mishra@Sun.COM i += sizeof (uint32_t);
72210393SSaurabh.Mishra@Sun.COM }
72310393SSaurabh.Mishra@Sun.COM
72410393SSaurabh.Mishra@Sun.COM /*
72510393SSaurabh.Mishra@Sun.COM * SMB is cleared everytime we read; hence we always do '+='.
72610393SSaurabh.Mishra@Sun.COM */
72710393SSaurabh.Mishra@Sun.COM
72810393SSaurabh.Mishra@Sun.COM /* Rx stats. */
72910393SSaurabh.Mishra@Sun.COM stat->rx_frames += smb->rx_frames;
73010393SSaurabh.Mishra@Sun.COM stat->rx_bcast_frames += smb->rx_bcast_frames;
73110393SSaurabh.Mishra@Sun.COM stat->rx_mcast_frames += smb->rx_mcast_frames;
73210393SSaurabh.Mishra@Sun.COM stat->rx_pause_frames += smb->rx_pause_frames;
73310393SSaurabh.Mishra@Sun.COM stat->rx_control_frames += smb->rx_control_frames;
73410393SSaurabh.Mishra@Sun.COM stat->rx_crcerrs += smb->rx_crcerrs;
73510393SSaurabh.Mishra@Sun.COM stat->rx_lenerrs += smb->rx_lenerrs;
73610393SSaurabh.Mishra@Sun.COM stat->rx_bytes += smb->rx_bytes;
73710393SSaurabh.Mishra@Sun.COM stat->rx_runts += smb->rx_runts;
73810393SSaurabh.Mishra@Sun.COM stat->rx_fragments += smb->rx_fragments;
73910393SSaurabh.Mishra@Sun.COM stat->rx_pkts_64 += smb->rx_pkts_64;
74010393SSaurabh.Mishra@Sun.COM stat->rx_pkts_65_127 += smb->rx_pkts_65_127;
74110393SSaurabh.Mishra@Sun.COM stat->rx_pkts_128_255 += smb->rx_pkts_128_255;
74210393SSaurabh.Mishra@Sun.COM stat->rx_pkts_256_511 += smb->rx_pkts_256_511;
74310393SSaurabh.Mishra@Sun.COM stat->rx_pkts_512_1023 += smb->rx_pkts_512_1023;
74410393SSaurabh.Mishra@Sun.COM stat->rx_pkts_1024_1518 += smb->rx_pkts_1024_1518;
74510393SSaurabh.Mishra@Sun.COM stat->rx_pkts_1519_max += smb->rx_pkts_1519_max;
74610393SSaurabh.Mishra@Sun.COM stat->rx_pkts_truncated += smb->rx_pkts_truncated;
74710393SSaurabh.Mishra@Sun.COM stat->rx_fifo_oflows += smb->rx_fifo_oflows;
74810393SSaurabh.Mishra@Sun.COM stat->rx_rrs_errs += smb->rx_rrs_errs;
74910393SSaurabh.Mishra@Sun.COM stat->rx_alignerrs += smb->rx_alignerrs;
75010393SSaurabh.Mishra@Sun.COM stat->rx_bcast_bytes += smb->rx_bcast_bytes;
75110393SSaurabh.Mishra@Sun.COM stat->rx_mcast_bytes += smb->rx_mcast_bytes;
75210393SSaurabh.Mishra@Sun.COM stat->rx_pkts_filtered += smb->rx_pkts_filtered;
75310393SSaurabh.Mishra@Sun.COM
75410393SSaurabh.Mishra@Sun.COM /* Tx stats. */
75510393SSaurabh.Mishra@Sun.COM stat->tx_frames += smb->tx_frames;
75610393SSaurabh.Mishra@Sun.COM stat->tx_bcast_frames += smb->tx_bcast_frames;
75710393SSaurabh.Mishra@Sun.COM stat->tx_mcast_frames += smb->tx_mcast_frames;
75810393SSaurabh.Mishra@Sun.COM stat->tx_pause_frames += smb->tx_pause_frames;
75910393SSaurabh.Mishra@Sun.COM stat->tx_excess_defer += smb->tx_excess_defer;
76010393SSaurabh.Mishra@Sun.COM stat->tx_control_frames += smb->tx_control_frames;
76110393SSaurabh.Mishra@Sun.COM stat->tx_deferred += smb->tx_deferred;
76210393SSaurabh.Mishra@Sun.COM stat->tx_bytes += smb->tx_bytes;
76310393SSaurabh.Mishra@Sun.COM stat->tx_pkts_64 += smb->tx_pkts_64;
76410393SSaurabh.Mishra@Sun.COM stat->tx_pkts_65_127 += smb->tx_pkts_65_127;
76510393SSaurabh.Mishra@Sun.COM stat->tx_pkts_128_255 += smb->tx_pkts_128_255;
76610393SSaurabh.Mishra@Sun.COM stat->tx_pkts_256_511 += smb->tx_pkts_256_511;
76710393SSaurabh.Mishra@Sun.COM stat->tx_pkts_512_1023 += smb->tx_pkts_512_1023;
76810393SSaurabh.Mishra@Sun.COM stat->tx_pkts_1024_1518 += smb->tx_pkts_1024_1518;
76910393SSaurabh.Mishra@Sun.COM stat->tx_pkts_1519_max += smb->tx_pkts_1519_max;
77010393SSaurabh.Mishra@Sun.COM stat->tx_single_colls += smb->tx_single_colls;
77110393SSaurabh.Mishra@Sun.COM stat->tx_multi_colls += smb->tx_multi_colls;
77210393SSaurabh.Mishra@Sun.COM stat->tx_late_colls += smb->tx_late_colls;
77310393SSaurabh.Mishra@Sun.COM stat->tx_excess_colls += smb->tx_excess_colls;
77410393SSaurabh.Mishra@Sun.COM stat->tx_abort += smb->tx_abort;
77510393SSaurabh.Mishra@Sun.COM stat->tx_underrun += smb->tx_underrun;
77610393SSaurabh.Mishra@Sun.COM stat->tx_desc_underrun += smb->tx_desc_underrun;
77710393SSaurabh.Mishra@Sun.COM stat->tx_lenerrs += smb->tx_lenerrs;
77810393SSaurabh.Mishra@Sun.COM stat->tx_pkts_truncated += smb->tx_pkts_truncated;
77910393SSaurabh.Mishra@Sun.COM stat->tx_bcast_bytes += smb->tx_bcast_bytes;
78010393SSaurabh.Mishra@Sun.COM stat->tx_mcast_bytes += smb->tx_mcast_bytes;
78110393SSaurabh.Mishra@Sun.COM
78210393SSaurabh.Mishra@Sun.COM /*
78310393SSaurabh.Mishra@Sun.COM * Update global counters in atge_t.
78410393SSaurabh.Mishra@Sun.COM */
78510393SSaurabh.Mishra@Sun.COM atgep->atge_brdcstrcv += smb->rx_bcast_frames;
78610393SSaurabh.Mishra@Sun.COM atgep->atge_multircv += smb->rx_mcast_frames;
78710393SSaurabh.Mishra@Sun.COM atgep->atge_multixmt += smb->tx_mcast_frames;
78810393SSaurabh.Mishra@Sun.COM atgep->atge_brdcstxmt += smb->tx_bcast_frames;
78910393SSaurabh.Mishra@Sun.COM
79010393SSaurabh.Mishra@Sun.COM atgep->atge_align_errors += smb->rx_alignerrs;
79110393SSaurabh.Mishra@Sun.COM atgep->atge_fcs_errors += smb->rx_crcerrs;
79210393SSaurabh.Mishra@Sun.COM atgep->atge_sqe_errors += smb->rx_rrs_errs;
79310393SSaurabh.Mishra@Sun.COM atgep->atge_defer_xmts += smb->tx_deferred;
79410393SSaurabh.Mishra@Sun.COM atgep->atge_first_collisions += smb->tx_single_colls;
79510393SSaurabh.Mishra@Sun.COM atgep->atge_multi_collisions += smb->tx_multi_colls * 2;
79610393SSaurabh.Mishra@Sun.COM atgep->atge_tx_late_collisions += smb->tx_late_colls;
79710393SSaurabh.Mishra@Sun.COM atgep->atge_ex_collisions += smb->tx_excess_colls;
79810393SSaurabh.Mishra@Sun.COM atgep->atge_macxmt_errors += smb->tx_abort;
79910393SSaurabh.Mishra@Sun.COM atgep->atge_toolong_errors += smb->rx_lenerrs;
80010393SSaurabh.Mishra@Sun.COM atgep->atge_overflow += smb->rx_fifo_oflows;
80110393SSaurabh.Mishra@Sun.COM atgep->atge_underflow += (smb->tx_underrun + smb->tx_desc_underrun);
80210393SSaurabh.Mishra@Sun.COM atgep->atge_runt += smb->rx_runts;
80310393SSaurabh.Mishra@Sun.COM
80410393SSaurabh.Mishra@Sun.COM
80510393SSaurabh.Mishra@Sun.COM atgep->atge_collisions += smb->tx_single_colls +
80610393SSaurabh.Mishra@Sun.COM smb->tx_multi_colls * 2 + smb->tx_late_colls +
80710393SSaurabh.Mishra@Sun.COM smb->tx_abort * HDPX_CFG_RETRY_DEFAULT;
80810393SSaurabh.Mishra@Sun.COM
80910393SSaurabh.Mishra@Sun.COM /*
81010393SSaurabh.Mishra@Sun.COM * tx_pkts_truncated counter looks suspicious. It constantly
81110393SSaurabh.Mishra@Sun.COM * increments with no sign of Tx errors. Hence we don't factor it.
81210393SSaurabh.Mishra@Sun.COM */
81310393SSaurabh.Mishra@Sun.COM atgep->atge_macxmt_errors += smb->tx_abort + smb->tx_late_colls +
81410393SSaurabh.Mishra@Sun.COM smb->tx_underrun;
81510393SSaurabh.Mishra@Sun.COM
81610393SSaurabh.Mishra@Sun.COM atgep->atge_macrcv_errors += smb->rx_crcerrs + smb->rx_lenerrs +
81710393SSaurabh.Mishra@Sun.COM smb->rx_runts + smb->rx_pkts_truncated +
81810393SSaurabh.Mishra@Sun.COM smb->rx_fifo_oflows + smb->rx_rrs_errs +
81910393SSaurabh.Mishra@Sun.COM smb->rx_alignerrs;
82010393SSaurabh.Mishra@Sun.COM }
82110393SSaurabh.Mishra@Sun.COM
82210393SSaurabh.Mishra@Sun.COM void
atge_l1e_stop_mac(atge_t * atgep)82310393SSaurabh.Mishra@Sun.COM atge_l1e_stop_mac(atge_t *atgep)
82410393SSaurabh.Mishra@Sun.COM {
82510393SSaurabh.Mishra@Sun.COM uint32_t reg;
82610393SSaurabh.Mishra@Sun.COM
82710393SSaurabh.Mishra@Sun.COM reg = INL(atgep, ATGE_MAC_CFG);
82810393SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() reg : %x", atgep->atge_name, __func__, reg));
82910393SSaurabh.Mishra@Sun.COM
83010393SSaurabh.Mishra@Sun.COM if ((reg & (ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB)) != 0) {
83110393SSaurabh.Mishra@Sun.COM reg &= ~ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB;
83210393SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_MAC_CFG, reg);
83310393SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() mac stopped", atgep->atge_name, __func__));
83410393SSaurabh.Mishra@Sun.COM }
83510393SSaurabh.Mishra@Sun.COM }
836*11353SSaurabh.Mishra@Sun.COM
837*11353SSaurabh.Mishra@Sun.COM /*
838*11353SSaurabh.Mishra@Sun.COM * The interrupt handler for L1E/L2E
839*11353SSaurabh.Mishra@Sun.COM */
840*11353SSaurabh.Mishra@Sun.COM /*ARGSUSED*/
841*11353SSaurabh.Mishra@Sun.COM uint_t
atge_l1e_interrupt(caddr_t arg1,caddr_t arg2)842*11353SSaurabh.Mishra@Sun.COM atge_l1e_interrupt(caddr_t arg1, caddr_t arg2)
843*11353SSaurabh.Mishra@Sun.COM {
844*11353SSaurabh.Mishra@Sun.COM atge_t *atgep = (void *)arg1;
845*11353SSaurabh.Mishra@Sun.COM mblk_t *rx_head = NULL;
846*11353SSaurabh.Mishra@Sun.COM uint32_t status;
847*11353SSaurabh.Mishra@Sun.COM int resched = 0;
848*11353SSaurabh.Mishra@Sun.COM
849*11353SSaurabh.Mishra@Sun.COM ASSERT(atgep != NULL);
850*11353SSaurabh.Mishra@Sun.COM
851*11353SSaurabh.Mishra@Sun.COM mutex_enter(&atgep->atge_intr_lock);
852*11353SSaurabh.Mishra@Sun.COM
853*11353SSaurabh.Mishra@Sun.COM if (atgep->atge_chip_state & ATGE_CHIP_SUSPENDED) {
854*11353SSaurabh.Mishra@Sun.COM mutex_exit(&atgep->atge_intr_lock);
855*11353SSaurabh.Mishra@Sun.COM return (DDI_INTR_UNCLAIMED);
856*11353SSaurabh.Mishra@Sun.COM }
857*11353SSaurabh.Mishra@Sun.COM
858*11353SSaurabh.Mishra@Sun.COM status = INL(atgep, ATGE_INTR_STATUS);
859*11353SSaurabh.Mishra@Sun.COM if (status == 0 || (status & atgep->atge_intrs) == 0) {
860*11353SSaurabh.Mishra@Sun.COM mutex_exit(&atgep->atge_intr_lock);
861*11353SSaurabh.Mishra@Sun.COM
862*11353SSaurabh.Mishra@Sun.COM if (atgep->atge_flags & ATGE_FIXED_TYPE)
863*11353SSaurabh.Mishra@Sun.COM return (DDI_INTR_UNCLAIMED);
864*11353SSaurabh.Mishra@Sun.COM
865*11353SSaurabh.Mishra@Sun.COM return (DDI_INTR_CLAIMED);
866*11353SSaurabh.Mishra@Sun.COM }
867*11353SSaurabh.Mishra@Sun.COM
868*11353SSaurabh.Mishra@Sun.COM ATGE_DB(("%s: %s() entry status : %x",
869*11353SSaurabh.Mishra@Sun.COM atgep->atge_name, __func__, status));
870*11353SSaurabh.Mishra@Sun.COM
871*11353SSaurabh.Mishra@Sun.COM
872*11353SSaurabh.Mishra@Sun.COM /*
873*11353SSaurabh.Mishra@Sun.COM * Disable interrupts.
874*11353SSaurabh.Mishra@Sun.COM */
875*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_INTR_STATUS, status | INTR_DIS_INT);
876*11353SSaurabh.Mishra@Sun.COM FLUSH(atgep, ATGE_INTR_STATUS);
877*11353SSaurabh.Mishra@Sun.COM
878*11353SSaurabh.Mishra@Sun.COM /*
879*11353SSaurabh.Mishra@Sun.COM * Check if chip is running, only then do the work.
880*11353SSaurabh.Mishra@Sun.COM */
881*11353SSaurabh.Mishra@Sun.COM if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) {
882*11353SSaurabh.Mishra@Sun.COM if (status & INTR_SMB) {
883*11353SSaurabh.Mishra@Sun.COM atge_l1e_gather_stats(atgep);
884*11353SSaurabh.Mishra@Sun.COM }
885*11353SSaurabh.Mishra@Sun.COM
886*11353SSaurabh.Mishra@Sun.COM /*
887*11353SSaurabh.Mishra@Sun.COM * Check for errors.
888*11353SSaurabh.Mishra@Sun.COM */
889*11353SSaurabh.Mishra@Sun.COM if (status & L1E_INTR_ERRORS) {
890*11353SSaurabh.Mishra@Sun.COM atge_error(atgep->atge_dip,
891*11353SSaurabh.Mishra@Sun.COM "L1E chip found an error intr status : %x",
892*11353SSaurabh.Mishra@Sun.COM status);
893*11353SSaurabh.Mishra@Sun.COM
894*11353SSaurabh.Mishra@Sun.COM if (status &
895*11353SSaurabh.Mishra@Sun.COM (INTR_DMA_RD_TO_RST | INTR_DMA_WR_TO_RST)) {
896*11353SSaurabh.Mishra@Sun.COM atge_error(atgep->atge_dip, "DMA transfer err");
897*11353SSaurabh.Mishra@Sun.COM
898*11353SSaurabh.Mishra@Sun.COM atge_device_stop(atgep);
899*11353SSaurabh.Mishra@Sun.COM goto done;
900*11353SSaurabh.Mishra@Sun.COM }
901*11353SSaurabh.Mishra@Sun.COM
902*11353SSaurabh.Mishra@Sun.COM if (status & INTR_TX_FIFO_UNDERRUN) {
903*11353SSaurabh.Mishra@Sun.COM atge_error(atgep->atge_dip, "TX FIFO underrun");
904*11353SSaurabh.Mishra@Sun.COM }
905*11353SSaurabh.Mishra@Sun.COM }
906*11353SSaurabh.Mishra@Sun.COM
907*11353SSaurabh.Mishra@Sun.COM rx_head = atge_l1e_receive(atgep);
908*11353SSaurabh.Mishra@Sun.COM
909*11353SSaurabh.Mishra@Sun.COM if (status & INTR_TX_PKT) {
910*11353SSaurabh.Mishra@Sun.COM int cons;
911*11353SSaurabh.Mishra@Sun.COM
912*11353SSaurabh.Mishra@Sun.COM mutex_enter(&atgep->atge_tx_lock);
913*11353SSaurabh.Mishra@Sun.COM cons = INW(atgep, L1E_TPD_CONS_IDX);
914*11353SSaurabh.Mishra@Sun.COM atge_tx_reclaim(atgep, cons);
915*11353SSaurabh.Mishra@Sun.COM if (atgep->atge_tx_resched) {
916*11353SSaurabh.Mishra@Sun.COM atgep->atge_tx_resched = 0;
917*11353SSaurabh.Mishra@Sun.COM resched = 1;
918*11353SSaurabh.Mishra@Sun.COM }
919*11353SSaurabh.Mishra@Sun.COM
920*11353SSaurabh.Mishra@Sun.COM mutex_exit(&atgep->atge_tx_lock);
921*11353SSaurabh.Mishra@Sun.COM }
922*11353SSaurabh.Mishra@Sun.COM }
923*11353SSaurabh.Mishra@Sun.COM
924*11353SSaurabh.Mishra@Sun.COM /*
925*11353SSaurabh.Mishra@Sun.COM * Enable interrupts.
926*11353SSaurabh.Mishra@Sun.COM */
927*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_INTR_STATUS, 0);
928*11353SSaurabh.Mishra@Sun.COM
929*11353SSaurabh.Mishra@Sun.COM done:
930*11353SSaurabh.Mishra@Sun.COM
931*11353SSaurabh.Mishra@Sun.COM mutex_exit(&atgep->atge_intr_lock);
932*11353SSaurabh.Mishra@Sun.COM
933*11353SSaurabh.Mishra@Sun.COM if (status & INTR_GPHY) {
934*11353SSaurabh.Mishra@Sun.COM /*
935*11353SSaurabh.Mishra@Sun.COM * Ack interrupts from PHY
936*11353SSaurabh.Mishra@Sun.COM */
937*11353SSaurabh.Mishra@Sun.COM (void) atge_mii_read(atgep,
938*11353SSaurabh.Mishra@Sun.COM atgep->atge_phyaddr, ATGE_ISR_ACK_GPHY);
939*11353SSaurabh.Mishra@Sun.COM
940*11353SSaurabh.Mishra@Sun.COM mii_check(atgep->atge_mii);
941*11353SSaurabh.Mishra@Sun.COM }
942*11353SSaurabh.Mishra@Sun.COM
943*11353SSaurabh.Mishra@Sun.COM /*
944*11353SSaurabh.Mishra@Sun.COM * Pass the list of packets received from chip to MAC layer.
945*11353SSaurabh.Mishra@Sun.COM */
946*11353SSaurabh.Mishra@Sun.COM if (rx_head) {
947*11353SSaurabh.Mishra@Sun.COM mac_rx(atgep->atge_mh, 0, rx_head);
948*11353SSaurabh.Mishra@Sun.COM }
949*11353SSaurabh.Mishra@Sun.COM
950*11353SSaurabh.Mishra@Sun.COM /*
951*11353SSaurabh.Mishra@Sun.COM * Let MAC start sending pkts if the downstream was asked to pause.
952*11353SSaurabh.Mishra@Sun.COM */
953*11353SSaurabh.Mishra@Sun.COM if (resched)
954*11353SSaurabh.Mishra@Sun.COM mac_tx_update(atgep->atge_mh);
955*11353SSaurabh.Mishra@Sun.COM
956*11353SSaurabh.Mishra@Sun.COM return (DDI_INTR_CLAIMED);
957*11353SSaurabh.Mishra@Sun.COM }
958