c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * CDDL HEADER START
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs *
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * The contents of this file are subject to the terms of the
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb * Common Development and Distribution License (the "License").
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb * You may not use this file except in compliance with the License.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs *
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * or http://www.opensolaris.org/os/licensing.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * See the License for the specific language governing permissions
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * and limitations under the License.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs *
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * When distributing Covered Code, include this CDDL HEADER in each
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * If applicable, add the following below this CDDL HEADER, with the
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * fields enclosed by brackets "[]" replaced with your own identifying
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * information: Portions Copyright [yyyy] [name of copyright owner]
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs *
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * CDDL HEADER END
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
5ca61e50c68a7a60dc35cd76831471faa4974d71Li-Zhen You * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Use is subject to license terms.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs#include "rge.h"
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * This is the string displayed by modinfo, etc.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Make sure you keep the version ID up to date!
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
193974072f41a843678abf5f61979c748687e66bSherry Moorestatic char rge_ident[] = "Realtek 1Gb Ethernet";
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Used for buffers allocated by ddi_dma_mem_alloc()
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic ddi_dma_attr_t dma_attr_buf = {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DMA_ATTR_V0, /* dma_attr version */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs (uint32_t)0, /* dma_attr_addr_lo */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs (uint32_t)0xFFFFFFFF, /* dma_attr_addr_hi */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs (uint32_t)0xFFFFFFFF, /* dma_attr_count_max */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs (uint32_t)16, /* dma_attr_align */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs 0xFFFFFFFF, /* dma_attr_burstsizes */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs 1, /* dma_attr_minxfer */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs (uint32_t)0xFFFFFFFF, /* dma_attr_maxxfer */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs (uint32_t)0xFFFFFFFF, /* dma_attr_seg */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs 1, /* dma_attr_sgllen */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs 1, /* dma_attr_granular */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs 0, /* dma_attr_flags */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs};
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Used for BDs allocated by ddi_dma_mem_alloc()
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic ddi_dma_attr_t dma_attr_desc = {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DMA_ATTR_V0, /* dma_attr version */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs (uint32_t)0, /* dma_attr_addr_lo */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs (uint32_t)0xFFFFFFFF, /* dma_attr_addr_hi */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs (uint32_t)0xFFFFFFFF, /* dma_attr_count_max */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs (uint32_t)256, /* dma_attr_align */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs 0xFFFFFFFF, /* dma_attr_burstsizes */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs 1, /* dma_attr_minxfer */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs (uint32_t)0xFFFFFFFF, /* dma_attr_maxxfer */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs (uint32_t)0xFFFFFFFF, /* dma_attr_seg */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs 1, /* dma_attr_sgllen */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs 1, /* dma_attr_granular */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs 0, /* dma_attr_flags */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs};
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * PIO access attributes for registers
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic ddi_device_acc_attr_t rge_reg_accattr = {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DDI_DEVICE_ATTR_V0,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DDI_STRUCTURE_LE_ACC,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DDI_STRICTORDER_ACC,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DDI_DEFAULT_ACC
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs};
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * DMA access attributes for descriptors
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic ddi_device_acc_attr_t rge_desc_accattr = {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DDI_DEVICE_ATTR_V0,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DDI_NEVERSWAP_ACC,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DDI_STRICTORDER_ACC,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DDI_DEFAULT_ACC
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs};
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * DMA access attributes for data
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic ddi_device_acc_attr_t rge_buf_accattr = {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DDI_DEVICE_ATTR_V0,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DDI_NEVERSWAP_ACC,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DDI_STRICTORDER_ACC,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DDI_DEFAULT_ACC
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs};
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Property names
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
aa81749390e332985277568edab1ee6132326b42gsstatic char debug_propname[] = "rge_debug_flags";
aa81749390e332985277568edab1ee6132326b42gsstatic char mtu_propname[] = "default_mtu";
aa81749390e332985277568edab1ee6132326b42gsstatic char msi_propname[] = "msi_enable";
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic int rge_m_start(void *);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic void rge_m_stop(void *);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic int rge_m_promisc(void *, boolean_t);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic int rge_m_multicst(void *, boolean_t, const uint8_t *);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic int rge_m_unicst(void *, const uint8_t *);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic void rge_m_ioctl(void *, queue_t *, mblk_t *);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic boolean_t rge_m_getcapab(void *, mac_capab_t, void *);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#define RGE_M_CALLBACK_FLAGS (MC_IOCTL | MC_GETCAPAB)
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic mac_callbacks_t rge_m_callbacks = {
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb RGE_M_CALLBACK_FLAGS,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb rge_m_stat,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb rge_m_start,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb rge_m_stop,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb rge_m_promisc,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb rge_m_multicst,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb rge_m_unicst,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb rge_m_tx,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer NULL,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb rge_m_ioctl,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb rge_m_getcapab
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb};
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Allocate an area of memory and a DMA handle for accessing it
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic int
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_alloc_dma_mem(rge_t *rgep, size_t memsize, ddi_dma_attr_t *dma_attr_p,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs ddi_device_acc_attr_t *acc_attr_p, uint_t dma_flags, dma_area_t *dma_p)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs caddr_t vaddr;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs int err;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Allocate handle
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs err = ddi_dma_alloc_handle(rgep->devinfo, dma_attr_p,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (err != DDI_SUCCESS) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_p->dma_hdl = NULL;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Allocate memory
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, acc_attr_p,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING),
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DDI_DMA_SLEEP, NULL, &vaddr, &dma_p->alength, &dma_p->acc_hdl);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (err != DDI_SUCCESS) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs ddi_dma_free_handle(&dma_p->dma_hdl);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_p->dma_hdl = NULL;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_p->acc_hdl = NULL;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Bind the two together
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_p->mem_va = vaddr;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs vaddr, dma_p->alength, dma_flags, DDI_DMA_SLEEP, NULL,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs &dma_p->cookie, &dma_p->ncookies);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (err != DDI_DMA_MAPPED || dma_p->ncookies != 1) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs ddi_dma_mem_free(&dma_p->acc_hdl);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs ddi_dma_free_handle(&dma_p->dma_hdl);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_p->acc_hdl = NULL;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_p->dma_hdl = NULL;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_p->nslots = ~0U;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_p->size = ~0U;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_p->token = ~0U;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_p->offset = 0;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_SUCCESS);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Free one allocated area of DMAable memory
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic void
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_free_dma_mem(dma_area_t *dma_p)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (dma_p->dma_hdl != NULL) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (dma_p->ncookies) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs (void) ddi_dma_unbind_handle(dma_p->dma_hdl);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_p->ncookies = 0;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs ddi_dma_free_handle(&dma_p->dma_hdl);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_p->dma_hdl = NULL;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (dma_p->acc_hdl != NULL) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs ddi_dma_mem_free(&dma_p->acc_hdl);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_p->acc_hdl = NULL;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Utility routine to carve a slice off a chunk of allocated memory,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * updating the chunk descriptor accordingly. The size of the slice
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * is given by the product of the <qty> and <size> parameters.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic void
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_slice_chunk(dma_area_t *slice, dma_area_t *chunk,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs uint32_t qty, uint32_t size)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs static uint32_t sequence = 0xbcd5704a;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs size_t totsize;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs totsize = qty*size;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs ASSERT(totsize <= chunk->alength);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs *slice = *chunk;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs slice->nslots = qty;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs slice->size = size;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs slice->alength = totsize;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs slice->token = ++sequence;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs chunk->mem_va = (caddr_t)chunk->mem_va + totsize;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs chunk->alength -= totsize;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs chunk->offset += totsize;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs chunk->cookie.dmac_laddress += totsize;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs chunk->cookie.dmac_size -= totsize;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic int
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_alloc_bufs(rge_t *rgep)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs size_t txdescsize;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs size_t rxdescsize;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs int err;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Allocate memory & handle for packet statistics
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs err = rge_alloc_dma_mem(rgep,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs RGE_STATS_DUMP_SIZE,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs &dma_attr_desc,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs &rge_desc_accattr,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs &rgep->dma_area_stats);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (err != DDI_SUCCESS)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->hw_stats = DMA_VPTR(rgep->dma_area_stats);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Allocate memory & handle for Tx descriptor ring
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs txdescsize = RGE_SEND_SLOTS * sizeof (rge_bd_t);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs err = rge_alloc_dma_mem(rgep,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs txdescsize,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs &dma_attr_desc,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs &rge_desc_accattr,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs &rgep->dma_area_txdesc);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (err != DDI_SUCCESS)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Allocate memory & handle for Rx descriptor ring
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rxdescsize = RGE_RECV_SLOTS * sizeof (rge_bd_t);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs err = rge_alloc_dma_mem(rgep,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rxdescsize,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs &dma_attr_desc,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs &rge_desc_accattr,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs &rgep->dma_area_rxdesc);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (err != DDI_SUCCESS)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_SUCCESS);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * rge_free_bufs() -- free descriptors/buffers allocated for this
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * device instance.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic void
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_free_bufs(rge_t *rgep)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_free_dma_mem(&rgep->dma_area_stats);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_free_dma_mem(&rgep->dma_area_txdesc);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_free_dma_mem(&rgep->dma_area_rxdesc);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * ========== Transmit and receive ring reinitialisation ==========
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * These <reinit> routines each reset the rx/tx rings to an initial
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * state, assuming that the corresponding <init> routine has already
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * been called exactly once.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic void
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_reinit_send_ring(rge_t *rgep)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs sw_sbd_t *ssbdp;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_bd_t *bdp;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs uint32_t slot;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * re-init send ring
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DMA_ZERO(rgep->tx_desc);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs ssbdp = rgep->sw_sbds;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs bdp = rgep->tx_ring;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs for (slot = 0; slot < RGE_SEND_SLOTS; slot++) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs bdp->host_buf_addr =
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs RGE_BSWAP_32(ssbdp->pbuf.cookie.dmac_laddress);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs bdp->host_buf_addr_hi =
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs RGE_BSWAP_32(ssbdp->pbuf.cookie.dmac_laddress >> 32);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /* last BD in Tx ring */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (slot == (RGE_SEND_SLOTS - 1))
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs bdp->flags_len = RGE_BSWAP_32(BD_FLAG_EOR);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs ssbdp++;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs bdp++;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DMA_SYNC(rgep->tx_desc, DDI_DMA_SYNC_FORDEV);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->tx_next = 0;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->tc_next = 0;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->tc_tail = 0;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->tx_flow = 0;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->tx_free = RGE_SEND_SLOTS;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic void
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_reinit_recv_ring(rge_t *rgep)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_bd_t *bdp;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs sw_rbd_t *srbdp;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_area_t *pbuf;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs uint32_t slot;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * re-init receive ring
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DMA_ZERO(rgep->rx_desc);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs srbdp = rgep->sw_rbds;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs bdp = rgep->rx_ring;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs for (slot = 0; slot < RGE_RECV_SLOTS; slot++) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs pbuf = &srbdp->rx_buf->pbuf;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs bdp->host_buf_addr =
aa81749390e332985277568edab1ee6132326b42gs RGE_BSWAP_32(pbuf->cookie.dmac_laddress + rgep->head_room);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs bdp->host_buf_addr_hi =
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs RGE_BSWAP_32(pbuf->cookie.dmac_laddress >> 32);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs bdp->flags_len = RGE_BSWAP_32(BD_FLAG_HW_OWN |
aa81749390e332985277568edab1ee6132326b42gs (rgep->rxbuf_size - rgep->head_room));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /* last BD in Tx ring */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (slot == (RGE_RECV_SLOTS - 1))
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs bdp->flags_len |= RGE_BSWAP_32(BD_FLAG_EOR);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs srbdp++;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs bdp++;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DMA_SYNC(rgep->rx_desc, DDI_DMA_SYNC_FORDEV);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->watchdog = 0;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->rx_next = 0;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic void
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_reinit_buf_ring(rge_t *rgep)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs if (rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY)
aa81749390e332985277568edab1ee6132326b42gs return;
aa81749390e332985277568edab1ee6132326b42gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
aa81749390e332985277568edab1ee6132326b42gs * If all the up-sending buffers haven't been returned to driver,
aa81749390e332985277568edab1ee6132326b42gs * use bcopy() only in rx process.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (rgep->rx_free != RGE_BUF_SLOTS)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->rx_bcopy = B_TRUE;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic void
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_reinit_rings(rge_t *rgep)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_reinit_send_ring(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_reinit_recv_ring(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_reinit_buf_ring(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic void
aa81749390e332985277568edab1ee6132326b42gsrge_fini_send_ring(rge_t *rgep)
aa81749390e332985277568edab1ee6132326b42gs{
aa81749390e332985277568edab1ee6132326b42gs sw_sbd_t *ssbdp;
aa81749390e332985277568edab1ee6132326b42gs uint32_t slot;
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs ssbdp = rgep->sw_sbds;
aa81749390e332985277568edab1ee6132326b42gs for (slot = 0; slot < RGE_SEND_SLOTS; ++slot) {
aa81749390e332985277568edab1ee6132326b42gs rge_free_dma_mem(&ssbdp->pbuf);
aa81749390e332985277568edab1ee6132326b42gs ssbdp++;
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs kmem_free(rgep->sw_sbds, RGE_SEND_SLOTS * sizeof (sw_sbd_t));
aa81749390e332985277568edab1ee6132326b42gs rgep->sw_sbds = NULL;
aa81749390e332985277568edab1ee6132326b42gs}
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gsstatic void
aa81749390e332985277568edab1ee6132326b42gsrge_fini_recv_ring(rge_t *rgep)
aa81749390e332985277568edab1ee6132326b42gs{
aa81749390e332985277568edab1ee6132326b42gs sw_rbd_t *srbdp;
aa81749390e332985277568edab1ee6132326b42gs uint32_t slot;
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs srbdp = rgep->sw_rbds;
aa81749390e332985277568edab1ee6132326b42gs for (slot = 0; slot < RGE_RECV_SLOTS; ++srbdp, ++slot) {
aa81749390e332985277568edab1ee6132326b42gs if (srbdp->rx_buf) {
aa81749390e332985277568edab1ee6132326b42gs if (srbdp->rx_buf->mp != NULL) {
aa81749390e332985277568edab1ee6132326b42gs freemsg(srbdp->rx_buf->mp);
aa81749390e332985277568edab1ee6132326b42gs srbdp->rx_buf->mp = NULL;
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs rge_free_dma_mem(&srbdp->rx_buf->pbuf);
aa81749390e332985277568edab1ee6132326b42gs kmem_free(srbdp->rx_buf, sizeof (dma_buf_t));
aa81749390e332985277568edab1ee6132326b42gs srbdp->rx_buf = NULL;
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs kmem_free(rgep->sw_rbds, RGE_RECV_SLOTS * sizeof (sw_rbd_t));
aa81749390e332985277568edab1ee6132326b42gs rgep->sw_rbds = NULL;
aa81749390e332985277568edab1ee6132326b42gs}
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gsstatic void
aa81749390e332985277568edab1ee6132326b42gsrge_fini_buf_ring(rge_t *rgep)
aa81749390e332985277568edab1ee6132326b42gs{
aa81749390e332985277568edab1ee6132326b42gs sw_rbd_t *srbdp;
aa81749390e332985277568edab1ee6132326b42gs uint32_t slot;
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs if (rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY)
aa81749390e332985277568edab1ee6132326b42gs return;
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs ASSERT(rgep->rx_free == RGE_BUF_SLOTS);
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs srbdp = rgep->free_srbds;
aa81749390e332985277568edab1ee6132326b42gs for (slot = 0; slot < RGE_BUF_SLOTS; ++srbdp, ++slot) {
aa81749390e332985277568edab1ee6132326b42gs if (srbdp->rx_buf != NULL) {
aa81749390e332985277568edab1ee6132326b42gs if (srbdp->rx_buf->mp != NULL) {
aa81749390e332985277568edab1ee6132326b42gs freemsg(srbdp->rx_buf->mp);
aa81749390e332985277568edab1ee6132326b42gs srbdp->rx_buf->mp = NULL;
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs rge_free_dma_mem(&srbdp->rx_buf->pbuf);
aa81749390e332985277568edab1ee6132326b42gs kmem_free(srbdp->rx_buf, sizeof (dma_buf_t));
aa81749390e332985277568edab1ee6132326b42gs srbdp->rx_buf = NULL;
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs kmem_free(rgep->free_srbds, RGE_BUF_SLOTS * sizeof (sw_rbd_t));
aa81749390e332985277568edab1ee6132326b42gs rgep->free_srbds = NULL;
aa81749390e332985277568edab1ee6132326b42gs}
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gsstatic void
aa81749390e332985277568edab1ee6132326b42gsrge_fini_rings(rge_t *rgep)
aa81749390e332985277568edab1ee6132326b42gs{
aa81749390e332985277568edab1ee6132326b42gs rge_fini_send_ring(rgep);
aa81749390e332985277568edab1ee6132326b42gs rge_fini_recv_ring(rgep);
aa81749390e332985277568edab1ee6132326b42gs rge_fini_buf_ring(rgep);
aa81749390e332985277568edab1ee6132326b42gs}
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gsstatic int
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_init_send_ring(rge_t *rgep)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs uint32_t slot;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs sw_sbd_t *ssbdp;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_area_t *pbuf;
aa81749390e332985277568edab1ee6132326b42gs dma_area_t desc;
aa81749390e332985277568edab1ee6132326b42gs int err;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Allocate the array of s/w Tx Buffer Descriptors
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs ssbdp = kmem_zalloc(RGE_SEND_SLOTS*sizeof (*ssbdp), KM_SLEEP);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->sw_sbds = ssbdp;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Init send ring
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->tx_desc = rgep->dma_area_txdesc;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DMA_ZERO(rgep->tx_desc);
aa81749390e332985277568edab1ee6132326b42gs rgep->tx_ring = rgep->tx_desc.mem_va;
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs desc = rgep->tx_desc;
aa81749390e332985277568edab1ee6132326b42gs for (slot = 0; slot < RGE_SEND_SLOTS; slot++) {
aa81749390e332985277568edab1ee6132326b42gs rge_slice_chunk(&ssbdp->desc, &desc, 1, sizeof (rge_bd_t));
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs /*
aa81749390e332985277568edab1ee6132326b42gs * Allocate memory & handle for Tx buffers
aa81749390e332985277568edab1ee6132326b42gs */
aa81749390e332985277568edab1ee6132326b42gs pbuf = &ssbdp->pbuf;
aa81749390e332985277568edab1ee6132326b42gs err = rge_alloc_dma_mem(rgep, rgep->txbuf_size,
aa81749390e332985277568edab1ee6132326b42gs &dma_attr_buf, &rge_buf_accattr,
aa81749390e332985277568edab1ee6132326b42gs DDI_DMA_WRITE | DDI_DMA_STREAMING, pbuf);
aa81749390e332985277568edab1ee6132326b42gs if (err != DDI_SUCCESS) {
aa81749390e332985277568edab1ee6132326b42gs rge_error(rgep,
aa81749390e332985277568edab1ee6132326b42gs "rge_init_send_ring: alloc tx buffer failed");
aa81749390e332985277568edab1ee6132326b42gs rge_fini_send_ring(rgep);
aa81749390e332985277568edab1ee6132326b42gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
aa81749390e332985277568edab1ee6132326b42gs ssbdp++;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
aa81749390e332985277568edab1ee6132326b42gs ASSERT(desc.alength == 0);
aa81749390e332985277568edab1ee6132326b42gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DMA_SYNC(rgep->tx_desc, DDI_DMA_SYNC_FORDEV);
aa81749390e332985277568edab1ee6132326b42gs return (DDI_SUCCESS);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic int
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_init_recv_ring(rge_t *rgep)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs uint32_t slot;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs sw_rbd_t *srbdp;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_buf_t *rx_buf;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_area_t *pbuf;
aa81749390e332985277568edab1ee6132326b42gs int err;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Allocate the array of s/w Rx Buffer Descriptors
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs srbdp = kmem_zalloc(RGE_RECV_SLOTS*sizeof (*srbdp), KM_SLEEP);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->sw_rbds = srbdp;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Init receive ring
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->rx_next = 0;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->rx_desc = rgep->dma_area_rxdesc;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DMA_ZERO(rgep->rx_desc);
aa81749390e332985277568edab1ee6132326b42gs rgep->rx_ring = rgep->rx_desc.mem_va;
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs for (slot = 0; slot < RGE_RECV_SLOTS; slot++) {
aa81749390e332985277568edab1ee6132326b42gs srbdp->rx_buf = rx_buf =
aa81749390e332985277568edab1ee6132326b42gs kmem_zalloc(sizeof (dma_buf_t), KM_SLEEP);
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs /*
aa81749390e332985277568edab1ee6132326b42gs * Allocate memory & handle for Rx buffers
aa81749390e332985277568edab1ee6132326b42gs */
aa81749390e332985277568edab1ee6132326b42gs pbuf = &rx_buf->pbuf;
aa81749390e332985277568edab1ee6132326b42gs err = rge_alloc_dma_mem(rgep, rgep->rxbuf_size,
aa81749390e332985277568edab1ee6132326b42gs &dma_attr_buf, &rge_buf_accattr,
aa81749390e332985277568edab1ee6132326b42gs DDI_DMA_READ | DDI_DMA_STREAMING, pbuf);
aa81749390e332985277568edab1ee6132326b42gs if (err != DDI_SUCCESS) {
aa81749390e332985277568edab1ee6132326b42gs rge_fini_recv_ring(rgep);
aa81749390e332985277568edab1ee6132326b42gs rge_error(rgep,
aa81749390e332985277568edab1ee6132326b42gs "rge_init_recv_ring: alloc rx buffer failed");
aa81749390e332985277568edab1ee6132326b42gs return (DDI_FAILURE);
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs pbuf->alength -= rgep->head_room;
aa81749390e332985277568edab1ee6132326b42gs pbuf->offset += rgep->head_room;
aa81749390e332985277568edab1ee6132326b42gs if (!(rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY)) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rx_buf->rx_recycle.free_func = rge_rx_recycle;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rx_buf->rx_recycle.free_arg = (caddr_t)rx_buf;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rx_buf->private = (caddr_t)rgep;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rx_buf->mp = desballoc(DMA_VPTR(rx_buf->pbuf),
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->rxbuf_size, 0, &rx_buf->rx_recycle);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (rx_buf->mp == NULL) {
aa81749390e332985277568edab1ee6132326b42gs rge_fini_recv_ring(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_problem(rgep,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs "rge_init_recv_ring: desballoc() failed");
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
aa81749390e332985277568edab1ee6132326b42gs srbdp++;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DMA_SYNC(rgep->rx_desc, DDI_DMA_SYNC_FORDEV);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_SUCCESS);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic int
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_init_buf_ring(rge_t *rgep)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs uint32_t slot;
aa81749390e332985277568edab1ee6132326b42gs sw_rbd_t *free_srbdp;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_buf_t *rx_buf;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs dma_area_t *pbuf;
aa81749390e332985277568edab1ee6132326b42gs int err;
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs if (rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY) {
aa81749390e332985277568edab1ee6132326b42gs rgep->rx_bcopy = B_TRUE;
aa81749390e332985277568edab1ee6132326b42gs return (DDI_SUCCESS);
aa81749390e332985277568edab1ee6132326b42gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Allocate the array of s/w free Buffer Descriptors
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
aa81749390e332985277568edab1ee6132326b42gs free_srbdp = kmem_zalloc(RGE_BUF_SLOTS*sizeof (*free_srbdp), KM_SLEEP);
aa81749390e332985277568edab1ee6132326b42gs rgep->free_srbds = free_srbdp;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Init free buffer ring
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->rc_next = 0;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->rf_next = 0;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->rx_bcopy = B_FALSE;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->rx_free = RGE_BUF_SLOTS;
aa81749390e332985277568edab1ee6132326b42gs for (slot = 0; slot < RGE_BUF_SLOTS; slot++) {
aa81749390e332985277568edab1ee6132326b42gs free_srbdp->rx_buf = rx_buf =
aa81749390e332985277568edab1ee6132326b42gs kmem_zalloc(sizeof (dma_buf_t), KM_SLEEP);
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs /*
aa81749390e332985277568edab1ee6132326b42gs * Allocate memory & handle for free Rx buffers
aa81749390e332985277568edab1ee6132326b42gs */
aa81749390e332985277568edab1ee6132326b42gs pbuf = &rx_buf->pbuf;
aa81749390e332985277568edab1ee6132326b42gs err = rge_alloc_dma_mem(rgep, rgep->rxbuf_size,
aa81749390e332985277568edab1ee6132326b42gs &dma_attr_buf, &rge_buf_accattr,
aa81749390e332985277568edab1ee6132326b42gs DDI_DMA_READ | DDI_DMA_STREAMING, pbuf);
aa81749390e332985277568edab1ee6132326b42gs if (err != DDI_SUCCESS) {
aa81749390e332985277568edab1ee6132326b42gs rge_fini_buf_ring(rgep);
aa81749390e332985277568edab1ee6132326b42gs rge_error(rgep,
aa81749390e332985277568edab1ee6132326b42gs "rge_init_buf_ring: alloc rx free buffer failed");
aa81749390e332985277568edab1ee6132326b42gs return (DDI_FAILURE);
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs pbuf->alength -= rgep->head_room;
aa81749390e332985277568edab1ee6132326b42gs pbuf->offset += rgep->head_room;
aa81749390e332985277568edab1ee6132326b42gs rx_buf->rx_recycle.free_func = rge_rx_recycle;
aa81749390e332985277568edab1ee6132326b42gs rx_buf->rx_recycle.free_arg = (caddr_t)rx_buf;
aa81749390e332985277568edab1ee6132326b42gs rx_buf->private = (caddr_t)rgep;
aa81749390e332985277568edab1ee6132326b42gs rx_buf->mp = desballoc(DMA_VPTR(rx_buf->pbuf),
aa81749390e332985277568edab1ee6132326b42gs rgep->rxbuf_size, 0, &rx_buf->rx_recycle);
aa81749390e332985277568edab1ee6132326b42gs if (rx_buf->mp == NULL) {
aa81749390e332985277568edab1ee6132326b42gs rge_fini_buf_ring(rgep);
aa81749390e332985277568edab1ee6132326b42gs rge_problem(rgep,
aa81749390e332985277568edab1ee6132326b42gs "rge_init_buf_ring: desballoc() failed");
aa81749390e332985277568edab1ee6132326b42gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
aa81749390e332985277568edab1ee6132326b42gs free_srbdp++;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_SUCCESS);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic int
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_init_rings(rge_t *rgep)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs int err;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
aa81749390e332985277568edab1ee6132326b42gs err = rge_init_send_ring(rgep);
aa81749390e332985277568edab1ee6132326b42gs if (err != DDI_SUCCESS)
aa81749390e332985277568edab1ee6132326b42gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
aa81749390e332985277568edab1ee6132326b42gs err = rge_init_recv_ring(rgep);
aa81749390e332985277568edab1ee6132326b42gs if (err != DDI_SUCCESS) {
aa81749390e332985277568edab1ee6132326b42gs rge_fini_send_ring(rgep);
aa81749390e332985277568edab1ee6132326b42gs return (DDI_FAILURE);
aa81749390e332985277568edab1ee6132326b42gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
aa81749390e332985277568edab1ee6132326b42gs err = rge_init_buf_ring(rgep);
aa81749390e332985277568edab1ee6132326b42gs if (err != DDI_SUCCESS) {
aa81749390e332985277568edab1ee6132326b42gs rge_fini_send_ring(rgep);
aa81749390e332985277568edab1ee6132326b42gs rge_fini_recv_ring(rgep);
aa81749390e332985277568edab1ee6132326b42gs return (DDI_FAILURE);
aa81749390e332985277568edab1ee6132326b42gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
aa81749390e332985277568edab1ee6132326b42gs return (DDI_SUCCESS);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * ========== Internal state management entry points ==========
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs#undef RGE_DBG
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs#define RGE_DBG RGE_DBG_NEMO /* debug flag for this code */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * These routines provide all the functionality required by the
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * corresponding MAC layer entry points, but don't update the
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * MAC state so they can be called internally without disturbing
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * our record of what NEMO thinks we should be doing ...
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * rge_reset() -- reset h/w & rings to initial state
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic void
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_reset(rge_t *rgep)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs ASSERT(mutex_owned(rgep->genlock));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Grab all the other mutexes in the world (this should
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * ensure no other threads are manipulating driver state)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_enter(rgep->rx_lock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_enter(rgep->rc_lock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rw_enter(rgep->errlock, RW_WRITER);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs (void) rge_chip_reset(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_reinit_rings(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_chip_init(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Free the world ...
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rw_exit(rgep->errlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_exit(rgep->rc_lock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_exit(rgep->rx_lock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
22dc213396fdd861beeb93f8cb17eaaeb9960cf4mx rgep->stats.rpackets = 0;
22dc213396fdd861beeb93f8cb17eaaeb9960cf4mx rgep->stats.rbytes = 0;
22dc213396fdd861beeb93f8cb17eaaeb9960cf4mx rgep->stats.opackets = 0;
22dc213396fdd861beeb93f8cb17eaaeb9960cf4mx rgep->stats.obytes = 0;
22dc213396fdd861beeb93f8cb17eaaeb9960cf4mx rgep->stats.tx_pre_ismax = B_FALSE;
22dc213396fdd861beeb93f8cb17eaaeb9960cf4mx rgep->stats.tx_cur_ismax = B_FALSE;
22dc213396fdd861beeb93f8cb17eaaeb9960cf4mx
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs RGE_DEBUG(("rge_reset($%p) done", (void *)rgep));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * rge_stop() -- stop processing, don't reset h/w or rings
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic void
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_stop(rge_t *rgep)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs ASSERT(mutex_owned(rgep->genlock));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_chip_stop(rgep, B_FALSE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs RGE_DEBUG(("rge_stop($%p) done", (void *)rgep));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * rge_start() -- start transmitting/receiving
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic void
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_start(rge_t *rgep)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs ASSERT(mutex_owned(rgep->genlock));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Start chip processing, including enabling interrupts
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_chip_start(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->watchdog = 0;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * rge_restart - restart transmitting/receiving after error or suspend
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsvoid
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_restart(rge_t *rgep)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs uint32_t i;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs ASSERT(mutex_owned(rgep->genlock));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Wait for posted buffer to be freed...
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (!rgep->rx_bcopy) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs for (i = 0; i < RXBUFF_FREE_LOOP; i++) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (rgep->rx_free == RGE_BUF_SLOTS)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs break;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs drv_usecwait(1000);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs RGE_DEBUG(("rge_restart: waiting for rx buf free..."));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_reset(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->stats.chip_reset++;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (rgep->rge_mac_state == RGE_MAC_STARTED) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_start(rgep);
aa81749390e332985277568edab1ee6132326b42gs rgep->resched_needed = B_TRUE;
aa81749390e332985277568edab1ee6132326b42gs (void) ddi_intr_trigger_softint(rgep->resched_hdl, NULL);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * ========== Nemo-required management entry points ==========
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs#undef RGE_DBG
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs#define RGE_DBG RGE_DBG_NEMO /* debug flag for this code */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * rge_m_stop() -- stop transmitting/receiving
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic void
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_m_stop(void *arg)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_t *rgep = arg; /* private device info */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs uint32_t i;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Just stop processing, then record new MAC state
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_enter(rgep->genlock);
343c26163d86b7f3b861ae03b20226fecee1ab99mx if (rgep->suspended) {
343c26163d86b7f3b861ae03b20226fecee1ab99mx ASSERT(rgep->rge_mac_state == RGE_MAC_STOPPED);
343c26163d86b7f3b861ae03b20226fecee1ab99mx mutex_exit(rgep->genlock);
343c26163d86b7f3b861ae03b20226fecee1ab99mx return;
343c26163d86b7f3b861ae03b20226fecee1ab99mx }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_stop(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Wait for posted buffer to be freed...
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (!rgep->rx_bcopy) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs for (i = 0; i < RXBUFF_FREE_LOOP; i++) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (rgep->rx_free == RGE_BUF_SLOTS)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs break;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs drv_usecwait(1000);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs RGE_DEBUG(("rge_m_stop: waiting for rx buf free..."));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->rge_mac_state = RGE_MAC_STOPPED;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs RGE_DEBUG(("rge_m_stop($%p) done", arg));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_exit(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * rge_m_start() -- start transmitting/receiving
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic int
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_m_start(void *arg)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_t *rgep = arg; /* private device info */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_enter(rgep->genlock);
343c26163d86b7f3b861ae03b20226fecee1ab99mx if (rgep->suspended) {
343c26163d86b7f3b861ae03b20226fecee1ab99mx mutex_exit(rgep->genlock);
343c26163d86b7f3b861ae03b20226fecee1ab99mx return (DDI_FAILURE);
343c26163d86b7f3b861ae03b20226fecee1ab99mx }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Clear hw/sw statistics
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs DMA_ZERO(rgep->dma_area_stats);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs bzero(&rgep->stats, sizeof (rge_stats_t));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Start processing and record new MAC state
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_reset(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_start(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->rge_mac_state = RGE_MAC_STARTED;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs RGE_DEBUG(("rge_m_start($%p) done", arg));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_exit(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (0);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * rge_m_unicst_set() -- set the physical network address
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic int
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_m_unicst(void *arg, const uint8_t *macaddr)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_t *rgep = arg; /* private device info */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Remember the new current address in the driver state
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Sync the chip's idea of the address too ...
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_enter(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs bcopy(macaddr, rgep->netaddr, ETHERADDRL);
343c26163d86b7f3b861ae03b20226fecee1ab99mx
343c26163d86b7f3b861ae03b20226fecee1ab99mx if (rgep->suspended) {
343c26163d86b7f3b861ae03b20226fecee1ab99mx mutex_exit(rgep->genlock);
343c26163d86b7f3b861ae03b20226fecee1ab99mx return (DDI_SUCCESS);
343c26163d86b7f3b861ae03b20226fecee1ab99mx }
343c26163d86b7f3b861ae03b20226fecee1ab99mx
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_chip_sync(rgep, RGE_SET_MAC);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_exit(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (0);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Compute the index of the required bit in the multicast hash map.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * This must mirror the way the hardware actually does it!
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic uint32_t
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_hash_index(const uint8_t *mca)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
aa81749390e332985277568edab1ee6132326b42gs uint32_t crc = (uint32_t)RGE_HASH_CRC;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs uint32_t const POLY = RGE_HASH_POLY;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs uint32_t msb;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs int bytes;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs uchar_t currentbyte;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs uint32_t index;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs int bit;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs for (bytes = 0; bytes < ETHERADDRL; bytes++) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs currentbyte = mca[bytes];
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs for (bit = 0; bit < 8; bit++) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs msb = crc >> 31;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs crc <<= 1;
aa81749390e332985277568edab1ee6132326b42gs if (msb ^ (currentbyte & 1))
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs crc ^= POLY;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs currentbyte >>= 1;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs index = crc >> 26;
aa81749390e332985277568edab1ee6132326b42gs /* the index value is between 0 and 63(0x3f) */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (index);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * rge_m_multicst_add() -- enable/disable a multicast address
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic int
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_t *rgep = arg; /* private device info */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs struct ether_addr *addr;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs uint32_t index;
aa81749390e332985277568edab1ee6132326b42gs uint32_t reg;
aa81749390e332985277568edab1ee6132326b42gs uint8_t *hashp;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_enter(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs hashp = rgep->mcast_hash;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs addr = (struct ether_addr *)mca;
aa81749390e332985277568edab1ee6132326b42gs /*
aa81749390e332985277568edab1ee6132326b42gs * Calculate the Multicast address hash index value
aa81749390e332985277568edab1ee6132326b42gs * Normally, the position of MAR0-MAR7 is
aa81749390e332985277568edab1ee6132326b42gs * MAR0: offset 0x08, ..., MAR7: offset 0x0F.
aa81749390e332985277568edab1ee6132326b42gs *
aa81749390e332985277568edab1ee6132326b42gs * For pcie chipset, the position of MAR0-MAR7 is
aa81749390e332985277568edab1ee6132326b42gs * different from others:
aa81749390e332985277568edab1ee6132326b42gs * MAR0: offset 0x0F, ..., MAR7: offset 0x08.
aa81749390e332985277568edab1ee6132326b42gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs index = rge_hash_index(addr->ether_addr_octet);
aa81749390e332985277568edab1ee6132326b42gs if (rgep->chipid.is_pcie)
aa81749390e332985277568edab1ee6132326b42gs reg = (~(index / RGE_MCAST_NUM)) & 0x7;
aa81749390e332985277568edab1ee6132326b42gs else
aa81749390e332985277568edab1ee6132326b42gs reg = index / RGE_MCAST_NUM;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (add) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (rgep->mcast_refs[index]++) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_exit(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (0);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
aa81749390e332985277568edab1ee6132326b42gs hashp[reg] |= 1 << (index % RGE_MCAST_NUM);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs } else {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (--rgep->mcast_refs[index]) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_exit(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (0);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
aa81749390e332985277568edab1ee6132326b42gs hashp[reg] &= ~ (1 << (index % RGE_MCAST_NUM));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
343c26163d86b7f3b861ae03b20226fecee1ab99mx if (rgep->suspended) {
343c26163d86b7f3b861ae03b20226fecee1ab99mx mutex_exit(rgep->genlock);
343c26163d86b7f3b861ae03b20226fecee1ab99mx return (DDI_SUCCESS);
343c26163d86b7f3b861ae03b20226fecee1ab99mx }
343c26163d86b7f3b861ae03b20226fecee1ab99mx
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Set multicast register
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_chip_sync(rgep, RGE_SET_MUL);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_exit(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (0);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * rge_m_promisc() -- set or reset promiscuous mode on the board
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs *
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Program the hardware to enable/disable promiscuous and/or
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * receive-all-multicast modes.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic int
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_m_promisc(void *arg, boolean_t on)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_t *rgep = arg;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Store MAC layer specified mode and pass to chip layer to update h/w
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_enter(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (rgep->promisc == on) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_exit(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (0);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->promisc = on;
343c26163d86b7f3b861ae03b20226fecee1ab99mx
343c26163d86b7f3b861ae03b20226fecee1ab99mx if (rgep->suspended) {
343c26163d86b7f3b861ae03b20226fecee1ab99mx mutex_exit(rgep->genlock);
343c26163d86b7f3b861ae03b20226fecee1ab99mx return (DDI_SUCCESS);
343c26163d86b7f3b861ae03b20226fecee1ab99mx }
343c26163d86b7f3b861ae03b20226fecee1ab99mx
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_chip_sync(rgep, RGE_SET_PROMISC);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs RGE_DEBUG(("rge_m_promisc_set($%p) done", arg));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_exit(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (0);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Loopback ioctl code
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic lb_property_t loopmodes[] = {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs { normal, "normal", RGE_LOOP_NONE },
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs { internal, "PHY", RGE_LOOP_INTERNAL_PHY },
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs { internal, "MAC", RGE_LOOP_INTERNAL_MAC }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs};
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic enum ioc_reply
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_set_loop_mode(rge_t *rgep, uint32_t mode)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * If the mode isn't being changed, there's nothing to do ...
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (mode == rgep->param_loop_mode)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (IOC_ACK);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Validate the requested mode and prepare a suitable message
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * to explain the link down/up cycle that the change will
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * probably induce ...
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs switch (mode) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs default:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (IOC_INVAL);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_LOOP_NONE:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_LOOP_INTERNAL_PHY:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_LOOP_INTERNAL_MAC:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs break;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * All OK; tell the caller to reprogram
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * the PHY and/or MAC for the new mode ...
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->param_loop_mode = mode;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (IOC_RESTART_ACK);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic enum ioc_reply
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_loop_ioctl(rge_t *rgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs lb_info_sz_t *lbsp;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs lb_property_t *lbpp;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs uint32_t *lbmp;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs int cmd;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs _NOTE(ARGUNUSED(wq))
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Validate format of ioctl
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (mp->b_cont == NULL)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (IOC_INVAL);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs cmd = iocp->ioc_cmd;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs switch (cmd) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs default:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /* NOTREACHED */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_error(rgep, "rge_loop_ioctl: invalid cmd 0x%x", cmd);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (IOC_INVAL);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case LB_GET_INFO_SIZE:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (iocp->ioc_count != sizeof (lb_info_sz_t))
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (IOC_INVAL);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs lbsp = (lb_info_sz_t *)mp->b_cont->b_rptr;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs *lbsp = sizeof (loopmodes);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (IOC_REPLY);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case LB_GET_INFO:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (iocp->ioc_count != sizeof (loopmodes))
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (IOC_INVAL);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs lbpp = (lb_property_t *)mp->b_cont->b_rptr;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs bcopy(loopmodes, lbpp, sizeof (loopmodes));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (IOC_REPLY);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case LB_GET_MODE:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (iocp->ioc_count != sizeof (uint32_t))
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (IOC_INVAL);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs lbmp = (uint32_t *)mp->b_cont->b_rptr;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs *lbmp = rgep->param_loop_mode;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (IOC_REPLY);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case LB_SET_MODE:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (iocp->ioc_count != sizeof (uint32_t))
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (IOC_INVAL);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs lbmp = (uint32_t *)mp->b_cont->b_rptr;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (rge_set_loop_mode(rgep, *lbmp));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Specific rge IOCTLs, the MAC layer handles the generic ones.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic void
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_t *rgep = arg;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs struct iocblk *iocp;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs enum ioc_reply status;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs boolean_t need_privilege;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs int err;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs int cmd;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
343c26163d86b7f3b861ae03b20226fecee1ab99mx /*
343c26163d86b7f3b861ae03b20226fecee1ab99mx * If suspended, we might actually be able to do some of
343c26163d86b7f3b861ae03b20226fecee1ab99mx * these ioctls, but it is harder to make sure they occur
343c26163d86b7f3b861ae03b20226fecee1ab99mx * without actually putting the hardware in an undesireable
343c26163d86b7f3b861ae03b20226fecee1ab99mx * state. So just NAK it.
343c26163d86b7f3b861ae03b20226fecee1ab99mx */
343c26163d86b7f3b861ae03b20226fecee1ab99mx mutex_enter(rgep->genlock);
343c26163d86b7f3b861ae03b20226fecee1ab99mx if (rgep->suspended) {
343c26163d86b7f3b861ae03b20226fecee1ab99mx miocnak(wq, mp, 0, EINVAL);
343c26163d86b7f3b861ae03b20226fecee1ab99mx mutex_exit(rgep->genlock);
343c26163d86b7f3b861ae03b20226fecee1ab99mx return;
343c26163d86b7f3b861ae03b20226fecee1ab99mx }
343c26163d86b7f3b861ae03b20226fecee1ab99mx mutex_exit(rgep->genlock);
343c26163d86b7f3b861ae03b20226fecee1ab99mx
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Validate the command before bothering with the mutex ...
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs iocp = (struct iocblk *)mp->b_rptr;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs iocp->ioc_error = 0;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs need_privilege = B_TRUE;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs cmd = iocp->ioc_cmd;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs switch (cmd) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs default:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs miocnak(wq, mp, 0, EINVAL);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_MII_READ:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_MII_WRITE:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_DIAG:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_PEEK:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_POKE:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_PHY_RESET:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_SOFT_RESET:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_HARD_RESET:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs break;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case LB_GET_INFO_SIZE:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case LB_GET_INFO:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case LB_GET_MODE:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs need_privilege = B_FALSE;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /* FALLTHRU */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case LB_SET_MODE:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs break;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case ND_GET:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs need_privilege = B_FALSE;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /* FALLTHRU */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case ND_SET:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs break;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (need_privilege) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
aa81749390e332985277568edab1ee6132326b42gs * Check for specific net_config privilege
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
aa81749390e332985277568edab1ee6132326b42gs err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (err != 0) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs miocnak(wq, mp, 0, err);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_enter(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs switch (cmd) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs default:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs _NOTE(NOTREACHED)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs status = IOC_INVAL;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs break;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_MII_READ:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_MII_WRITE:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_DIAG:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_PEEK:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_POKE:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_PHY_RESET:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_SOFT_RESET:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case RGE_HARD_RESET:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs status = rge_chip_ioctl(rgep, wq, mp, iocp);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs break;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case LB_GET_INFO_SIZE:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case LB_GET_INFO:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case LB_GET_MODE:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case LB_SET_MODE:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs status = rge_loop_ioctl(rgep, wq, mp, iocp);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs break;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case ND_GET:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case ND_SET:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs status = rge_nd_ioctl(rgep, wq, mp, iocp);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs break;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Do we need to reprogram the PHY and/or the MAC?
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Do it now, while we still have the mutex.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs *
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Note: update the PHY first, 'cos it controls the
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * speed/duplex parameters that the MAC code uses.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs switch (status) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case IOC_RESTART_REPLY:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case IOC_RESTART_ACK:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_phy_update(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs break;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_exit(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Finally, decide how to reply
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs switch (status) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs default:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case IOC_INVAL:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Error, reply with a NAK and EINVAL or the specified error
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs miocnak(wq, mp, 0, iocp->ioc_error == 0 ?
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota EINVAL : iocp->ioc_error);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs break;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case IOC_DONE:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * OK, reply already sent
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs break;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case IOC_RESTART_ACK:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case IOC_ACK:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * OK, reply with an ACK
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs miocack(wq, mp, 0, 0);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs break;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case IOC_RESTART_REPLY:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case IOC_REPLY:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * OK, send prepared reply as ACK or NAK
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mp->b_datap->db_type = iocp->ioc_error == 0 ?
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota M_IOCACK : M_IOCNAK;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs qreply(wq, mp);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs break;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb/* ARGSUSED */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic boolean_t
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebrge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb{
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China rge_t *rgep = arg;
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb switch (cap) {
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case MAC_CAPAB_HCKSUM: {
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb uint32_t *hcksum_txflags = cap_data;
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China switch (rgep->chipid.mac_ver) {
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China case MAC_VER_8169:
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China case MAC_VER_8169S_D:
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China case MAC_VER_8169S_E:
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China case MAC_VER_8169SB:
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China case MAC_VER_8169SC:
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China case MAC_VER_8168:
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China case MAC_VER_8168B_B:
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China case MAC_VER_8168B_C:
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China case MAC_VER_8101E:
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China *hcksum_txflags = HCKSUM_INET_FULL_V4 |
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China HCKSUM_IPHDRCKSUM;
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China break;
5927ab2b3c9b313d37a3417c6a5571fdf191b693KHF case MAC_VER_8168C:
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China case MAC_VER_8101E_B:
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China case MAC_VER_8101E_C:
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China default:
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China *hcksum_txflags = 0;
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China break;
834a2629f6f251c7492f75e808a856b82a27b337yong tan - Sun Microsystems - Beijing China }
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb break;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb }
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb default:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb return (B_FALSE);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb }
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb return (B_TRUE);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb}
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb
aa81749390e332985277568edab1ee6132326b42gs/*
aa81749390e332985277568edab1ee6132326b42gs * ============ Init MSI/Fixed Interrupt routines ==============
aa81749390e332985277568edab1ee6132326b42gs */
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs/*
aa81749390e332985277568edab1ee6132326b42gs * rge_add_intrs:
aa81749390e332985277568edab1ee6132326b42gs *
aa81749390e332985277568edab1ee6132326b42gs * Register FIXED or MSI interrupts.
aa81749390e332985277568edab1ee6132326b42gs */
aa81749390e332985277568edab1ee6132326b42gsstatic int
aa81749390e332985277568edab1ee6132326b42gsrge_add_intrs(rge_t *rgep, int intr_type)
aa81749390e332985277568edab1ee6132326b42gs{
aa81749390e332985277568edab1ee6132326b42gs dev_info_t *dip = rgep->devinfo;
aa81749390e332985277568edab1ee6132326b42gs int avail;
aa81749390e332985277568edab1ee6132326b42gs int actual;
aa81749390e332985277568edab1ee6132326b42gs int intr_size;
aa81749390e332985277568edab1ee6132326b42gs int count;
aa81749390e332985277568edab1ee6132326b42gs int i, j;
aa81749390e332985277568edab1ee6132326b42gs int ret;
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs /* Get number of interrupts */
aa81749390e332985277568edab1ee6132326b42gs ret = ddi_intr_get_nintrs(dip, intr_type, &count);
aa81749390e332985277568edab1ee6132326b42gs if ((ret != DDI_SUCCESS) || (count == 0)) {
aa81749390e332985277568edab1ee6132326b42gs rge_error(rgep, "ddi_intr_get_nintrs() failure, ret: %d, "
aa81749390e332985277568edab1ee6132326b42gs "count: %d", ret, count);
aa81749390e332985277568edab1ee6132326b42gs return (DDI_FAILURE);
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs /* Get number of available interrupts */
aa81749390e332985277568edab1ee6132326b42gs ret = ddi_intr_get_navail(dip, intr_type, &avail);
aa81749390e332985277568edab1ee6132326b42gs if ((ret != DDI_SUCCESS) || (avail == 0)) {
aa81749390e332985277568edab1ee6132326b42gs rge_error(rgep, "ddi_intr_get_navail() failure, "
aa81749390e332985277568edab1ee6132326b42gs "ret: %d, avail: %d\n", ret, avail);
aa81749390e332985277568edab1ee6132326b42gs return (DDI_FAILURE);
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs /* Allocate an array of interrupt handles */
aa81749390e332985277568edab1ee6132326b42gs intr_size = count * sizeof (ddi_intr_handle_t);
aa81749390e332985277568edab1ee6132326b42gs rgep->htable = kmem_alloc(intr_size, KM_SLEEP);
aa81749390e332985277568edab1ee6132326b42gs rgep->intr_rqst = count;
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs /* Call ddi_intr_alloc() */
aa81749390e332985277568edab1ee6132326b42gs ret = ddi_intr_alloc(dip, rgep->htable, intr_type, 0,
aa81749390e332985277568edab1ee6132326b42gs count, &actual, DDI_INTR_ALLOC_NORMAL);
aa81749390e332985277568edab1ee6132326b42gs if (ret != DDI_SUCCESS || actual == 0) {
aa81749390e332985277568edab1ee6132326b42gs rge_error(rgep, "ddi_intr_alloc() failed %d\n", ret);
aa81749390e332985277568edab1ee6132326b42gs kmem_free(rgep->htable, intr_size);
aa81749390e332985277568edab1ee6132326b42gs return (DDI_FAILURE);
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs if (actual < count) {
aa81749390e332985277568edab1ee6132326b42gs rge_log(rgep, "ddi_intr_alloc() Requested: %d, Received: %d\n",
aa81749390e332985277568edab1ee6132326b42gs count, actual);
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs rgep->intr_cnt = actual;
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs /*
aa81749390e332985277568edab1ee6132326b42gs * Get priority for first msi, assume remaining are all the same
aa81749390e332985277568edab1ee6132326b42gs */
aa81749390e332985277568edab1ee6132326b42gs if ((ret = ddi_intr_get_pri(rgep->htable[0], &rgep->intr_pri)) !=
aa81749390e332985277568edab1ee6132326b42gs DDI_SUCCESS) {
aa81749390e332985277568edab1ee6132326b42gs rge_error(rgep, "ddi_intr_get_pri() failed %d\n", ret);
aa81749390e332985277568edab1ee6132326b42gs /* Free already allocated intr */
aa81749390e332985277568edab1ee6132326b42gs for (i = 0; i < actual; i++) {
aa81749390e332985277568edab1ee6132326b42gs (void) ddi_intr_free(rgep->htable[i]);
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs kmem_free(rgep->htable, intr_size);
aa81749390e332985277568edab1ee6132326b42gs return (DDI_FAILURE);
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs /* Test for high level mutex */
aa81749390e332985277568edab1ee6132326b42gs if (rgep->intr_pri >= ddi_intr_get_hilevel_pri()) {
aa81749390e332985277568edab1ee6132326b42gs rge_error(rgep, "rge_add_intrs:"
aa81749390e332985277568edab1ee6132326b42gs "Hi level interrupt not supported");
aa81749390e332985277568edab1ee6132326b42gs for (i = 0; i < actual; i++)
aa81749390e332985277568edab1ee6132326b42gs (void) ddi_intr_free(rgep->htable[i]);
aa81749390e332985277568edab1ee6132326b42gs kmem_free(rgep->htable, intr_size);
aa81749390e332985277568edab1ee6132326b42gs return (DDI_FAILURE);
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs /* Call ddi_intr_add_handler() */
aa81749390e332985277568edab1ee6132326b42gs for (i = 0; i < actual; i++) {
aa81749390e332985277568edab1ee6132326b42gs if ((ret = ddi_intr_add_handler(rgep->htable[i], rge_intr,
aa81749390e332985277568edab1ee6132326b42gs (caddr_t)rgep, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) {
aa81749390e332985277568edab1ee6132326b42gs rge_error(rgep, "ddi_intr_add_handler() "
aa81749390e332985277568edab1ee6132326b42gs "failed %d\n", ret);
aa81749390e332985277568edab1ee6132326b42gs /* Remove already added intr */
aa81749390e332985277568edab1ee6132326b42gs for (j = 0; j < i; j++)
aa81749390e332985277568edab1ee6132326b42gs (void) ddi_intr_remove_handler(rgep->htable[j]);
aa81749390e332985277568edab1ee6132326b42gs /* Free already allocated intr */
aa81749390e332985277568edab1ee6132326b42gs for (i = 0; i < actual; i++) {
aa81749390e332985277568edab1ee6132326b42gs (void) ddi_intr_free(rgep->htable[i]);
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs kmem_free(rgep->htable, intr_size);
aa81749390e332985277568edab1ee6132326b42gs return (DDI_FAILURE);
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs if ((ret = ddi_intr_get_cap(rgep->htable[0], &rgep->intr_cap))
aa81749390e332985277568edab1ee6132326b42gs != DDI_SUCCESS) {
aa81749390e332985277568edab1ee6132326b42gs rge_error(rgep, "ddi_intr_get_cap() failed %d\n", ret);
aa81749390e332985277568edab1ee6132326b42gs for (i = 0; i < actual; i++) {
aa81749390e332985277568edab1ee6132326b42gs (void) ddi_intr_remove_handler(rgep->htable[i]);
aa81749390e332985277568edab1ee6132326b42gs (void) ddi_intr_free(rgep->htable[i]);
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs kmem_free(rgep->htable, intr_size);
aa81749390e332985277568edab1ee6132326b42gs return (DDI_FAILURE);
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs return (DDI_SUCCESS);
aa81749390e332985277568edab1ee6132326b42gs}
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs/*
aa81749390e332985277568edab1ee6132326b42gs * rge_rem_intrs:
aa81749390e332985277568edab1ee6132326b42gs *
aa81749390e332985277568edab1ee6132326b42gs * Unregister FIXED or MSI interrupts
aa81749390e332985277568edab1ee6132326b42gs */
aa81749390e332985277568edab1ee6132326b42gsstatic void
aa81749390e332985277568edab1ee6132326b42gsrge_rem_intrs(rge_t *rgep)
aa81749390e332985277568edab1ee6132326b42gs{
aa81749390e332985277568edab1ee6132326b42gs int i;
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs /* Disable all interrupts */
aa81749390e332985277568edab1ee6132326b42gs if (rgep->intr_cap & DDI_INTR_FLAG_BLOCK) {
aa81749390e332985277568edab1ee6132326b42gs /* Call ddi_intr_block_disable() */
aa81749390e332985277568edab1ee6132326b42gs (void) ddi_intr_block_disable(rgep->htable, rgep->intr_cnt);
aa81749390e332985277568edab1ee6132326b42gs } else {
aa81749390e332985277568edab1ee6132326b42gs for (i = 0; i < rgep->intr_cnt; i++) {
aa81749390e332985277568edab1ee6132326b42gs (void) ddi_intr_disable(rgep->htable[i]);
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs /* Call ddi_intr_remove_handler() */
aa81749390e332985277568edab1ee6132326b42gs for (i = 0; i < rgep->intr_cnt; i++) {
aa81749390e332985277568edab1ee6132326b42gs (void) ddi_intr_remove_handler(rgep->htable[i]);
aa81749390e332985277568edab1ee6132326b42gs (void) ddi_intr_free(rgep->htable[i]);
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs kmem_free(rgep->htable, rgep->intr_rqst * sizeof (ddi_intr_handle_t));
aa81749390e332985277568edab1ee6132326b42gs}
aa81749390e332985277568edab1ee6132326b42gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * ========== Per-instance setup/teardown code ==========
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs#undef RGE_DBG
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs#define RGE_DBG RGE_DBG_INIT /* debug flag for this code */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic void
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_unattach(rge_t *rgep)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Flag that no more activity may be initiated
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->progress &= ~PROGRESS_READY;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->rge_mac_state = RGE_MAC_UNATTACH;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Quiesce the PHY and MAC (leave it reset but still powered).
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Clean up and free all RGE data structures
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota if (rgep->periodic_id != NULL) {
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota ddi_periodic_delete(rgep->periodic_id);
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota rgep->periodic_id = NULL;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (rgep->progress & PROGRESS_KSTATS)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_fini_kstats(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (rgep->progress & PROGRESS_PHY)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs (void) rge_phy_reset(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
aa81749390e332985277568edab1ee6132326b42gs if (rgep->progress & PROGRESS_INIT) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_enter(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs (void) rge_chip_reset(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_exit(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_fini_rings(rgep);
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs if (rgep->progress & PROGRESS_INTR) {
aa81749390e332985277568edab1ee6132326b42gs rge_rem_intrs(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_destroy(rgep->rc_lock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_destroy(rgep->rx_lock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_destroy(rgep->tc_lock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_destroy(rgep->tx_lock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rw_destroy(rgep->errlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_destroy(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (rgep->progress & PROGRESS_FACTOTUM)
aa81749390e332985277568edab1ee6132326b42gs (void) ddi_intr_remove_softint(rgep->factotum_hdl);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (rgep->progress & PROGRESS_RESCHED)
aa81749390e332985277568edab1ee6132326b42gs (void) ddi_intr_remove_softint(rgep->resched_hdl);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (rgep->progress & PROGRESS_NDD)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_nd_cleanup(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
dfc2d53e07384b9eaca5466a2328c88a1ed96f32mx rge_free_bufs(rgep);
dfc2d53e07384b9eaca5466a2328c88a1ed96f32mx
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (rgep->progress & PROGRESS_REGS)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs ddi_regs_map_free(&rgep->io_handle);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (rgep->progress & PROGRESS_CFG)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs pci_config_teardown(&rgep->cfg_handle);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs ddi_remove_minor_node(rgep->devinfo, NULL);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs kmem_free(rgep, sizeof (*rgep));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic int
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_resume(dev_info_t *devinfo)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_t *rgep; /* Our private data */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs chip_id_t *cidp;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs chip_id_t chipid;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep = ddi_get_driver_private(devinfo);
343c26163d86b7f3b861ae03b20226fecee1ab99mx
343c26163d86b7f3b861ae03b20226fecee1ab99mx /*
343c26163d86b7f3b861ae03b20226fecee1ab99mx * If there are state inconsistancies, this is bad. Returning
343c26163d86b7f3b861ae03b20226fecee1ab99mx * DDI_FAILURE here will eventually cause the machine to panic,
343c26163d86b7f3b861ae03b20226fecee1ab99mx * so it is best done here so that there is a possibility of
343c26163d86b7f3b861ae03b20226fecee1ab99mx * debugging the problem.
343c26163d86b7f3b861ae03b20226fecee1ab99mx */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (rgep == NULL)
343c26163d86b7f3b861ae03b20226fecee1ab99mx cmn_err(CE_PANIC,
343c26163d86b7f3b861ae03b20226fecee1ab99mx "rge: ngep returned from ddi_get_driver_private was NULL");
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Refuse to resume if the data structures aren't consistent
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (rgep->devinfo != devinfo)
343c26163d86b7f3b861ae03b20226fecee1ab99mx cmn_err(CE_PANIC,
343c26163d86b7f3b861ae03b20226fecee1ab99mx "rge: passed devinfo not the same as saved devinfo");
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Read chip ID & set up config space command register(s)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Refuse to resume if the chip has changed its identity!
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs cidp = &rgep->chipid;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_chip_cfg_init(rgep, &chipid);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (chipid.vendor != cidp->vendor)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (chipid.device != cidp->device)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (chipid.revision != cidp->revision)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
343c26163d86b7f3b861ae03b20226fecee1ab99mx mutex_enter(rgep->genlock);
343c26163d86b7f3b861ae03b20226fecee1ab99mx
343c26163d86b7f3b861ae03b20226fecee1ab99mx /*
343c26163d86b7f3b861ae03b20226fecee1ab99mx * Only in one case, this conditional branch can be executed: the port
343c26163d86b7f3b861ae03b20226fecee1ab99mx * hasn't been plumbed.
343c26163d86b7f3b861ae03b20226fecee1ab99mx */
343c26163d86b7f3b861ae03b20226fecee1ab99mx if (rgep->suspended == B_FALSE) {
343c26163d86b7f3b861ae03b20226fecee1ab99mx mutex_exit(rgep->genlock);
343c26163d86b7f3b861ae03b20226fecee1ab99mx return (DDI_SUCCESS);
343c26163d86b7f3b861ae03b20226fecee1ab99mx }
343c26163d86b7f3b861ae03b20226fecee1ab99mx rgep->rge_mac_state = RGE_MAC_STARTED;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * All OK, reinitialise h/w & kick off NEMO scheduling
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_restart(rgep);
343c26163d86b7f3b861ae03b20226fecee1ab99mx rgep->suspended = B_FALSE;
343c26163d86b7f3b861ae03b20226fecee1ab99mx
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_exit(rgep->genlock);
343c26163d86b7f3b861ae03b20226fecee1ab99mx
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_SUCCESS);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * attach(9E) -- Attach a device to the system
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs *
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Called once for each board successfully probed.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic int
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_t *rgep; /* Our private data */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb mac_register_t *macp;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs chip_id_t *cidp;
aa81749390e332985277568edab1ee6132326b42gs int intr_types;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs caddr_t regs;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs int instance;
aa81749390e332985277568edab1ee6132326b42gs int i;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs int err;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * we don't support high level interrupts in the driver
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (ddi_intr_hilevel(devinfo, 0) != 0) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs cmn_err(CE_WARN,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs "rge_attach -- unsupported high level interrupt");
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs instance = ddi_get_instance(devinfo);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs RGE_GTRACE(("rge_attach($%p, %d) instance %d",
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota (void *)devinfo, cmd, instance));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs RGE_BRKPT(NULL, "rge_attach");
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs switch (cmd) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs default:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case DDI_RESUME:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (rge_resume(devinfo));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case DDI_ATTACH:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs break;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep = kmem_zalloc(sizeof (*rgep), KM_SLEEP);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs ddi_set_driver_private(devinfo, rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->devinfo = devinfo;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Initialize more fields in RGE private data
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
aa81749390e332985277568edab1ee6132326b42gs rgep->rge_mac_state = RGE_MAC_ATTACH;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->debug = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota DDI_PROP_DONTPASS, debug_propname, rge_debug);
aa81749390e332985277568edab1ee6132326b42gs rgep->default_mtu = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota DDI_PROP_DONTPASS, mtu_propname, ETHERMTU);
aa81749390e332985277568edab1ee6132326b42gs rgep->msi_enable = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota DDI_PROP_DONTPASS, msi_propname, B_TRUE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs (void) snprintf(rgep->ifname, sizeof (rgep->ifname), "%s%d",
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota RGE_DRIVER_NAME, instance);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Map config space registers
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Read chip ID & set up config space command register(s)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs *
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Note: this leaves the chip accessible by Memory Space
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * accesses, but with interrupts and Bus Mastering off.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * This should ensure that nothing untoward will happen
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * if it has been left active by the (net-)bootloader.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * We'll re-enable Bus Mastering once we've reset the chip,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * and allow interrupts only when everything else is set up.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs err = pci_config_setup(devinfo, &rgep->cfg_handle);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (err != DDI_SUCCESS) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_problem(rgep, "pci_config_setup() failed");
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs goto attach_fail;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->progress |= PROGRESS_CFG;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs cidp = &rgep->chipid;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs bzero(cidp, sizeof (*cidp));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_chip_cfg_init(rgep, cidp);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Map operating registers
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
3a84c50f71e0942a55e90913f6b44878d5062621Winson Wang - Sun Microsystems - Beijing China err = ddi_regs_map_setup(devinfo, 2, &regs,
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs 0, 0, &rge_reg_accattr, &rgep->io_handle);
5ca61e50c68a7a60dc35cd76831471faa4974d71Li-Zhen You
5ca61e50c68a7a60dc35cd76831471faa4974d71Li-Zhen You /*
5ca61e50c68a7a60dc35cd76831471faa4974d71Li-Zhen You * MMIO map will fail if the assigned address is bigger than 4G
5ca61e50c68a7a60dc35cd76831471faa4974d71Li-Zhen You * then choose I/O map
5ca61e50c68a7a60dc35cd76831471faa4974d71Li-Zhen You */
5ca61e50c68a7a60dc35cd76831471faa4974d71Li-Zhen You if (err != DDI_SUCCESS) {
5ca61e50c68a7a60dc35cd76831471faa4974d71Li-Zhen You err = ddi_regs_map_setup(devinfo, 1, &regs,
5ca61e50c68a7a60dc35cd76831471faa4974d71Li-Zhen You 0, 0, &rge_reg_accattr, &rgep->io_handle);
5ca61e50c68a7a60dc35cd76831471faa4974d71Li-Zhen You }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (err != DDI_SUCCESS) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_problem(rgep, "ddi_regs_map_setup() failed");
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs goto attach_fail;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->io_regs = regs;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->progress |= PROGRESS_REGS;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Characterise the device, so we know its requirements.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Then allocate the appropriate TX and RX descriptors & buffers.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_chip_ident(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs err = rge_alloc_bufs(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (err != DDI_SUCCESS) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_problem(rgep, "DMA buffer allocation failed");
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs goto attach_fail;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
dfc2d53e07384b9eaca5466a2328c88a1ed96f32mx /*
dfc2d53e07384b9eaca5466a2328c88a1ed96f32mx * Register NDD-tweakable parameters
dfc2d53e07384b9eaca5466a2328c88a1ed96f32mx */
dfc2d53e07384b9eaca5466a2328c88a1ed96f32mx if (rge_nd_init(rgep)) {
dfc2d53e07384b9eaca5466a2328c88a1ed96f32mx rge_problem(rgep, "rge_nd_init() failed");
dfc2d53e07384b9eaca5466a2328c88a1ed96f32mx goto attach_fail;
dfc2d53e07384b9eaca5466a2328c88a1ed96f32mx }
dfc2d53e07384b9eaca5466a2328c88a1ed96f32mx rgep->progress |= PROGRESS_NDD;
dfc2d53e07384b9eaca5466a2328c88a1ed96f32mx
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Add the softint handlers:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs *
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Both of these handlers are used to avoid restrictions on the
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * context and/or mutexes required for some operations. In
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * particular, the hardware interrupt handler and its subfunctions
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * can detect a number of conditions that we don't want to handle
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * in that context or with that set of mutexes held. So, these
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * softints are triggered instead:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs *
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * the <resched> softint is triggered if if we have previously
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * had to refuse to send a packet because of resource shortage
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * (we've run out of transmit buffers), but the send completion
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * interrupt handler has now detected that more buffers have
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * become available.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs *
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * the <factotum> is triggered if the h/w interrupt handler
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * sees the <link state changed> or <error> bits in the status
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * block. It's also triggered periodically to poll the link
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * state, just in case we aren't getting link status change
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * interrupts ...
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
aa81749390e332985277568edab1ee6132326b42gs err = ddi_intr_add_softint(devinfo, &rgep->resched_hdl,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota DDI_INTR_SOFTPRI_MIN, rge_reschedule, (caddr_t)rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (err != DDI_SUCCESS) {
aa81749390e332985277568edab1ee6132326b42gs rge_problem(rgep, "ddi_intr_add_softint() failed");
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs goto attach_fail;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->progress |= PROGRESS_RESCHED;
aa81749390e332985277568edab1ee6132326b42gs err = ddi_intr_add_softint(devinfo, &rgep->factotum_hdl,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota DDI_INTR_SOFTPRI_MIN, rge_chip_factotum, (caddr_t)rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (err != DDI_SUCCESS) {
aa81749390e332985277568edab1ee6132326b42gs rge_problem(rgep, "ddi_intr_add_softint() failed");
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs goto attach_fail;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->progress |= PROGRESS_FACTOTUM;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
aa81749390e332985277568edab1ee6132326b42gs /*
aa81749390e332985277568edab1ee6132326b42gs * Get supported interrupt types
aa81749390e332985277568edab1ee6132326b42gs */
aa81749390e332985277568edab1ee6132326b42gs if (ddi_intr_get_supported_types(devinfo, &intr_types)
aa81749390e332985277568edab1ee6132326b42gs != DDI_SUCCESS) {
aa81749390e332985277568edab1ee6132326b42gs rge_error(rgep, "ddi_intr_get_supported_types failed\n");
aa81749390e332985277568edab1ee6132326b42gs goto attach_fail;
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Add the h/w interrupt handler and initialise mutexes
343c26163d86b7f3b861ae03b20226fecee1ab99mx * RTL8101E is observed to have MSI invalidation issue after S/R.
343c26163d86b7f3b861ae03b20226fecee1ab99mx * So the FIXED interrupt is used instead.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
343c26163d86b7f3b861ae03b20226fecee1ab99mx if (rgep->chipid.mac_ver == MAC_VER_8101E)
343c26163d86b7f3b861ae03b20226fecee1ab99mx rgep->msi_enable = B_FALSE;
aa81749390e332985277568edab1ee6132326b42gs if ((intr_types & DDI_INTR_TYPE_MSI) && rgep->msi_enable) {
aa81749390e332985277568edab1ee6132326b42gs if (rge_add_intrs(rgep, DDI_INTR_TYPE_MSI) != DDI_SUCCESS) {
aa81749390e332985277568edab1ee6132326b42gs rge_error(rgep, "MSI registration failed, "
aa81749390e332985277568edab1ee6132326b42gs "trying FIXED interrupt type\n");
aa81749390e332985277568edab1ee6132326b42gs } else {
aa81749390e332985277568edab1ee6132326b42gs rge_log(rgep, "Using MSI interrupt type\n");
aa81749390e332985277568edab1ee6132326b42gs rgep->intr_type = DDI_INTR_TYPE_MSI;
aa81749390e332985277568edab1ee6132326b42gs rgep->progress |= PROGRESS_INTR;
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs if (!(rgep->progress & PROGRESS_INTR) &&
aa81749390e332985277568edab1ee6132326b42gs (intr_types & DDI_INTR_TYPE_FIXED)) {
aa81749390e332985277568edab1ee6132326b42gs if (rge_add_intrs(rgep, DDI_INTR_TYPE_FIXED) != DDI_SUCCESS) {
aa81749390e332985277568edab1ee6132326b42gs rge_error(rgep, "FIXED interrupt "
aa81749390e332985277568edab1ee6132326b42gs "registration failed\n");
aa81749390e332985277568edab1ee6132326b42gs goto attach_fail;
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs rge_log(rgep, "Using FIXED interrupt type\n");
aa81749390e332985277568edab1ee6132326b42gs rgep->intr_type = DDI_INTR_TYPE_FIXED;
aa81749390e332985277568edab1ee6132326b42gs rgep->progress |= PROGRESS_INTR;
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs if (!(rgep->progress & PROGRESS_INTR)) {
aa81749390e332985277568edab1ee6132326b42gs rge_error(rgep, "No interrupts registered\n");
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs goto attach_fail;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
aa81749390e332985277568edab1ee6132326b42gs mutex_init(rgep->genlock, NULL, MUTEX_DRIVER,
aa81749390e332985277568edab1ee6132326b42gs DDI_INTR_PRI(rgep->intr_pri));
aa81749390e332985277568edab1ee6132326b42gs rw_init(rgep->errlock, NULL, RW_DRIVER,
aa81749390e332985277568edab1ee6132326b42gs DDI_INTR_PRI(rgep->intr_pri));
aa81749390e332985277568edab1ee6132326b42gs mutex_init(rgep->tx_lock, NULL, MUTEX_DRIVER,
aa81749390e332985277568edab1ee6132326b42gs DDI_INTR_PRI(rgep->intr_pri));
aa81749390e332985277568edab1ee6132326b42gs mutex_init(rgep->tc_lock, NULL, MUTEX_DRIVER,
aa81749390e332985277568edab1ee6132326b42gs DDI_INTR_PRI(rgep->intr_pri));
aa81749390e332985277568edab1ee6132326b42gs mutex_init(rgep->rx_lock, NULL, MUTEX_DRIVER,
aa81749390e332985277568edab1ee6132326b42gs DDI_INTR_PRI(rgep->intr_pri));
aa81749390e332985277568edab1ee6132326b42gs mutex_init(rgep->rc_lock, NULL, MUTEX_DRIVER,
aa81749390e332985277568edab1ee6132326b42gs DDI_INTR_PRI(rgep->intr_pri));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Initialize rings
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs err = rge_init_rings(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (err != DDI_SUCCESS) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_problem(rgep, "rge_init_rings() failed");
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs goto attach_fail;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
aa81749390e332985277568edab1ee6132326b42gs rgep->progress |= PROGRESS_INIT;
aa81749390e332985277568edab1ee6132326b42gs
aa81749390e332985277568edab1ee6132326b42gs /*
aa81749390e332985277568edab1ee6132326b42gs * Now that mutex locks are initialized, enable interrupts.
aa81749390e332985277568edab1ee6132326b42gs */
aa81749390e332985277568edab1ee6132326b42gs if (rgep->intr_cap & DDI_INTR_FLAG_BLOCK) {
aa81749390e332985277568edab1ee6132326b42gs /* Call ddi_intr_block_enable() for MSI interrupts */
aa81749390e332985277568edab1ee6132326b42gs (void) ddi_intr_block_enable(rgep->htable, rgep->intr_cnt);
aa81749390e332985277568edab1ee6132326b42gs } else {
aa81749390e332985277568edab1ee6132326b42gs /* Call ddi_intr_enable for MSI or FIXED interrupts */
aa81749390e332985277568edab1ee6132326b42gs for (i = 0; i < rgep->intr_cnt; i++) {
aa81749390e332985277568edab1ee6132326b42gs (void) ddi_intr_enable(rgep->htable[i]);
aa81749390e332985277568edab1ee6132326b42gs }
aa81749390e332985277568edab1ee6132326b42gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Initialise link state variables
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Stop, reset & reinitialise the chip.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Initialise the (internal) PHY.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->param_link_up = LINK_STATE_UNKNOWN;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Reset chip & rings to initial state; also reset address
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * filtering, promiscuity, loopback mode.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_enter(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs (void) rge_chip_reset(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_chip_sync(rgep, RGE_GET_MAC);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs bzero(rgep->mcast_hash, sizeof (rgep->mcast_hash));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs bzero(rgep->mcast_refs, sizeof (rgep->mcast_refs));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->promisc = B_FALSE;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->param_loop_mode = RGE_LOOP_NONE;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_exit(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_phy_init(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->progress |= PROGRESS_PHY;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Create & initialise named kstats
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_init_kstats(rgep, instance);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->progress |= PROGRESS_KSTATS;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb if ((macp = mac_alloc(MAC_VERSION)) == NULL)
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb goto attach_fail;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb macp->m_driver = rgep;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs macp->m_dip = devinfo;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb macp->m_src_addr = rgep->netaddr;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb macp->m_callbacks = &rge_m_callbacks;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb macp->m_min_sdu = 0;
aa81749390e332985277568edab1ee6132326b42gs macp->m_max_sdu = rgep->default_mtu;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz macp->m_margin = VLAN_TAGSZ;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Finally, we're ready to register ourselves with the MAC layer
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * interface; if this succeeds, we're all ready to start()
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb err = mac_register(macp, &rgep->mh);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb mac_free(macp);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb if (err != 0)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs goto attach_fail;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota /*
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota * Register a periodical handler.
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota * reg_chip_cyclic() is invoked in kernel context.
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota */
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota rgep->periodic_id = ddi_periodic_add(rge_chip_cyclic, rgep,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota RGE_CYCLIC_PERIOD, DDI_IPL_0);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep->progress |= PROGRESS_READY;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_SUCCESS);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsattach_fail:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_unattach(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * rge_suspend() -- suspend transmit/receive for powerdown
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic int
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_suspend(rge_t *rgep)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Stop processing and idle (powerdown) the PHY ...
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_enter(rgep->genlock);
368a5ef88e8811b10e03b912242c0faef12ce713Miles Xu, Sun Microsystems rw_enter(rgep->errlock, RW_WRITER);
343c26163d86b7f3b861ae03b20226fecee1ab99mx
343c26163d86b7f3b861ae03b20226fecee1ab99mx if (rgep->rge_mac_state != RGE_MAC_STARTED) {
368a5ef88e8811b10e03b912242c0faef12ce713Miles Xu, Sun Microsystems rw_exit(rgep->errlock);
343c26163d86b7f3b861ae03b20226fecee1ab99mx mutex_exit(rgep->genlock);
343c26163d86b7f3b861ae03b20226fecee1ab99mx return (DDI_SUCCESS);
343c26163d86b7f3b861ae03b20226fecee1ab99mx }
343c26163d86b7f3b861ae03b20226fecee1ab99mx
343c26163d86b7f3b861ae03b20226fecee1ab99mx rgep->suspended = B_TRUE;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_stop(rgep);
343c26163d86b7f3b861ae03b20226fecee1ab99mx rgep->rge_mac_state = RGE_MAC_STOPPED;
343c26163d86b7f3b861ae03b20226fecee1ab99mx
343c26163d86b7f3b861ae03b20226fecee1ab99mx rw_exit(rgep->errlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_exit(rgep->genlock);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_SUCCESS);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
193974072f41a843678abf5f61979c748687e66bSherry Moore/*
193974072f41a843678abf5f61979c748687e66bSherry Moore * quiesce(9E) entry point.
193974072f41a843678abf5f61979c748687e66bSherry Moore *
193974072f41a843678abf5f61979c748687e66bSherry Moore * This function is called when the system is single-threaded at high
193974072f41a843678abf5f61979c748687e66bSherry Moore * PIL with preemption disabled. Therefore, this function must not be
193974072f41a843678abf5f61979c748687e66bSherry Moore * blocked.
193974072f41a843678abf5f61979c748687e66bSherry Moore *
193974072f41a843678abf5f61979c748687e66bSherry Moore * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
193974072f41a843678abf5f61979c748687e66bSherry Moore * DDI_FAILURE indicates an error condition and should almost never happen.
193974072f41a843678abf5f61979c748687e66bSherry Moore */
193974072f41a843678abf5f61979c748687e66bSherry Moorestatic int
193974072f41a843678abf5f61979c748687e66bSherry Moorerge_quiesce(dev_info_t *devinfo)
193974072f41a843678abf5f61979c748687e66bSherry Moore{
193974072f41a843678abf5f61979c748687e66bSherry Moore rge_t *rgep = ddi_get_driver_private(devinfo);
193974072f41a843678abf5f61979c748687e66bSherry Moore
193974072f41a843678abf5f61979c748687e66bSherry Moore if (rgep == NULL)
193974072f41a843678abf5f61979c748687e66bSherry Moore return (DDI_FAILURE);
193974072f41a843678abf5f61979c748687e66bSherry Moore
193974072f41a843678abf5f61979c748687e66bSherry Moore /*
193974072f41a843678abf5f61979c748687e66bSherry Moore * Turn off debugging
193974072f41a843678abf5f61979c748687e66bSherry Moore */
193974072f41a843678abf5f61979c748687e66bSherry Moore rge_debug = 0;
193974072f41a843678abf5f61979c748687e66bSherry Moore rgep->debug = 0;
193974072f41a843678abf5f61979c748687e66bSherry Moore
193974072f41a843678abf5f61979c748687e66bSherry Moore /* Stop the chip */
193974072f41a843678abf5f61979c748687e66bSherry Moore rge_chip_stop(rgep, B_FALSE);
193974072f41a843678abf5f61979c748687e66bSherry Moore
193974072f41a843678abf5f61979c748687e66bSherry Moore return (DDI_SUCCESS);
193974072f41a843678abf5f61979c748687e66bSherry Moore}
193974072f41a843678abf5f61979c748687e66bSherry Moore
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * detach(9E) -- Detach a device from the system
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic int
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsrge_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_t *rgep;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs RGE_GTRACE(("rge_detach($%p, %d)", (void *)devinfo, cmd));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rgep = ddi_get_driver_private(devinfo);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs switch (cmd) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs default:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case DDI_SUSPEND:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (rge_suspend(rgep));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs case DDI_DETACH:
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs break;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * If there is any posted buffer, the driver should reject to be
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * detached. Need notice upper layer to release them.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
aa81749390e332985277568edab1ee6132326b42gs if (!(rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY) &&
aa81749390e332985277568edab1ee6132326b42gs rgep->rx_free != RGE_BUF_SLOTS)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * Unregister from the MAC layer subsystem. This can fail, in
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * particular if there are DLPI style-2 streams still open -
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * in which case we just return failure without shutting
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * down chip operations.
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb if (mac_unregister(rgep->mh) != 0)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_FAILURE);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs /*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * All activity stopped, so we can clean up & exit
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_unattach(rgep);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (DDI_SUCCESS);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs/*
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs * ========== Module Loading Data & Entry Points ==========
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs#undef RGE_DBG
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs#define RGE_DBG RGE_DBG_INIT /* debug flag for this code */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsDDI_DEFINE_STREAM_OPS(rge_dev_ops, nulldev, nulldev, rge_attach, rge_detach,
193974072f41a843678abf5f61979c748687e66bSherry Moore nodev, NULL, D_MP, NULL, rge_quiesce);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic struct modldrv rge_modldrv = {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs &mod_driverops, /* Type of module. This one is a driver */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs rge_ident, /* short description */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs &rge_dev_ops /* driver specific ops */
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs};
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsstatic struct modlinkage modlinkage = {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs MODREV_1, (void *)&rge_modldrv, NULL
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs};
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsint
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs_info(struct modinfo *modinfop)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (mod_info(&modlinkage, modinfop));
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsint
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs_init(void)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs int status;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mac_init_ops(&rge_dev_ops, "rge");
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs status = mod_install(&modlinkage);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (status == DDI_SUCCESS)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_init(rge_log_mutex, NULL, MUTEX_DRIVER, NULL);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs else
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mac_fini_ops(&rge_dev_ops);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (status);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gsint
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs_fini(void)
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs{
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs int status;
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs status = mod_remove(&modlinkage);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs if (status == DDI_SUCCESS) {
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mac_fini_ops(&rge_dev_ops);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs mutex_destroy(rge_log_mutex);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs }
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs return (status);
c7fd2ed091e4e4beb47e1da3a6197a2c38f29c02gs}