1*5e8715b9SGary Mills /* 2*5e8715b9SGary Mills * CDDL HEADER START 3*5e8715b9SGary Mills * 4*5e8715b9SGary Mills * The contents of this file are subject to the terms of the 5*5e8715b9SGary Mills * Common Development and Distribution License (the "License"). 6*5e8715b9SGary Mills * You may not use this file except in compliance with the License. 7*5e8715b9SGary Mills * 8*5e8715b9SGary Mills * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5e8715b9SGary Mills * or http://www.opensolaris.org/os/licensing. 10*5e8715b9SGary Mills * See the License for the specific language governing permissions 11*5e8715b9SGary Mills * and limitations under the License. 12*5e8715b9SGary Mills * 13*5e8715b9SGary Mills * When distributing Covered Code, include this CDDL HEADER in each 14*5e8715b9SGary Mills * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5e8715b9SGary Mills * If applicable, add the following below this CDDL HEADER, with the 16*5e8715b9SGary Mills * fields enclosed by brackets "[]" replaced with your own identifying 17*5e8715b9SGary Mills * information: Portions Copyright [yyyy] [name of copyright owner] 18*5e8715b9SGary Mills * 19*5e8715b9SGary Mills * CDDL HEADER END 20*5e8715b9SGary Mills */ 21*5e8715b9SGary Mills 22*5e8715b9SGary Mills /* 23*5e8715b9SGary Mills * Copyright (c) 2012 Gary Mills 24*5e8715b9SGary Mills * 25*5e8715b9SGary Mills * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 26*5e8715b9SGary Mills * Use is subject to license terms. 27*5e8715b9SGary Mills */ 28*5e8715b9SGary Mills /* 29*5e8715b9SGary Mills * Copyright (c) 2009, Pyun YongHyeon <yongari@FreeBSD.org> 30*5e8715b9SGary Mills * All rights reserved. 31*5e8715b9SGary Mills * 32*5e8715b9SGary Mills * Redistribution and use in source and binary forms, with or without 33*5e8715b9SGary Mills * modification, are permitted provided that the following conditions 34*5e8715b9SGary Mills * are met: 35*5e8715b9SGary Mills * 1. Redistributions of source code must retain the above copyright 36*5e8715b9SGary Mills * notice unmodified, this list of conditions, and the following 37*5e8715b9SGary Mills * disclaimer. 38*5e8715b9SGary Mills * 2. Redistributions in binary form must reproduce the above copyright 39*5e8715b9SGary Mills * notice, this list of conditions and the following disclaimer in the 40*5e8715b9SGary Mills * documentation and/or other materials provided with the distribution. 41*5e8715b9SGary Mills * 42*5e8715b9SGary Mills * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 43*5e8715b9SGary Mills * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 44*5e8715b9SGary Mills * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 45*5e8715b9SGary Mills * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 46*5e8715b9SGary Mills * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 47*5e8715b9SGary Mills * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 48*5e8715b9SGary Mills * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 49*5e8715b9SGary Mills * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 50*5e8715b9SGary Mills * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 51*5e8715b9SGary Mills * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 52*5e8715b9SGary Mills * SUCH DAMAGE. 53*5e8715b9SGary Mills */ 54*5e8715b9SGary Mills 55*5e8715b9SGary Mills #include <sys/types.h> 56*5e8715b9SGary Mills #include <sys/stream.h> 57*5e8715b9SGary Mills #include <sys/strsun.h> 58*5e8715b9SGary Mills #include <sys/stat.h> 59*5e8715b9SGary Mills #include <sys/modctl.h> 60*5e8715b9SGary Mills #include <sys/ethernet.h> 61*5e8715b9SGary Mills #include <sys/debug.h> 62*5e8715b9SGary Mills #include <sys/conf.h> 63*5e8715b9SGary Mills #include <sys/mii.h> 64*5e8715b9SGary Mills #include <sys/miiregs.h> 65*5e8715b9SGary Mills #include <sys/sysmacros.h> 66*5e8715b9SGary Mills #include <sys/dditypes.h> 67*5e8715b9SGary Mills #include <sys/ddi.h> 68*5e8715b9SGary Mills #include <sys/sunddi.h> 69*5e8715b9SGary Mills #include <sys/byteorder.h> 70*5e8715b9SGary Mills #include <sys/note.h> 71*5e8715b9SGary Mills #include <sys/vlan.h> 72*5e8715b9SGary Mills #include <sys/stream.h> 73*5e8715b9SGary Mills 74*5e8715b9SGary Mills #include "atge.h" 75*5e8715b9SGary Mills #include "atge_l1c_reg.h" 76*5e8715b9SGary Mills #include "atge_cmn_reg.h" 77*5e8715b9SGary Mills 78*5e8715b9SGary Mills static ddi_dma_attr_t atge_l1c_dma_attr_tx_desc = { 79*5e8715b9SGary Mills DMA_ATTR_V0, /* dma_attr_version */ 80*5e8715b9SGary Mills 0, /* dma_attr_addr_lo */ 81*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_addr_hi */ 82*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_count_max */ 83*5e8715b9SGary Mills L1C_TX_RING_ALIGN, /* dma_attr_align */ 84*5e8715b9SGary Mills 0x0000fffc, /* dma_attr_burstsizes */ 85*5e8715b9SGary Mills 1, /* dma_attr_minxfer */ 86*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_maxxfer */ 87*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_seg */ 88*5e8715b9SGary Mills 1, /* dma_attr_sgllen */ 89*5e8715b9SGary Mills 1, /* dma_attr_granular */ 90*5e8715b9SGary Mills 0 /* dma_attr_flags */ 91*5e8715b9SGary Mills }; 92*5e8715b9SGary Mills 93*5e8715b9SGary Mills static ddi_dma_attr_t atge_l1c_dma_attr_rx_desc = { 94*5e8715b9SGary Mills DMA_ATTR_V0, /* dma_attr_version */ 95*5e8715b9SGary Mills 0, /* dma_attr_addr_lo */ 96*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_addr_hi */ 97*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_count_max */ 98*5e8715b9SGary Mills L1C_RX_RING_ALIGN, /* dma_attr_align */ 99*5e8715b9SGary Mills 0x0000fffc, /* dma_attr_burstsizes */ 100*5e8715b9SGary Mills 1, /* dma_attr_minxfer */ 101*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_maxxfer */ 102*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_seg */ 103*5e8715b9SGary Mills 1, /* dma_attr_sgllen */ 104*5e8715b9SGary Mills 1, /* dma_attr_granular */ 105*5e8715b9SGary Mills 0 /* dma_attr_flags */ 106*5e8715b9SGary Mills }; 107*5e8715b9SGary Mills 108*5e8715b9SGary Mills static ddi_dma_attr_t atge_l1c_dma_attr_cmb = { 109*5e8715b9SGary Mills DMA_ATTR_V0, /* dma_attr_version */ 110*5e8715b9SGary Mills 0, /* dma_attr_addr_lo */ 111*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_addr_hi */ 112*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_count_max */ 113*5e8715b9SGary Mills L1C_CMB_ALIGN, /* dma_attr_align */ 114*5e8715b9SGary Mills 0x0000fffc, /* dma_attr_burstsizes */ 115*5e8715b9SGary Mills 1, /* dma_attr_minxfer */ 116*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_maxxfer */ 117*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_seg */ 118*5e8715b9SGary Mills 1, /* dma_attr_sgllen */ 119*5e8715b9SGary Mills 1, /* dma_attr_granular */ 120*5e8715b9SGary Mills 0 /* dma_attr_flags */ 121*5e8715b9SGary Mills }; 122*5e8715b9SGary Mills 123*5e8715b9SGary Mills static ddi_dma_attr_t atge_l1c_dma_attr_smb = { 124*5e8715b9SGary Mills DMA_ATTR_V0, /* dma_attr_version */ 125*5e8715b9SGary Mills 0, /* dma_attr_addr_lo */ 126*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_addr_hi */ 127*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_count_max */ 128*5e8715b9SGary Mills L1C_SMB_ALIGN, /* dma_attr_align */ 129*5e8715b9SGary Mills 0x0000fffc, /* dma_attr_burstsizes */ 130*5e8715b9SGary Mills 1, /* dma_attr_minxfer */ 131*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_maxxfer */ 132*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_seg */ 133*5e8715b9SGary Mills 1, /* dma_attr_sgllen */ 134*5e8715b9SGary Mills 1, /* dma_attr_granular */ 135*5e8715b9SGary Mills 0 /* dma_attr_flags */ 136*5e8715b9SGary Mills }; 137*5e8715b9SGary Mills 138*5e8715b9SGary Mills static ddi_dma_attr_t atge_l1c_dma_attr_rr = { 139*5e8715b9SGary Mills DMA_ATTR_V0, /* dma_attr_version */ 140*5e8715b9SGary Mills 0, /* dma_attr_addr_lo */ 141*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_addr_hi */ 142*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_count_max */ 143*5e8715b9SGary Mills L1C_RR_RING_ALIGN, /* dma_attr_align */ 144*5e8715b9SGary Mills 0x0000fffc, /* dma_attr_burstsizes */ 145*5e8715b9SGary Mills 1, /* dma_attr_minxfer */ 146*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_maxxfer */ 147*5e8715b9SGary Mills 0x0000ffffffffull, /* dma_attr_seg */ 148*5e8715b9SGary Mills 1, /* dma_attr_sgllen */ 149*5e8715b9SGary Mills 1, /* dma_attr_granular */ 150*5e8715b9SGary Mills 0 /* dma_attr_flags */ 151*5e8715b9SGary Mills }; 152*5e8715b9SGary Mills 153*5e8715b9SGary Mills int 154*5e8715b9SGary Mills atge_l1c_alloc_dma(atge_t *atgep) 155*5e8715b9SGary Mills { 156*5e8715b9SGary Mills atge_l1c_data_t *l1c; 157*5e8715b9SGary Mills atge_dma_t *dma; 158*5e8715b9SGary Mills int err; 159*5e8715b9SGary Mills 160*5e8715b9SGary Mills l1c = kmem_zalloc(sizeof (atge_l1c_data_t), KM_SLEEP); 161*5e8715b9SGary Mills atgep->atge_private_data = l1c; 162*5e8715b9SGary Mills 163*5e8715b9SGary Mills /* 164*5e8715b9SGary Mills * Allocate TX ring descriptor. 165*5e8715b9SGary Mills */ 166*5e8715b9SGary Mills atgep->atge_tx_buf_len = atgep->atge_mtu + 167*5e8715b9SGary Mills sizeof (struct ether_header) + VLAN_TAGSZ + ETHERFCSL; 168*5e8715b9SGary Mills atgep->atge_tx_ring = kmem_alloc(sizeof (atge_ring_t), KM_SLEEP); 169*5e8715b9SGary Mills atgep->atge_tx_ring->r_atge = atgep; 170*5e8715b9SGary Mills atgep->atge_tx_ring->r_desc_ring = NULL; 171*5e8715b9SGary Mills dma = atge_alloc_a_dma_blk(atgep, &atge_l1c_dma_attr_tx_desc, 172*5e8715b9SGary Mills ATGE_TX_RING_SZ, DDI_DMA_RDWR); 173*5e8715b9SGary Mills if (dma == NULL) { 174*5e8715b9SGary Mills atge_error(atgep->atge_dip, "DMA allocation failed for TX" 175*5e8715b9SGary Mills " desc ring"); 176*5e8715b9SGary Mills return (DDI_FAILURE); 177*5e8715b9SGary Mills } 178*5e8715b9SGary Mills atgep->atge_tx_ring->r_desc_ring = dma; 179*5e8715b9SGary Mills 180*5e8715b9SGary Mills /* 181*5e8715b9SGary Mills * Allocate DMA buffers for TX ring. 182*5e8715b9SGary Mills */ 183*5e8715b9SGary Mills err = atge_alloc_buffers(atgep->atge_tx_ring, ATGE_TX_RING_CNT, 184*5e8715b9SGary Mills atgep->atge_tx_buf_len, DDI_DMA_WRITE); 185*5e8715b9SGary Mills if (err != DDI_SUCCESS) { 186*5e8715b9SGary Mills atge_error(atgep->atge_dip, "DMA allocation failed for" 187*5e8715b9SGary Mills " TX Ring"); 188*5e8715b9SGary Mills return (err); 189*5e8715b9SGary Mills } 190*5e8715b9SGary Mills 191*5e8715b9SGary Mills /* 192*5e8715b9SGary Mills * Allocate RX ring. 193*5e8715b9SGary Mills */ 194*5e8715b9SGary Mills atgep->atge_rx_buf_len = atgep->atge_mtu + 195*5e8715b9SGary Mills sizeof (struct ether_header) + VLAN_TAGSZ + ETHERFCSL; 196*5e8715b9SGary Mills l1c->atge_rx_ring = kmem_alloc(sizeof (atge_ring_t), KM_SLEEP); 197*5e8715b9SGary Mills l1c->atge_rx_ring->r_atge = atgep; 198*5e8715b9SGary Mills l1c->atge_rx_ring->r_desc_ring = NULL; 199*5e8715b9SGary Mills dma = atge_alloc_a_dma_blk(atgep, &atge_l1c_dma_attr_rx_desc, 200*5e8715b9SGary Mills L1C_RX_RING_SZ, DDI_DMA_RDWR); 201*5e8715b9SGary Mills if (dma == NULL) { 202*5e8715b9SGary Mills atge_error(atgep->atge_dip, "DMA allocation failed" 203*5e8715b9SGary Mills " for RX Ring"); 204*5e8715b9SGary Mills return (DDI_FAILURE); 205*5e8715b9SGary Mills } 206*5e8715b9SGary Mills l1c->atge_rx_ring->r_desc_ring = dma; 207*5e8715b9SGary Mills 208*5e8715b9SGary Mills /* 209*5e8715b9SGary Mills * Allocate DMA buffers for RX ring. 210*5e8715b9SGary Mills */ 211*5e8715b9SGary Mills err = atge_alloc_buffers(l1c->atge_rx_ring, L1C_RX_RING_CNT, 212*5e8715b9SGary Mills atgep->atge_rx_buf_len, DDI_DMA_READ); 213*5e8715b9SGary Mills if (err != DDI_SUCCESS) { 214*5e8715b9SGary Mills atge_error(atgep->atge_dip, "DMA allocation failed for" 215*5e8715b9SGary Mills " RX buffers"); 216*5e8715b9SGary Mills return (err); 217*5e8715b9SGary Mills } 218*5e8715b9SGary Mills 219*5e8715b9SGary Mills /* 220*5e8715b9SGary Mills * Allocate CMB used for fetching interrupt status data. 221*5e8715b9SGary Mills */ 222*5e8715b9SGary Mills ATGE_DB(("%s: %s() L1C_CMB_BLOCK_SZ : 0x%x", atgep->atge_name, 223*5e8715b9SGary Mills __func__, L1C_CMB_BLOCK_SZ)); 224*5e8715b9SGary Mills 225*5e8715b9SGary Mills dma = atge_alloc_a_dma_blk(atgep, &atge_l1c_dma_attr_cmb, 226*5e8715b9SGary Mills L1C_CMB_BLOCK_SZ, DDI_DMA_RDWR); 227*5e8715b9SGary Mills l1c->atge_l1c_cmb = dma; 228*5e8715b9SGary Mills if (dma == NULL) { 229*5e8715b9SGary Mills atge_error(atgep->atge_dip, "DMA allocation failed for CMB"); 230*5e8715b9SGary Mills return (DDI_FAILURE); 231*5e8715b9SGary Mills } 232*5e8715b9SGary Mills 233*5e8715b9SGary Mills /* 234*5e8715b9SGary Mills * RR ring (Return Ring for RX and TX). 235*5e8715b9SGary Mills */ 236*5e8715b9SGary Mills ATGE_DB(("%s: %s() L1C_RR_RING_SZ : 0x%x", atgep->atge_name, 237*5e8715b9SGary Mills __func__, L1C_RR_RING_SZ)); 238*5e8715b9SGary Mills 239*5e8715b9SGary Mills dma = atge_alloc_a_dma_blk(atgep, &atge_l1c_dma_attr_rr, 240*5e8715b9SGary Mills L1C_RR_RING_SZ, DDI_DMA_RDWR); 241*5e8715b9SGary Mills l1c->atge_l1c_rr = dma; 242*5e8715b9SGary Mills if (dma == NULL) { 243*5e8715b9SGary Mills atge_error(atgep->atge_dip, "DMA allocation failed" 244*5e8715b9SGary Mills " for RX RR ring"); 245*5e8715b9SGary Mills return (DDI_FAILURE); 246*5e8715b9SGary Mills } 247*5e8715b9SGary Mills 248*5e8715b9SGary Mills /* 249*5e8715b9SGary Mills * SMB for statistics. 250*5e8715b9SGary Mills */ 251*5e8715b9SGary Mills ATGE_DB(("%s: %s() L1C_SMB_BLOCK_SZ : 0x%x", atgep->atge_name, 252*5e8715b9SGary Mills __func__, L1C_SMB_BLOCK_SZ)); 253*5e8715b9SGary Mills 254*5e8715b9SGary Mills dma = atge_alloc_a_dma_blk(atgep, &atge_l1c_dma_attr_smb, 255*5e8715b9SGary Mills L1C_SMB_BLOCK_SZ, DDI_DMA_RDWR); 256*5e8715b9SGary Mills l1c->atge_l1c_smb = dma; 257*5e8715b9SGary Mills if (dma == NULL) { 258*5e8715b9SGary Mills atge_error(atgep->atge_dip, "DMA allocation failed for SMB"); 259*5e8715b9SGary Mills return (DDI_FAILURE); 260*5e8715b9SGary Mills } 261*5e8715b9SGary Mills 262*5e8715b9SGary Mills atgep->atge_hw_stats = kmem_zalloc(sizeof (atge_l1c_smb_t), KM_SLEEP); 263*5e8715b9SGary Mills 264*5e8715b9SGary Mills return (DDI_SUCCESS); 265*5e8715b9SGary Mills } 266*5e8715b9SGary Mills 267*5e8715b9SGary Mills void 268*5e8715b9SGary Mills atge_l1c_free_dma(atge_t *atgep) 269*5e8715b9SGary Mills { 270*5e8715b9SGary Mills atge_l1c_data_t *l1c; 271*5e8715b9SGary Mills 272*5e8715b9SGary Mills l1c = atgep->atge_private_data; 273*5e8715b9SGary Mills 274*5e8715b9SGary Mills /* 275*5e8715b9SGary Mills * Free TX ring. 276*5e8715b9SGary Mills */ 277*5e8715b9SGary Mills if (atgep->atge_tx_ring != NULL) { 278*5e8715b9SGary Mills atge_free_buffers(atgep->atge_tx_ring, ATGE_TX_RING_CNT); 279*5e8715b9SGary Mills 280*5e8715b9SGary Mills if (atgep->atge_tx_ring->r_desc_ring != NULL) { 281*5e8715b9SGary Mills atge_free_a_dma_blk(atgep->atge_tx_ring->r_desc_ring); 282*5e8715b9SGary Mills } 283*5e8715b9SGary Mills 284*5e8715b9SGary Mills kmem_free(atgep->atge_tx_ring, sizeof (atge_ring_t)); 285*5e8715b9SGary Mills atgep->atge_tx_ring = NULL; 286*5e8715b9SGary Mills } 287*5e8715b9SGary Mills 288*5e8715b9SGary Mills if (l1c && l1c->atge_l1c_cmb != NULL) { 289*5e8715b9SGary Mills atge_free_a_dma_blk(l1c->atge_l1c_cmb); 290*5e8715b9SGary Mills l1c->atge_l1c_cmb = NULL; 291*5e8715b9SGary Mills } 292*5e8715b9SGary Mills 293*5e8715b9SGary Mills if (l1c && l1c->atge_l1c_rr != NULL) { 294*5e8715b9SGary Mills atge_free_a_dma_blk(l1c->atge_l1c_rr); 295*5e8715b9SGary Mills l1c->atge_l1c_rr = NULL; 296*5e8715b9SGary Mills } 297*5e8715b9SGary Mills 298*5e8715b9SGary Mills if (l1c && l1c->atge_l1c_smb != NULL) { 299*5e8715b9SGary Mills atge_free_a_dma_blk(l1c->atge_l1c_smb); 300*5e8715b9SGary Mills l1c->atge_l1c_smb = NULL; 301*5e8715b9SGary Mills } 302*5e8715b9SGary Mills 303*5e8715b9SGary Mills /* 304*5e8715b9SGary Mills * Free RX ring. 305*5e8715b9SGary Mills */ 306*5e8715b9SGary Mills if (l1c && l1c->atge_rx_ring != NULL) { 307*5e8715b9SGary Mills atge_free_buffers(l1c->atge_rx_ring, L1C_RX_RING_CNT); 308*5e8715b9SGary Mills 309*5e8715b9SGary Mills if (l1c->atge_rx_ring->r_desc_ring != NULL) { 310*5e8715b9SGary Mills atge_free_a_dma_blk(l1c->atge_rx_ring->r_desc_ring); 311*5e8715b9SGary Mills } 312*5e8715b9SGary Mills 313*5e8715b9SGary Mills kmem_free(l1c->atge_rx_ring, sizeof (atge_ring_t)); 314*5e8715b9SGary Mills l1c->atge_rx_ring = NULL; 315*5e8715b9SGary Mills } 316*5e8715b9SGary Mills 317*5e8715b9SGary Mills /* 318*5e8715b9SGary Mills * Free the memory allocated for gathering hw stats. 319*5e8715b9SGary Mills */ 320*5e8715b9SGary Mills if (atgep->atge_hw_stats != NULL) { 321*5e8715b9SGary Mills kmem_free(atgep->atge_hw_stats, sizeof (atge_l1c_smb_t)); 322*5e8715b9SGary Mills atgep->atge_hw_stats = NULL; 323*5e8715b9SGary Mills } 324*5e8715b9SGary Mills 325*5e8715b9SGary Mills /* 326*5e8715b9SGary Mills * Free the private area. 327*5e8715b9SGary Mills */ 328*5e8715b9SGary Mills if (l1c != NULL) { 329*5e8715b9SGary Mills kmem_free(l1c, sizeof (atge_l1c_data_t)); 330*5e8715b9SGary Mills atgep->atge_private_data = NULL; 331*5e8715b9SGary Mills } 332*5e8715b9SGary Mills } 333*5e8715b9SGary Mills 334*5e8715b9SGary Mills void 335*5e8715b9SGary Mills atge_l1c_init_rx_ring(atge_t *atgep) 336*5e8715b9SGary Mills { 337*5e8715b9SGary Mills atge_l1c_data_t *l1c; 338*5e8715b9SGary Mills atge_dma_t *dma; 339*5e8715b9SGary Mills l1c_rx_desc_t *rx; 340*5e8715b9SGary Mills int i; 341*5e8715b9SGary Mills 342*5e8715b9SGary Mills l1c = atgep->atge_private_data; 343*5e8715b9SGary Mills l1c->atge_rx_ring->r_consumer = L1C_RX_RING_CNT - 1; 344*5e8715b9SGary Mills dma = l1c->atge_rx_ring->r_desc_ring; 345*5e8715b9SGary Mills bzero(dma->addr, L1C_RX_RING_SZ); 346*5e8715b9SGary Mills 347*5e8715b9SGary Mills for (i = 0; i < L1C_RX_RING_CNT; i++) { 348*5e8715b9SGary Mills rx = (l1c_rx_desc_t *)(dma->addr + 349*5e8715b9SGary Mills (i * sizeof (l1c_rx_desc_t))); 350*5e8715b9SGary Mills 351*5e8715b9SGary Mills ATGE_PUT64(dma, &rx->addr, 352*5e8715b9SGary Mills l1c->atge_rx_ring->r_buf_tbl[i]->cookie.dmac_laddress); 353*5e8715b9SGary Mills /* No length field. */ 354*5e8715b9SGary Mills } 355*5e8715b9SGary Mills 356*5e8715b9SGary Mills DMA_SYNC(dma, 0, 0, DDI_DMA_SYNC_FORDEV); 357*5e8715b9SGary Mills /* Let controller know availability of new Rx buffers. */ 358*5e8715b9SGary Mills OUTL(atgep, ATGE_MBOX_RD0_PROD_IDX, l1c->atge_rx_ring->r_consumer); 359*5e8715b9SGary Mills } 360*5e8715b9SGary Mills 361*5e8715b9SGary Mills void 362*5e8715b9SGary Mills atge_l1c_init_tx_ring(atge_t *atgep) 363*5e8715b9SGary Mills { 364*5e8715b9SGary Mills atgep->atge_tx_ring->r_producer = 0; 365*5e8715b9SGary Mills atgep->atge_tx_ring->r_consumer = 0; 366*5e8715b9SGary Mills atgep->atge_tx_ring->r_avail_desc = ATGE_TX_RING_CNT; 367*5e8715b9SGary Mills 368*5e8715b9SGary Mills bzero(atgep->atge_tx_ring->r_desc_ring->addr, ATGE_TX_RING_SZ); 369*5e8715b9SGary Mills DMA_SYNC(atgep->atge_tx_ring->r_desc_ring, 0, 0, DDI_DMA_SYNC_FORDEV); 370*5e8715b9SGary Mills } 371*5e8715b9SGary Mills 372*5e8715b9SGary Mills void 373*5e8715b9SGary Mills atge_l1c_init_rr_ring(atge_t *atgep) 374*5e8715b9SGary Mills { 375*5e8715b9SGary Mills atge_l1c_data_t *l1c; 376*5e8715b9SGary Mills atge_dma_t *dma; 377*5e8715b9SGary Mills 378*5e8715b9SGary Mills l1c = atgep->atge_private_data; 379*5e8715b9SGary Mills l1c->atge_l1c_rr_consumers = 0; 380*5e8715b9SGary Mills 381*5e8715b9SGary Mills dma = l1c->atge_l1c_rr; 382*5e8715b9SGary Mills bzero(dma->addr, L1C_RR_RING_SZ); 383*5e8715b9SGary Mills DMA_SYNC(dma, 0, 0, DDI_DMA_SYNC_FORDEV); 384*5e8715b9SGary Mills } 385*5e8715b9SGary Mills 386*5e8715b9SGary Mills void 387*5e8715b9SGary Mills atge_l1c_init_smb(atge_t *atgep) 388*5e8715b9SGary Mills { 389*5e8715b9SGary Mills atge_l1c_data_t *l1c; 390*5e8715b9SGary Mills atge_dma_t *dma; 391*5e8715b9SGary Mills 392*5e8715b9SGary Mills l1c = atgep->atge_private_data; 393*5e8715b9SGary Mills dma = l1c->atge_l1c_smb; 394*5e8715b9SGary Mills bzero(dma->addr, L1C_SMB_BLOCK_SZ); 395*5e8715b9SGary Mills DMA_SYNC(dma, 0, 0, DDI_DMA_SYNC_FORDEV); 396*5e8715b9SGary Mills } 397*5e8715b9SGary Mills 398*5e8715b9SGary Mills void 399*5e8715b9SGary Mills atge_l1c_init_cmb(atge_t *atgep) 400*5e8715b9SGary Mills { 401*5e8715b9SGary Mills atge_l1c_data_t *l1c; 402*5e8715b9SGary Mills atge_dma_t *dma; 403*5e8715b9SGary Mills 404*5e8715b9SGary Mills l1c = atgep->atge_private_data; 405*5e8715b9SGary Mills dma = l1c->atge_l1c_cmb; 406*5e8715b9SGary Mills bzero(dma->addr, L1C_CMB_BLOCK_SZ); 407*5e8715b9SGary Mills DMA_SYNC(dma, 0, 0, DDI_DMA_SYNC_FORDEV); 408*5e8715b9SGary Mills } 409*5e8715b9SGary Mills 410*5e8715b9SGary Mills void 411*5e8715b9SGary Mills atge_l1c_program_dma(atge_t *atgep) 412*5e8715b9SGary Mills { 413*5e8715b9SGary Mills atge_l1c_data_t *l1c; 414*5e8715b9SGary Mills atge_ring_t *r; 415*5e8715b9SGary Mills uint32_t reg; 416*5e8715b9SGary Mills 417*5e8715b9SGary Mills l1c = atgep->atge_private_data; 418*5e8715b9SGary Mills 419*5e8715b9SGary Mills /* 420*5e8715b9SGary Mills * Clear WOL status and disable all WOL feature as WOL 421*5e8715b9SGary Mills * would interfere Rx operation under normal environments. 422*5e8715b9SGary Mills */ 423*5e8715b9SGary Mills (void) INL(atgep, ATGE_WOL_CFG); 424*5e8715b9SGary Mills OUTL(atgep, ATGE_WOL_CFG, 0); 425*5e8715b9SGary Mills 426*5e8715b9SGary Mills /* TX */ 427*5e8715b9SGary Mills r = atgep->atge_tx_ring; 428*5e8715b9SGary Mills OUTL(atgep, L1C_TX_BASE_ADDR_HI, 429*5e8715b9SGary Mills ATGE_ADDR_HI(r->r_desc_ring->cookie.dmac_laddress)); 430*5e8715b9SGary Mills OUTL(atgep, L1C_TDL_HEAD_ADDR_LO, 431*5e8715b9SGary Mills ATGE_ADDR_LO(r->r_desc_ring->cookie.dmac_laddress)); 432*5e8715b9SGary Mills /* We don't use high priority ring. */ 433*5e8715b9SGary Mills OUTL(atgep, L1C_TDH_HEAD_ADDR_LO, 0); 434*5e8715b9SGary Mills 435*5e8715b9SGary Mills /* RX */ 436*5e8715b9SGary Mills r = l1c->atge_rx_ring; 437*5e8715b9SGary Mills OUTL(atgep, L1C_RX_BASE_ADDR_HI, 438*5e8715b9SGary Mills ATGE_ADDR_HI(r->r_desc_ring->cookie.dmac_laddress)); 439*5e8715b9SGary Mills OUTL(atgep, L1C_RD0_HEAD_ADDR_LO, 440*5e8715b9SGary Mills ATGE_ADDR_LO(r->r_desc_ring->cookie.dmac_laddress)); 441*5e8715b9SGary Mills /* We use one Rx ring. */ 442*5e8715b9SGary Mills OUTL(atgep, L1C_RD1_HEAD_ADDR_LO, 0); 443*5e8715b9SGary Mills OUTL(atgep, L1C_RD2_HEAD_ADDR_LO, 0); 444*5e8715b9SGary Mills OUTL(atgep, L1C_RD3_HEAD_ADDR_LO, 0); 445*5e8715b9SGary Mills 446*5e8715b9SGary Mills /* RR Ring */ 447*5e8715b9SGary Mills /* 448*5e8715b9SGary Mills * Let hardware split jumbo frames into alc_max_buf_sized chunks. 449*5e8715b9SGary Mills * if it do not fit the buffer size. Rx return descriptor holds 450*5e8715b9SGary Mills * a counter that indicates how many fragments were made by the 451*5e8715b9SGary Mills * hardware. The buffer size should be multiple of 8 bytes. 452*5e8715b9SGary Mills * Since hardware has limit on the size of buffer size, always 453*5e8715b9SGary Mills * use the maximum value. 454*5e8715b9SGary Mills * For strict-alignment architectures make sure to reduce buffer 455*5e8715b9SGary Mills * size by 8 bytes to make room for alignment fixup. 456*5e8715b9SGary Mills */ 457*5e8715b9SGary Mills OUTL(atgep, L1C_RX_BUF_SIZE, RX_BUF_SIZE_MAX); /* XXX */ 458*5e8715b9SGary Mills 459*5e8715b9SGary Mills /* Set Rx return descriptor base addresses. */ 460*5e8715b9SGary Mills OUTL(atgep, L1C_RRD0_HEAD_ADDR_LO, 461*5e8715b9SGary Mills ATGE_ADDR_LO(l1c->atge_l1c_rr->cookie.dmac_laddress)); 462*5e8715b9SGary Mills /* We use one Rx return ring. */ 463*5e8715b9SGary Mills OUTL(atgep, L1C_RRD1_HEAD_ADDR_LO, 0); 464*5e8715b9SGary Mills OUTL(atgep, L1C_RRD2_HEAD_ADDR_LO, 0); 465*5e8715b9SGary Mills OUTL(atgep, L1C_RRD3_HEAD_ADDR_LO, 0); 466*5e8715b9SGary Mills 467*5e8715b9SGary Mills /* CMB */ 468*5e8715b9SGary Mills OUTL(atgep, L1C_CMB_BASE_ADDR_LO, 469*5e8715b9SGary Mills ATGE_ADDR_LO(l1c->atge_l1c_cmb->cookie.dmac_laddress)); 470*5e8715b9SGary Mills 471*5e8715b9SGary Mills /* SMB */ 472*5e8715b9SGary Mills OUTL(atgep, L1C_SMB_BASE_ADDR_HI, 473*5e8715b9SGary Mills ATGE_ADDR_HI(l1c->atge_l1c_smb->cookie.dmac_laddress)); 474*5e8715b9SGary Mills OUTL(atgep, L1C_SMB_BASE_ADDR_LO, 475*5e8715b9SGary Mills ATGE_ADDR_LO(l1c->atge_l1c_smb->cookie.dmac_laddress)); 476*5e8715b9SGary Mills 477*5e8715b9SGary Mills /* 478*5e8715b9SGary Mills * Set RX return ring (RR) counter. 479*5e8715b9SGary Mills */ 480*5e8715b9SGary Mills /* Set Rx descriptor counter. */ 481*5e8715b9SGary Mills OUTL(atgep, L1C_RD_RING_CNT, 482*5e8715b9SGary Mills (L1C_RX_RING_CNT << RD_RING_CNT_SHIFT) & RD_RING_CNT_MASK); 483*5e8715b9SGary Mills /* Set Rx return descriptor counter. */ 484*5e8715b9SGary Mills OUTL(atgep, L1C_RRD_RING_CNT, 485*5e8715b9SGary Mills (L1C_RR_RING_CNT << RRD_RING_CNT_SHIFT) & RRD_RING_CNT_MASK); 486*5e8715b9SGary Mills 487*5e8715b9SGary Mills /* 488*5e8715b9SGary Mills * Set TX descriptor counter. 489*5e8715b9SGary Mills */ 490*5e8715b9SGary Mills OUTL(atgep, L1C_TD_RING_CNT, 491*5e8715b9SGary Mills (ATGE_TX_RING_CNT << TD_RING_CNT_SHIFT) & TD_RING_CNT_MASK); 492*5e8715b9SGary Mills 493*5e8715b9SGary Mills switch (ATGE_DID(atgep)) { 494*5e8715b9SGary Mills case ATGE_CHIP_AR8152V1_DEV_ID: 495*5e8715b9SGary Mills /* Reconfigure SRAM - Vendor magic. */ 496*5e8715b9SGary Mills OUTL(atgep, L1C_SRAM_RX_FIFO_LEN, 0x000002A0); 497*5e8715b9SGary Mills OUTL(atgep, L1C_SRAM_TX_FIFO_LEN, 0x00000100); 498*5e8715b9SGary Mills OUTL(atgep, L1C_SRAM_RX_FIFO_ADDR, 0x029F0000); 499*5e8715b9SGary Mills OUTL(atgep, L1C_SRAM_RD_ADDR, 0x02BF02A0); 500*5e8715b9SGary Mills OUTL(atgep, L1C_SRAM_TX_FIFO_ADDR, 0x03BF02C0); 501*5e8715b9SGary Mills OUTL(atgep, L1C_SRAM_TRD_ADDR, 0x03DF03C0); 502*5e8715b9SGary Mills OUTL(atgep, L1C_TXF_WATER_MARK, 0x00000000); 503*5e8715b9SGary Mills OUTL(atgep, L1C_RD_DMA_CFG, 0x00000000); 504*5e8715b9SGary Mills break; 505*5e8715b9SGary Mills } 506*5e8715b9SGary Mills 507*5e8715b9SGary Mills /* 508*5e8715b9SGary Mills * Inform hardware that we have loaded DMA registers. 509*5e8715b9SGary Mills */ 510*5e8715b9SGary Mills OUTL(atgep, ATGE_DMA_BLOCK, DMA_BLOCK_LOAD); 511*5e8715b9SGary Mills 512*5e8715b9SGary Mills /* Configure interrupt moderation timer. */ 513*5e8715b9SGary Mills reg = ATGE_USECS(atgep->atge_int_rx_mod) << IM_TIMER_RX_SHIFT; 514*5e8715b9SGary Mills reg |= ATGE_USECS(atgep->atge_int_tx_mod) << IM_TIMER_TX_SHIFT; 515*5e8715b9SGary Mills OUTL(atgep, ATGE_IM_TIMER, reg); 516*5e8715b9SGary Mills /* 517*5e8715b9SGary Mills * We don't want to automatic interrupt clear as task queue 518*5e8715b9SGary Mills * for the interrupt should know interrupt status. 519*5e8715b9SGary Mills */ 520*5e8715b9SGary Mills reg = 0; 521*5e8715b9SGary Mills if (ATGE_USECS(atgep->atge_int_rx_mod) != 0) 522*5e8715b9SGary Mills reg |= MASTER_IM_RX_TIMER_ENB; 523*5e8715b9SGary Mills if (ATGE_USECS(atgep->atge_int_tx_mod) != 0) 524*5e8715b9SGary Mills reg |= MASTER_IM_TX_TIMER_ENB; 525*5e8715b9SGary Mills OUTL(atgep, ATGE_MASTER_CFG, reg); 526*5e8715b9SGary Mills } 527*5e8715b9SGary Mills 528*5e8715b9SGary Mills void 529*5e8715b9SGary Mills atge_l1c_clear_stats(atge_t *atgep) 530*5e8715b9SGary Mills { 531*5e8715b9SGary Mills atge_l1c_smb_t smb; 532*5e8715b9SGary Mills uint32_t *reg; 533*5e8715b9SGary Mills int i; 534*5e8715b9SGary Mills 535*5e8715b9SGary Mills /* 536*5e8715b9SGary Mills * Clear RX stats first. 537*5e8715b9SGary Mills */ 538*5e8715b9SGary Mills i = 0; 539*5e8715b9SGary Mills reg = &smb.rx_frames; 540*5e8715b9SGary Mills while (reg++ <= &smb.rx_pkts_filtered) { 541*5e8715b9SGary Mills (void) INL(atgep, ATGE_RX_MIB_BASE + i); 542*5e8715b9SGary Mills i += sizeof (uint32_t); 543*5e8715b9SGary Mills } 544*5e8715b9SGary Mills 545*5e8715b9SGary Mills /* 546*5e8715b9SGary Mills * Clear TX stats. 547*5e8715b9SGary Mills */ 548*5e8715b9SGary Mills i = 0; 549*5e8715b9SGary Mills reg = &smb.tx_frames; 550*5e8715b9SGary Mills while (reg++ <= &smb.tx_mcast_bytes) { 551*5e8715b9SGary Mills (void) INL(atgep, ATGE_TX_MIB_BASE + i); 552*5e8715b9SGary Mills i += sizeof (uint32_t); 553*5e8715b9SGary Mills } 554*5e8715b9SGary Mills } 555*5e8715b9SGary Mills 556*5e8715b9SGary Mills void 557*5e8715b9SGary Mills atge_l1c_gather_stats(atge_t *atgep) 558*5e8715b9SGary Mills { 559*5e8715b9SGary Mills atge_l1c_data_t *l1c; 560*5e8715b9SGary Mills atge_dma_t *dma; 561*5e8715b9SGary Mills atge_l1c_smb_t *stat; 562*5e8715b9SGary Mills atge_l1c_smb_t *smb; 563*5e8715b9SGary Mills 564*5e8715b9SGary Mills ASSERT(atgep != NULL); 565*5e8715b9SGary Mills 566*5e8715b9SGary Mills l1c = atgep->atge_private_data; 567*5e8715b9SGary Mills dma = l1c->atge_l1c_smb; 568*5e8715b9SGary Mills DMA_SYNC(dma, 0, 0, DDI_DMA_SYNC_FORKERNEL); 569*5e8715b9SGary Mills stat = (atge_l1c_smb_t *)atgep->atge_hw_stats; 570*5e8715b9SGary Mills smb = (atge_l1c_smb_t *)dma->addr; 571*5e8715b9SGary Mills 572*5e8715b9SGary Mills /* Rx stats. */ 573*5e8715b9SGary Mills stat->rx_frames += smb->rx_frames; 574*5e8715b9SGary Mills stat->rx_bcast_frames += smb->rx_bcast_frames; 575*5e8715b9SGary Mills stat->rx_mcast_frames += smb->rx_mcast_frames; 576*5e8715b9SGary Mills stat->rx_pause_frames += smb->rx_pause_frames; 577*5e8715b9SGary Mills stat->rx_control_frames += smb->rx_control_frames; 578*5e8715b9SGary Mills stat->rx_crcerrs += smb->rx_crcerrs; 579*5e8715b9SGary Mills stat->rx_lenerrs += smb->rx_lenerrs; 580*5e8715b9SGary Mills stat->rx_bytes += smb->rx_bytes; 581*5e8715b9SGary Mills stat->rx_runts += smb->rx_runts; 582*5e8715b9SGary Mills stat->rx_fragments += smb->rx_fragments; 583*5e8715b9SGary Mills stat->rx_pkts_64 += smb->rx_pkts_64; 584*5e8715b9SGary Mills stat->rx_pkts_65_127 += smb->rx_pkts_65_127; 585*5e8715b9SGary Mills stat->rx_pkts_128_255 += smb->rx_pkts_128_255; 586*5e8715b9SGary Mills stat->rx_pkts_256_511 += smb->rx_pkts_256_511; 587*5e8715b9SGary Mills stat->rx_pkts_512_1023 += smb->rx_pkts_512_1023; 588*5e8715b9SGary Mills stat->rx_pkts_1024_1518 += smb->rx_pkts_1024_1518; 589*5e8715b9SGary Mills stat->rx_pkts_1519_max += smb->rx_pkts_1519_max; 590*5e8715b9SGary Mills stat->rx_pkts_truncated += smb->rx_pkts_truncated; 591*5e8715b9SGary Mills stat->rx_fifo_oflows += smb->rx_fifo_oflows; 592*5e8715b9SGary Mills stat->rx_alignerrs += smb->rx_alignerrs; 593*5e8715b9SGary Mills stat->rx_bcast_bytes += smb->rx_bcast_bytes; 594*5e8715b9SGary Mills stat->rx_mcast_bytes += smb->rx_mcast_bytes; 595*5e8715b9SGary Mills stat->rx_pkts_filtered += smb->rx_pkts_filtered; 596*5e8715b9SGary Mills 597*5e8715b9SGary Mills /* Tx stats. */ 598*5e8715b9SGary Mills stat->tx_frames += smb->tx_frames; 599*5e8715b9SGary Mills stat->tx_bcast_frames += smb->tx_bcast_frames; 600*5e8715b9SGary Mills stat->tx_mcast_frames += smb->tx_mcast_frames; 601*5e8715b9SGary Mills stat->tx_pause_frames += smb->tx_pause_frames; 602*5e8715b9SGary Mills stat->tx_excess_defer += smb->tx_excess_defer; 603*5e8715b9SGary Mills stat->tx_control_frames += smb->tx_control_frames; 604*5e8715b9SGary Mills stat->tx_deferred += smb->tx_deferred; 605*5e8715b9SGary Mills stat->tx_bytes += smb->tx_bytes; 606*5e8715b9SGary Mills stat->tx_pkts_64 += smb->tx_pkts_64; 607*5e8715b9SGary Mills stat->tx_pkts_65_127 += smb->tx_pkts_65_127; 608*5e8715b9SGary Mills stat->tx_pkts_128_255 += smb->tx_pkts_128_255; 609*5e8715b9SGary Mills stat->tx_pkts_256_511 += smb->tx_pkts_256_511; 610*5e8715b9SGary Mills stat->tx_pkts_512_1023 += smb->tx_pkts_512_1023; 611*5e8715b9SGary Mills stat->tx_pkts_1024_1518 += smb->tx_pkts_1024_1518; 612*5e8715b9SGary Mills stat->tx_pkts_1519_max += smb->tx_pkts_1519_max; 613*5e8715b9SGary Mills stat->tx_single_colls += smb->tx_single_colls; 614*5e8715b9SGary Mills stat->tx_multi_colls += smb->tx_multi_colls; 615*5e8715b9SGary Mills stat->tx_late_colls += smb->tx_late_colls; 616*5e8715b9SGary Mills stat->tx_excess_colls += smb->tx_excess_colls; 617*5e8715b9SGary Mills stat->tx_underrun += smb->tx_underrun; 618*5e8715b9SGary Mills stat->tx_desc_underrun += smb->tx_desc_underrun; 619*5e8715b9SGary Mills stat->tx_lenerrs += smb->tx_lenerrs; 620*5e8715b9SGary Mills stat->tx_pkts_truncated += smb->tx_pkts_truncated; 621*5e8715b9SGary Mills stat->tx_bcast_bytes += smb->tx_bcast_bytes; 622*5e8715b9SGary Mills stat->tx_mcast_bytes += smb->tx_mcast_bytes; 623*5e8715b9SGary Mills 624*5e8715b9SGary Mills /* 625*5e8715b9SGary Mills * Update global counters in atge_t. 626*5e8715b9SGary Mills */ 627*5e8715b9SGary Mills atgep->atge_brdcstrcv += smb->rx_bcast_frames; 628*5e8715b9SGary Mills atgep->atge_multircv += smb->rx_mcast_frames; 629*5e8715b9SGary Mills atgep->atge_multixmt += smb->tx_mcast_frames; 630*5e8715b9SGary Mills atgep->atge_brdcstxmt += smb->tx_bcast_frames; 631*5e8715b9SGary Mills 632*5e8715b9SGary Mills atgep->atge_align_errors += smb->rx_alignerrs; 633*5e8715b9SGary Mills atgep->atge_fcs_errors += smb->rx_crcerrs; 634*5e8715b9SGary Mills atgep->atge_defer_xmts += smb->tx_deferred; 635*5e8715b9SGary Mills atgep->atge_first_collisions += smb->tx_single_colls; 636*5e8715b9SGary Mills atgep->atge_multi_collisions += smb->tx_multi_colls * 2; 637*5e8715b9SGary Mills atgep->atge_tx_late_collisions += smb->tx_late_colls; 638*5e8715b9SGary Mills atgep->atge_ex_collisions += smb->tx_excess_colls; 639*5e8715b9SGary Mills atgep->atge_toolong_errors += smb->rx_lenerrs; 640*5e8715b9SGary Mills atgep->atge_overflow += smb->rx_fifo_oflows; 641*5e8715b9SGary Mills atgep->atge_underflow += (smb->tx_underrun + smb->tx_desc_underrun); 642*5e8715b9SGary Mills atgep->atge_runt += smb->rx_runts; 643*5e8715b9SGary Mills 644*5e8715b9SGary Mills 645*5e8715b9SGary Mills atgep->atge_collisions += smb->tx_single_colls + 646*5e8715b9SGary Mills smb->tx_multi_colls * 2 + smb->tx_late_colls; 647*5e8715b9SGary Mills 648*5e8715b9SGary Mills /* 649*5e8715b9SGary Mills * tx_pkts_truncated counter looks suspicious. It constantly 650*5e8715b9SGary Mills * increments with no sign of Tx errors. Hence we don't factor it. 651*5e8715b9SGary Mills */ 652*5e8715b9SGary Mills atgep->atge_macxmt_errors += smb->tx_late_colls + smb->tx_underrun; 653*5e8715b9SGary Mills 654*5e8715b9SGary Mills atgep->atge_macrcv_errors += smb->rx_crcerrs + smb->rx_lenerrs + 655*5e8715b9SGary Mills smb->rx_runts + smb->rx_pkts_truncated + 656*5e8715b9SGary Mills smb->rx_alignerrs; 657*5e8715b9SGary Mills 658*5e8715b9SGary Mills smb->updated = 0; 659*5e8715b9SGary Mills DMA_SYNC(dma, 0, 0, DDI_DMA_SYNC_FORDEV); 660*5e8715b9SGary Mills } 661*5e8715b9SGary Mills 662*5e8715b9SGary Mills void 663*5e8715b9SGary Mills atge_l1c_stop_tx_mac(atge_t *atgep) 664*5e8715b9SGary Mills { 665*5e8715b9SGary Mills uint32_t reg; 666*5e8715b9SGary Mills int t; 667*5e8715b9SGary Mills 668*5e8715b9SGary Mills ATGE_DB(("%s: %s() called", atgep->atge_name, __func__)); 669*5e8715b9SGary Mills 670*5e8715b9SGary Mills reg = INL(atgep, ATGE_MAC_CFG); 671*5e8715b9SGary Mills if ((reg & ATGE_CFG_TX_ENB) != 0) { 672*5e8715b9SGary Mills reg &= ~ATGE_CFG_TX_ENB; 673*5e8715b9SGary Mills OUTL(atgep, ATGE_MAC_CFG, reg); 674*5e8715b9SGary Mills } 675*5e8715b9SGary Mills 676*5e8715b9SGary Mills /* Stop TX DMA engine. */ 677*5e8715b9SGary Mills reg = INL(atgep, ATGE_DMA_CFG); 678*5e8715b9SGary Mills if ((reg & DMA_CFG_RD_ENB) != 0) { 679*5e8715b9SGary Mills reg &= ~DMA_CFG_RD_ENB; 680*5e8715b9SGary Mills OUTL(atgep, ATGE_DMA_CFG, reg); 681*5e8715b9SGary Mills } 682*5e8715b9SGary Mills 683*5e8715b9SGary Mills for (t = ATGE_RESET_TIMEOUT; t > 0; t--) { 684*5e8715b9SGary Mills if ((INL(atgep, ATGE_IDLE_STATUS) & 685*5e8715b9SGary Mills (IDLE_STATUS_TXMAC | IDLE_STATUS_DMARD)) == 0) 686*5e8715b9SGary Mills break; 687*5e8715b9SGary Mills 688*5e8715b9SGary Mills drv_usecwait(10); 689*5e8715b9SGary Mills } 690*5e8715b9SGary Mills 691*5e8715b9SGary Mills if (t == 0) { 692*5e8715b9SGary Mills /* This should be an FMA event. */ 693*5e8715b9SGary Mills atge_error(atgep->atge_dip, "stopping TX DMA Engine timeout"); 694*5e8715b9SGary Mills } 695*5e8715b9SGary Mills } 696*5e8715b9SGary Mills 697*5e8715b9SGary Mills void 698*5e8715b9SGary Mills atge_l1c_stop_rx_mac(atge_t *atgep) 699*5e8715b9SGary Mills { 700*5e8715b9SGary Mills uint32_t reg; 701*5e8715b9SGary Mills int t; 702*5e8715b9SGary Mills 703*5e8715b9SGary Mills ATGE_DB(("%s: %s() called", atgep->atge_name, __func__)); 704*5e8715b9SGary Mills 705*5e8715b9SGary Mills reg = INL(atgep, ATGE_MAC_CFG); 706*5e8715b9SGary Mills if ((reg & ATGE_CFG_RX_ENB) != 0) { 707*5e8715b9SGary Mills reg &= ~ATGE_CFG_RX_ENB; 708*5e8715b9SGary Mills OUTL(atgep, ATGE_MAC_CFG, reg); 709*5e8715b9SGary Mills } 710*5e8715b9SGary Mills 711*5e8715b9SGary Mills /* Stop RX DMA engine. */ 712*5e8715b9SGary Mills reg = INL(atgep, ATGE_DMA_CFG); 713*5e8715b9SGary Mills if ((reg & DMA_CFG_WR_ENB) != 0) { 714*5e8715b9SGary Mills reg &= ~DMA_CFG_WR_ENB; 715*5e8715b9SGary Mills OUTL(atgep, ATGE_DMA_CFG, reg); 716*5e8715b9SGary Mills } 717*5e8715b9SGary Mills 718*5e8715b9SGary Mills for (t = ATGE_RESET_TIMEOUT; t > 0; t--) { 719*5e8715b9SGary Mills if ((INL(atgep, ATGE_IDLE_STATUS) & 720*5e8715b9SGary Mills (IDLE_STATUS_RXMAC | IDLE_STATUS_DMAWR)) == 0) 721*5e8715b9SGary Mills break; 722*5e8715b9SGary Mills drv_usecwait(10); 723*5e8715b9SGary Mills } 724*5e8715b9SGary Mills 725*5e8715b9SGary Mills if (t == 0) { 726*5e8715b9SGary Mills /* This should be an FMA event. */ 727*5e8715b9SGary Mills atge_error(atgep->atge_dip, " stopping RX DMA Engine timeout"); 728*5e8715b9SGary Mills } 729*5e8715b9SGary Mills } 730*5e8715b9SGary Mills 731*5e8715b9SGary Mills /* 732*5e8715b9SGary Mills * Receives (consumes) packets. 733*5e8715b9SGary Mills */ 734*5e8715b9SGary Mills static mblk_t * 735*5e8715b9SGary Mills atge_l1c_rx(atge_t *atgep) 736*5e8715b9SGary Mills { 737*5e8715b9SGary Mills atge_l1c_data_t *l1c; 738*5e8715b9SGary Mills mblk_t *mp = NULL, *rx_head = NULL, *rx_tail = NULL; 739*5e8715b9SGary Mills l1c_rx_rdesc_t *rx_rr; 740*5e8715b9SGary Mills uint32_t rdinfo, status, totlen, pktlen, slotlen; 741*5e8715b9SGary Mills int nsegs, rx_cons = 0, cnt; 742*5e8715b9SGary Mills atge_dma_t *buf; 743*5e8715b9SGary Mills uchar_t *bufp; 744*5e8715b9SGary Mills int sync = 0; 745*5e8715b9SGary Mills 746*5e8715b9SGary Mills l1c = atgep->atge_private_data; 747*5e8715b9SGary Mills ASSERT(l1c != NULL); 748*5e8715b9SGary Mills 749*5e8715b9SGary Mills DMA_SYNC(l1c->atge_l1c_rr, 0, 0, DDI_DMA_SYNC_FORKERNEL); 750*5e8715b9SGary Mills for (;;) { 751*5e8715b9SGary Mills rx_rr = (l1c_rx_rdesc_t *)(l1c->atge_l1c_rr->addr + 752*5e8715b9SGary Mills (l1c->atge_l1c_rr_consumers * sizeof (l1c_rx_rdesc_t))); 753*5e8715b9SGary Mills 754*5e8715b9SGary Mills rdinfo = ATGE_GET32(l1c->atge_l1c_rr, &rx_rr->rdinfo); 755*5e8715b9SGary Mills status = ATGE_GET32(l1c->atge_l1c_rr, &rx_rr->status); 756*5e8715b9SGary Mills 757*5e8715b9SGary Mills rx_cons = L1C_RRD_RD_IDX(rdinfo); 758*5e8715b9SGary Mills nsegs = L1C_RRD_RD_CNT(rdinfo); 759*5e8715b9SGary Mills totlen = L1C_RRD_BYTES(status); 760*5e8715b9SGary Mills 761*5e8715b9SGary Mills ATGE_DB(("%s: %s() PKT -- rdinfo : 0x%x," 762*5e8715b9SGary Mills "status : 0x%x, totlen : %d," 763*5e8715b9SGary Mills " rx_cons : %d, nsegs : %d", atgep->atge_name, __func__, 764*5e8715b9SGary Mills rdinfo, status, totlen, rx_cons, nsegs)); 765*5e8715b9SGary Mills 766*5e8715b9SGary Mills if ((status & L1C_RRD_VALID) == 0) { 767*5e8715b9SGary Mills break; 768*5e8715b9SGary Mills } 769*5e8715b9SGary Mills 770*5e8715b9SGary Mills if ((status & (L1C_RRD_ERR_CRC | L1C_RRD_ERR_ALIGN | 771*5e8715b9SGary Mills L1C_RRD_ERR_TRUNC | L1C_RRD_ERR_RUNT | 772*5e8715b9SGary Mills L1C_RRD_ERR_ICMP | L1C_RRD_ERR_LENGTH)) != 0) { 773*5e8715b9SGary Mills atge_error(atgep->atge_dip, "errored pkt"); 774*5e8715b9SGary Mills 775*5e8715b9SGary Mills l1c->atge_rx_ring->r_consumer += nsegs; 776*5e8715b9SGary Mills l1c->atge_rx_ring->r_consumer %= L1C_RX_RING_CNT; 777*5e8715b9SGary Mills break; 778*5e8715b9SGary Mills } 779*5e8715b9SGary Mills 780*5e8715b9SGary Mills ASSERT(rx_cons >= 0 && rx_cons <= L1C_RX_RING_CNT); 781*5e8715b9SGary Mills 782*5e8715b9SGary Mills mp = allocb(totlen + L1C_HEADROOM, BPRI_MED); 783*5e8715b9SGary Mills if (mp != NULL) { 784*5e8715b9SGary Mills mp->b_rptr += L1C_HEADROOM; 785*5e8715b9SGary Mills bufp = mp->b_rptr; 786*5e8715b9SGary Mills mp->b_wptr = bufp + totlen; 787*5e8715b9SGary Mills mp->b_next = NULL; 788*5e8715b9SGary Mills 789*5e8715b9SGary Mills atgep->atge_ipackets++; 790*5e8715b9SGary Mills atgep->atge_rbytes += totlen; 791*5e8715b9SGary Mills 792*5e8715b9SGary Mills /* 793*5e8715b9SGary Mills * If there are more than one segments, then the first 794*5e8715b9SGary Mills * segment should be of size MTU. We couldn't verify 795*5e8715b9SGary Mills * this as our driver does not support changing MTU 796*5e8715b9SGary Mills * or Jumbo Frames. 797*5e8715b9SGary Mills */ 798*5e8715b9SGary Mills if (nsegs > 1) { 799*5e8715b9SGary Mills slotlen = atgep->atge_mtu; 800*5e8715b9SGary Mills } else { 801*5e8715b9SGary Mills slotlen = totlen; 802*5e8715b9SGary Mills } 803*5e8715b9SGary Mills } else { 804*5e8715b9SGary Mills ATGE_DB(("%s: %s() PKT mp == NULL totlen : %d", 805*5e8715b9SGary Mills atgep->atge_name, __func__, totlen)); 806*5e8715b9SGary Mills 807*5e8715b9SGary Mills if (slotlen > atgep->atge_rx_buf_len) { 808*5e8715b9SGary Mills atgep->atge_toolong_errors++; 809*5e8715b9SGary Mills } else if (mp == NULL) { 810*5e8715b9SGary Mills atgep->atge_norcvbuf++; 811*5e8715b9SGary Mills } 812*5e8715b9SGary Mills 813*5e8715b9SGary Mills rx_rr->status = 0; 814*5e8715b9SGary Mills break; 815*5e8715b9SGary Mills } 816*5e8715b9SGary Mills 817*5e8715b9SGary Mills for (cnt = 0, pktlen = 0; cnt < nsegs; cnt++) { 818*5e8715b9SGary Mills buf = l1c->atge_rx_ring->r_buf_tbl[rx_cons]; 819*5e8715b9SGary Mills 820*5e8715b9SGary Mills slotlen = min(atgep->atge_max_frame_size, totlen); 821*5e8715b9SGary Mills 822*5e8715b9SGary Mills bcopy(buf->addr, (bufp + pktlen), slotlen); 823*5e8715b9SGary Mills pktlen += slotlen; 824*5e8715b9SGary Mills totlen -= slotlen; 825*5e8715b9SGary Mills 826*5e8715b9SGary Mills ATGE_DB(("%s: %s() len : %d, rxcons : %d, pktlen : %d", 827*5e8715b9SGary Mills atgep->atge_name, __func__, slotlen, rx_cons, 828*5e8715b9SGary Mills pktlen)); 829*5e8715b9SGary Mills 830*5e8715b9SGary Mills ATGE_INC_SLOT(rx_cons, L1C_RX_RING_CNT); 831*5e8715b9SGary Mills } 832*5e8715b9SGary Mills 833*5e8715b9SGary Mills if (rx_tail == NULL) { 834*5e8715b9SGary Mills rx_head = rx_tail = mp; 835*5e8715b9SGary Mills } else { 836*5e8715b9SGary Mills rx_tail->b_next = mp; 837*5e8715b9SGary Mills rx_tail = mp; 838*5e8715b9SGary Mills } 839*5e8715b9SGary Mills 840*5e8715b9SGary Mills if (cnt != nsegs) { 841*5e8715b9SGary Mills l1c->atge_rx_ring->r_consumer += nsegs; 842*5e8715b9SGary Mills l1c->atge_rx_ring->r_consumer %= L1C_RX_RING_CNT; 843*5e8715b9SGary Mills } else { 844*5e8715b9SGary Mills l1c->atge_rx_ring->r_consumer = rx_cons; 845*5e8715b9SGary Mills } 846*5e8715b9SGary Mills 847*5e8715b9SGary Mills /* 848*5e8715b9SGary Mills * Tell the chip that this RR can be reused. 849*5e8715b9SGary Mills */ 850*5e8715b9SGary Mills rx_rr->status = 0; 851*5e8715b9SGary Mills 852*5e8715b9SGary Mills ATGE_INC_SLOT(l1c->atge_l1c_rr_consumers, L1C_RR_RING_CNT); 853*5e8715b9SGary Mills sync++; 854*5e8715b9SGary Mills } 855*5e8715b9SGary Mills 856*5e8715b9SGary Mills if (sync) { 857*5e8715b9SGary Mills DMA_SYNC(l1c->atge_rx_ring->r_desc_ring, 0, 0, 858*5e8715b9SGary Mills DDI_DMA_SYNC_FORDEV); 859*5e8715b9SGary Mills 860*5e8715b9SGary Mills DMA_SYNC(l1c->atge_l1c_rr, 0, 0, DDI_DMA_SYNC_FORDEV); 861*5e8715b9SGary Mills /* 862*5e8715b9SGary Mills * Let controller know availability of new Rx buffers. 863*5e8715b9SGary Mills */ 864*5e8715b9SGary Mills OUTL(atgep, ATGE_MBOX_RD0_PROD_IDX, 865*5e8715b9SGary Mills l1c->atge_rx_ring->r_consumer); 866*5e8715b9SGary Mills 867*5e8715b9SGary Mills ATGE_DB(("%s: %s() PKT Recved -> r_consumer : %d, rx_cons : %d" 868*5e8715b9SGary Mills " atge_l1c_rr_consumers : %d", 869*5e8715b9SGary Mills atgep->atge_name, __func__, l1c->atge_rx_ring->r_consumer, 870*5e8715b9SGary Mills rx_cons, l1c->atge_l1c_rr_consumers)); 871*5e8715b9SGary Mills } 872*5e8715b9SGary Mills 873*5e8715b9SGary Mills 874*5e8715b9SGary Mills return (rx_head); 875*5e8715b9SGary Mills } 876*5e8715b9SGary Mills 877*5e8715b9SGary Mills /* 878*5e8715b9SGary Mills * The interrupt handler for L1C chip. 879*5e8715b9SGary Mills */ 880*5e8715b9SGary Mills /*ARGSUSED*/ 881*5e8715b9SGary Mills uint_t 882*5e8715b9SGary Mills atge_l1c_interrupt(caddr_t arg1, caddr_t arg2) 883*5e8715b9SGary Mills { 884*5e8715b9SGary Mills atge_t *atgep = (void *)arg1; 885*5e8715b9SGary Mills mblk_t *rx_head = NULL; 886*5e8715b9SGary Mills uint32_t status; 887*5e8715b9SGary Mills int resched = 0; 888*5e8715b9SGary Mills 889*5e8715b9SGary Mills ASSERT(atgep != NULL); 890*5e8715b9SGary Mills 891*5e8715b9SGary Mills mutex_enter(&atgep->atge_intr_lock); 892*5e8715b9SGary Mills 893*5e8715b9SGary Mills if (atgep->atge_chip_state & ATGE_CHIP_SUSPENDED) { 894*5e8715b9SGary Mills mutex_exit(&atgep->atge_intr_lock); 895*5e8715b9SGary Mills return (DDI_INTR_UNCLAIMED); 896*5e8715b9SGary Mills } 897*5e8715b9SGary Mills 898*5e8715b9SGary Mills status = INL(atgep, ATGE_INTR_STATUS); 899*5e8715b9SGary Mills if (status == 0 || (status & atgep->atge_intrs) == 0) { 900*5e8715b9SGary Mills mutex_exit(&atgep->atge_intr_lock); 901*5e8715b9SGary Mills 902*5e8715b9SGary Mills if (atgep->atge_flags & ATGE_FIXED_TYPE) 903*5e8715b9SGary Mills return (DDI_INTR_UNCLAIMED); 904*5e8715b9SGary Mills 905*5e8715b9SGary Mills return (DDI_INTR_CLAIMED); 906*5e8715b9SGary Mills } 907*5e8715b9SGary Mills 908*5e8715b9SGary Mills ATGE_DB(("%s: %s() entry status : %x", 909*5e8715b9SGary Mills atgep->atge_name, __func__, status)); 910*5e8715b9SGary Mills 911*5e8715b9SGary Mills /* 912*5e8715b9SGary Mills * Disable interrupts. 913*5e8715b9SGary Mills */ 914*5e8715b9SGary Mills if (status & L1C_INTR_GPHY) { 915*5e8715b9SGary Mills /* clear PHY interrupt source before we ack interrupts */ 916*5e8715b9SGary Mills (void) atge_mii_read(atgep, 917*5e8715b9SGary Mills atgep->atge_phyaddr, ATGE_ISR_ACK_GPHY); 918*5e8715b9SGary Mills } 919*5e8715b9SGary Mills 920*5e8715b9SGary Mills OUTL(atgep, ATGE_INTR_STATUS, status | L1C_INTR_DIS_INT); 921*5e8715b9SGary Mills FLUSH(atgep, ATGE_INTR_STATUS); 922*5e8715b9SGary Mills 923*5e8715b9SGary Mills /* 924*5e8715b9SGary Mills * Check if chip is running, only then do the work. 925*5e8715b9SGary Mills */ 926*5e8715b9SGary Mills if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) { 927*5e8715b9SGary Mills atge_l1c_data_t *l1c; 928*5e8715b9SGary Mills 929*5e8715b9SGary Mills l1c = atgep->atge_private_data; 930*5e8715b9SGary Mills 931*5e8715b9SGary Mills ATGE_DB(("%s: %s() atge_l1c_intr_status : %x, " 932*5e8715b9SGary Mills "atge_l1c_rx_prod_cons : %d, atge_l1c_tx_prod_cons : %d" 933*5e8715b9SGary Mills " atge_l1c_rr_consumers : %d", 934*5e8715b9SGary Mills atgep->atge_name, __func__, l1c->atge_l1c_intr_status, 935*5e8715b9SGary Mills l1c->atge_l1c_rx_prod_cons, l1c->atge_l1c_tx_prod_cons, 936*5e8715b9SGary Mills l1c->atge_l1c_rr_consumers)); 937*5e8715b9SGary Mills 938*5e8715b9SGary Mills if (status & L1C_INTR_SMB) 939*5e8715b9SGary Mills atge_l1c_gather_stats(atgep); 940*5e8715b9SGary Mills 941*5e8715b9SGary Mills /* 942*5e8715b9SGary Mills * Check for errors. 943*5e8715b9SGary Mills */ 944*5e8715b9SGary Mills if (status & (L1C_INTR_DMA_RD_TO_RST | 945*5e8715b9SGary Mills L1C_INTR_DMA_WR_TO_RST | L1C_INTR_TXQ_TO_RST)) { 946*5e8715b9SGary Mills /* This should be an FMA event. */ 947*5e8715b9SGary Mills atge_error(atgep->atge_dip, 948*5e8715b9SGary Mills "L1C chip detected a fatal error, " 949*5e8715b9SGary Mills "interrupt status: %x", status); 950*5e8715b9SGary Mills 951*5e8715b9SGary Mills if (status & L1C_INTR_DMA_RD_TO_RST) { 952*5e8715b9SGary Mills atge_error(atgep->atge_dip, 953*5e8715b9SGary Mills "DMA read error"); 954*5e8715b9SGary Mills } 955*5e8715b9SGary Mills if (status & L1C_INTR_DMA_WR_TO_RST) { 956*5e8715b9SGary Mills atge_error(atgep->atge_dip, 957*5e8715b9SGary Mills "DMA write error"); 958*5e8715b9SGary Mills } 959*5e8715b9SGary Mills if (status & L1C_INTR_TXQ_TO_RST) { 960*5e8715b9SGary Mills atge_error(atgep->atge_dip, 961*5e8715b9SGary Mills "Transmit queue error"); 962*5e8715b9SGary Mills } 963*5e8715b9SGary Mills 964*5e8715b9SGary Mills /* This should be an FMA event. */ 965*5e8715b9SGary Mills atge_device_stop(atgep); 966*5e8715b9SGary Mills /* 967*5e8715b9SGary Mills * Device has failed fatally. 968*5e8715b9SGary Mills * It will not be restarted by the driver. 969*5e8715b9SGary Mills */ 970*5e8715b9SGary Mills goto done; 971*5e8715b9SGary Mills 972*5e8715b9SGary Mills } 973*5e8715b9SGary Mills 974*5e8715b9SGary Mills rx_head = atge_l1c_rx(atgep); 975*5e8715b9SGary Mills if (status & L1C_INTR_TX_PKT) { 976*5e8715b9SGary Mills int cons; 977*5e8715b9SGary Mills 978*5e8715b9SGary Mills mutex_enter(&atgep->atge_tx_lock); 979*5e8715b9SGary Mills cons = INL(atgep, ATGE_MBOX_TD_CONS_IDX) >> 16; 980*5e8715b9SGary Mills atge_tx_reclaim(atgep, cons); 981*5e8715b9SGary Mills if (atgep->atge_tx_resched) { 982*5e8715b9SGary Mills atgep->atge_tx_resched = 0; 983*5e8715b9SGary Mills resched = 1; 984*5e8715b9SGary Mills } 985*5e8715b9SGary Mills 986*5e8715b9SGary Mills mutex_exit(&atgep->atge_tx_lock); 987*5e8715b9SGary Mills } 988*5e8715b9SGary Mills } 989*5e8715b9SGary Mills 990*5e8715b9SGary Mills /* Re-enable interrupts. */ 991*5e8715b9SGary Mills OUTL(atgep, ATGE_INTR_STATUS, 0); 992*5e8715b9SGary Mills 993*5e8715b9SGary Mills done: 994*5e8715b9SGary Mills mutex_exit(&atgep->atge_intr_lock); 995*5e8715b9SGary Mills 996*5e8715b9SGary Mills if (status & L1C_INTR_GPHY) { 997*5e8715b9SGary Mills /* link down */ 998*5e8715b9SGary Mills ATGE_DB(("%s: %s() MII_CHECK Performed", 999*5e8715b9SGary Mills atgep->atge_name, __func__)); 1000*5e8715b9SGary Mills mii_check(atgep->atge_mii); 1001*5e8715b9SGary Mills } 1002*5e8715b9SGary Mills 1003*5e8715b9SGary Mills /* 1004*5e8715b9SGary Mills * Pass the list of packets received from chip to MAC layer. 1005*5e8715b9SGary Mills */ 1006*5e8715b9SGary Mills if (rx_head) { 1007*5e8715b9SGary Mills mac_rx(atgep->atge_mh, 0, rx_head); 1008*5e8715b9SGary Mills } 1009*5e8715b9SGary Mills 1010*5e8715b9SGary Mills /* 1011*5e8715b9SGary Mills * Let MAC start sending pkts if the downstream was asked to pause. 1012*5e8715b9SGary Mills */ 1013*5e8715b9SGary Mills if (resched) 1014*5e8715b9SGary Mills mac_tx_update(atgep->atge_mh); 1015*5e8715b9SGary Mills 1016*5e8715b9SGary Mills return (DDI_INTR_CLAIMED); 1017*5e8715b9SGary Mills } 1018*5e8715b9SGary Mills 1019*5e8715b9SGary Mills void 1020*5e8715b9SGary Mills atge_l1c_send_packet(atge_ring_t *r) 1021*5e8715b9SGary Mills { 1022*5e8715b9SGary Mills atge_t *atgep; 1023*5e8715b9SGary Mills 1024*5e8715b9SGary Mills atgep = r->r_atge; 1025*5e8715b9SGary Mills 1026*5e8715b9SGary Mills mutex_enter(&atgep->atge_mbox_lock); 1027*5e8715b9SGary Mills /* Sync descriptors. */ 1028*5e8715b9SGary Mills DMA_SYNC(atgep->atge_tx_ring->r_desc_ring, 0, 0, DDI_DMA_SYNC_FORDEV); 1029*5e8715b9SGary Mills /* Kick. Assume we're using normal Tx priority queue. */ 1030*5e8715b9SGary Mills OUTL(atgep, ATGE_MBOX_TD_PROD_IDX, 1031*5e8715b9SGary Mills (atgep->atge_tx_ring->r_producer << MBOX_TD_PROD_LO_IDX_SHIFT) & 1032*5e8715b9SGary Mills MBOX_TD_PROD_LO_IDX_MASK); 1033*5e8715b9SGary Mills mutex_exit(&atgep->atge_mbox_lock); 1034*5e8715b9SGary Mills } 1035