xref: /onnv-gate/usr/src/uts/intel/io/amd8111s/amd8111s_main.c (revision 5895:f251acdd9bdc)
15256Slh155975 /*
25256Slh155975  * CDDL HEADER START
35256Slh155975  *
45256Slh155975  * The contents of this file are subject to the terms of the
55256Slh155975  * Common Development and Distribution License (the "License").
65256Slh155975  * You may not use this file except in compliance with the License.
75256Slh155975  *
85256Slh155975  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95256Slh155975  * or http://www.opensolaris.org/os/licensing.
105256Slh155975  * See the License for the specific language governing permissions
115256Slh155975  * and limitations under the License.
125256Slh155975  *
135256Slh155975  * When distributing Covered Code, include this CDDL HEADER in each
145256Slh155975  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155256Slh155975  * If applicable, add the following below this CDDL HEADER, with the
165256Slh155975  * fields enclosed by brackets "[]" replaced with your own identifying
175256Slh155975  * information: Portions Copyright [yyyy] [name of copyright owner]
185256Slh155975  *
195256Slh155975  * CDDL HEADER END
205256Slh155975  */
215256Slh155975 
225256Slh155975 /*
23*5895Syz147064  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
245256Slh155975  * Use is subject to license terms.
255256Slh155975  */
265256Slh155975 
275256Slh155975 #pragma ident	"%Z%%M%	%I%	%E% SMI"
285256Slh155975 
295256Slh155975 /*
305256Slh155975  * Copyright (c) 2001-2006 Advanced Micro Devices, Inc.  All rights reserved.
315256Slh155975  *
325256Slh155975  * Redistribution and use in source and binary forms, with or without
335256Slh155975  * modification, are permitted provided that the following conditions are met:
345256Slh155975  *
355256Slh155975  * + Redistributions of source code must retain the above copyright notice,
365256Slh155975  * + this list of conditions and the following disclaimer.
375256Slh155975  *
385256Slh155975  * + Redistributions in binary form must reproduce the above copyright
395256Slh155975  * + notice, this list of conditions and the following disclaimer in the
405256Slh155975  * + documentation and/or other materials provided with the distribution.
415256Slh155975  *
425256Slh155975  * + Neither the name of Advanced Micro Devices, Inc. nor the names of its
435256Slh155975  * + contributors may be used to endorse or promote products derived from
445256Slh155975  * + this software without specific prior written permission.
455256Slh155975  *
465256Slh155975  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
475256Slh155975  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
485256Slh155975  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
495256Slh155975  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
505256Slh155975  * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. OR
515256Slh155975  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
525256Slh155975  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
535256Slh155975  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
545256Slh155975  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
555256Slh155975  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
565256Slh155975  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
575256Slh155975  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
585256Slh155975  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
595256Slh155975  *
605256Slh155975  * Import/Export/Re-Export/Use/Release/Transfer Restrictions and
615256Slh155975  * Compliance with Applicable Laws.  Notice is hereby given that
625256Slh155975  * the software may be subject to restrictions on use, release,
635256Slh155975  * transfer, importation, exportation and/or re-exportation under
645256Slh155975  * the laws and regulations of the United States or other
655256Slh155975  * countries ("Applicable Laws"), which include but are not
665256Slh155975  * limited to U.S. export control laws such as the Export
675256Slh155975  * Administration Regulations and national security controls as
685256Slh155975  * defined thereunder, as well as State Department controls under
695256Slh155975  * the U.S. Munitions List.  Permission to use and/or
705256Slh155975  * redistribute the software is conditioned upon compliance with
715256Slh155975  * all Applicable Laws, including U.S. export control laws
725256Slh155975  * regarding specifically designated persons, countries and
735256Slh155975  * nationals of countries subject to national security controls.
745256Slh155975  */
755256Slh155975 
765256Slh155975 
775256Slh155975 #pragma ident "@(#)$RCSfile: solaris_odl.c,v $ $Revision: 1.3 $ " \
785256Slh155975 " $Date: 2004/04/22 15:22:54 $ AMD"
795256Slh155975 
805256Slh155975 
815256Slh155975 /* include files */
825256Slh155975 #include <sys/disp.h>
835256Slh155975 #include <sys/atomic.h>
84*5895Syz147064 #include <sys/vlan.h>
855256Slh155975 #include "amd8111s_main.h"
865256Slh155975 
875256Slh155975 /* Global macro Definations */
885256Slh155975 #define	ROUNDUP(x, a)	(((x) + (a) - 1) & ~((a) - 1))
895256Slh155975 #define	INTERFACE_NAME "amd8111s"
905256Slh155975 #define	AMD8111S_SPLIT	128
915256Slh155975 #define	AMD8111S_SEND_MAX	64
925256Slh155975 
935256Slh155975 static char ident[] = "AMD8111 10/100M Ethernet 1.0";
945256Slh155975 
955256Slh155975 /*
965256Slh155975  * Driver Entry Points
975256Slh155975  */
985256Slh155975 static int amd8111s_attach(dev_info_t *, ddi_attach_cmd_t);
995256Slh155975 static int amd8111s_detach(dev_info_t *, ddi_detach_cmd_t);
1005256Slh155975 
1015256Slh155975 /*
1025256Slh155975  * GLD Entry points prototype
1035256Slh155975  */
1045256Slh155975 static int amd8111s_m_unicst(void *, const uint8_t *);
1055256Slh155975 static int amd8111s_m_promisc(void *, boolean_t);
1065256Slh155975 static int amd8111s_m_stat(void *, uint_t, uint64_t *);
1075256Slh155975 static void amd8111s_m_resources(void *arg);
1085256Slh155975 static void amd8111s_m_ioctl(void *, queue_t *, mblk_t *);
1095256Slh155975 static int amd8111s_m_multicst(void *, boolean_t, const uint8_t *addr);
1105256Slh155975 static int amd8111s_m_start(void *);
1115256Slh155975 static void amd8111s_m_stop(void *);
1125256Slh155975 static mblk_t *amd8111s_m_tx(void *, mblk_t *mp);
1135256Slh155975 static uint_t amd8111s_intr(caddr_t);
1145256Slh155975 
1155256Slh155975 static int amd8111s_unattach(dev_info_t *, struct LayerPointers *);
1165256Slh155975 
1175256Slh155975 static boolean_t amd8111s_allocate_buffers(struct LayerPointers *);
1185256Slh155975 static int amd8111s_odlInit(struct LayerPointers *);
1195256Slh155975 static boolean_t amd8111s_allocate_descriptors(struct LayerPointers *);
1205256Slh155975 static void amd8111s_free_descriptors(struct LayerPointers *);
1215256Slh155975 static boolean_t amd8111s_alloc_dma_ringbuf(struct LayerPointers *,
1225256Slh155975 		struct amd8111s_dma_ringbuf *, uint32_t, uint32_t);
1235256Slh155975 static void amd8111s_free_dma_ringbuf(struct amd8111s_dma_ringbuf *);
1245256Slh155975 
1255256Slh155975 
1265256Slh155975 static void amd8111s_log(struct LayerPointers *adapter, int level,
1275256Slh155975     char *fmt, ...);
1285256Slh155975 
1295256Slh155975 static struct cb_ops amd8111s_cb_ops = {
1305256Slh155975 	nulldev,
1315256Slh155975 	nulldev,
1325256Slh155975 	nodev,
1335256Slh155975 	nodev,
1345256Slh155975 	nodev,
1355256Slh155975 	nodev,
1365256Slh155975 	nodev,
1375256Slh155975 	nodev,
1385256Slh155975 	nodev,
1395256Slh155975 	nodev,
1405256Slh155975 	nodev,
1415256Slh155975 	nochpoll,
1425256Slh155975 	ddi_prop_op,
1435256Slh155975 	NULL,
1445256Slh155975 	D_NEW | D_MP,
1455256Slh155975 	CB_REV,		/* cb_rev */
1465256Slh155975 	nodev,		/* cb_aread */
1475256Slh155975 	nodev		/* cb_awrite */
1485256Slh155975 };
1495256Slh155975 
1505256Slh155975 static struct dev_ops amd8111s_dev_ops = {
1515256Slh155975 	DEVO_REV,		/* devo_rev */
1525256Slh155975 	0,			/* devo_refcnt */
1535256Slh155975 	NULL,			/* devo_getinfo */
1545256Slh155975 	nulldev,		/* devo_identify */
1555256Slh155975 	nulldev,		/* devo_probe */
1565256Slh155975 	amd8111s_attach,	/* devo_attach */
1575256Slh155975 	amd8111s_detach,	/* devo_detach */
1585256Slh155975 	nodev,			/* devo_reset */
1595256Slh155975 	&amd8111s_cb_ops,	/* devo_cb_ops */
1605256Slh155975 	NULL,			/* devo_bus_ops */
1615256Slh155975 	nodev
1625256Slh155975 };
1635256Slh155975 
1645256Slh155975 struct modldrv amd8111s_modldrv = {
1655256Slh155975 	&mod_driverops,		/* Type of module. This one is a driver */
1665256Slh155975 	ident,			/* short description */
1675256Slh155975 	&amd8111s_dev_ops	/* driver specific ops */
1685256Slh155975 };
1695256Slh155975 
1705256Slh155975 struct modlinkage amd8111s_modlinkage = {
1715256Slh155975 	MODREV_1, (void *)&amd8111s_modldrv, NULL
1725256Slh155975 };
1735256Slh155975 
1745256Slh155975 /*
1755256Slh155975  * Global Variables
1765256Slh155975  */
1775256Slh155975 struct LayerPointers *amd8111sadapter;
1785256Slh155975 
1795256Slh155975 static ddi_dma_attr_t pcn_buff_dma_attr_t = {
1805256Slh155975 	DMA_ATTR_V0,	/* dma_attr_version */
1815256Slh155975 	(uint64_t)0,		/* dma_attr_addr_lo */
1825256Slh155975 	(uint64_t)0xFFFFFFFF,	/* dma_attr_addr_hi */
1835256Slh155975 	(uint64_t)0xFFFFFFFF,	/* dma_attr_count_max */
1845256Slh155975 	(uint64_t)1,		/* dma_attr_align */
1855256Slh155975 	(uint_t)0x7F,		/* dma_attr_burstsizes */
1865256Slh155975 	(uint32_t)1,		/* dma_attr_minxfer */
1875256Slh155975 	(uint64_t)0xFFFFFFFF,	/* dma_attr_maxxfer */
1885256Slh155975 	(uint64_t)0xFFFFFFFF,	/* dma_attr_seg */
1895256Slh155975 	(int)1,			/* dma_attr_sgllen */
1905256Slh155975 	(uint32_t)1,		/* granularity */
1915256Slh155975 	(uint_t)0		/* dma_attr_flags */
1925256Slh155975 };
1935256Slh155975 
1945256Slh155975 static ddi_dma_attr_t pcn_desc_dma_attr_t = {
1955256Slh155975 	DMA_ATTR_V0,		/* dma_attr_version */
1965256Slh155975 	(uint64_t)0,		/* dma_attr_addr_lo */
1975256Slh155975 	(uint64_t)0xFFFFFFFF,	/* dma_attr_addr_hi */
1985256Slh155975 	(uint64_t)0x7FFFFFFF,	/* dma_attr_count_max */
1995256Slh155975 	(uint64_t)0x10,		/* dma_attr_align */
2005256Slh155975 	(uint_t)0xFFFFFFFFU,	/* dma_attr_burstsizes */
2015256Slh155975 	(uint32_t)1,		/* dma_attr_minxfer */
2025256Slh155975 	(uint64_t)0xFFFFFFFF,	/* dma_attr_maxxfer */
2035256Slh155975 	(uint64_t)0xFFFFFFFF,	/* dma_attr_seg */
2045256Slh155975 	(int)1,			/* dma_attr_sgllen */
2055256Slh155975 	(uint32_t)1,		/* granularity */
2065256Slh155975 	(uint_t)0		/* dma_attr_flags */
2075256Slh155975 };
2085256Slh155975 
2095256Slh155975 /* PIO access attributes for registers */
2105256Slh155975 static ddi_device_acc_attr_t pcn_acc_attr = {
2115256Slh155975 	DDI_DEVICE_ATTR_V0,
2125256Slh155975 	DDI_STRUCTURE_LE_ACC,
2135256Slh155975 	DDI_STRICTORDER_ACC
2145256Slh155975 };
2155256Slh155975 
2165256Slh155975 #define	AMD8111S_M_CALLBACK_FLAGS	(MC_RESOURCES | MC_IOCTL)
2175256Slh155975 
2185256Slh155975 
2195256Slh155975 static mac_callbacks_t amd8111s_m_callbacks = {
2205256Slh155975 	AMD8111S_M_CALLBACK_FLAGS,
2215256Slh155975 	amd8111s_m_stat,
2225256Slh155975 	amd8111s_m_start,
2235256Slh155975 	amd8111s_m_stop,
2245256Slh155975 	amd8111s_m_promisc,
2255256Slh155975 	amd8111s_m_multicst,
2265256Slh155975 	amd8111s_m_unicst,
2275256Slh155975 	amd8111s_m_tx,
2285256Slh155975 	amd8111s_m_resources,
2295256Slh155975 	amd8111s_m_ioctl
2305256Slh155975 };
2315256Slh155975 
2325256Slh155975 
2335256Slh155975 /*
2345256Slh155975  * Standard Driver Load Entry Point
2355256Slh155975  * It will be called at load time of driver.
2365256Slh155975  */
2375256Slh155975 int
2385256Slh155975 _init()
2395256Slh155975 {
2405256Slh155975 	int status;
2415256Slh155975 	mac_init_ops(&amd8111s_dev_ops, "amd8111s");
2425256Slh155975 
2435256Slh155975 	status = mod_install(&amd8111s_modlinkage);
2445256Slh155975 	if (status != DDI_SUCCESS) {
2455256Slh155975 		mac_fini_ops(&amd8111s_dev_ops);
2465256Slh155975 	}
2475256Slh155975 
2485256Slh155975 	return (status);
2495256Slh155975 }
2505256Slh155975 
2515256Slh155975 /*
2525256Slh155975  * Standard Driver Entry Point for Query.
2535256Slh155975  * It will be called at any time to get Driver info.
2545256Slh155975  */
2555256Slh155975 int
2565256Slh155975 _info(struct modinfo *modinfop)
2575256Slh155975 {
2585256Slh155975 	return (mod_info(&amd8111s_modlinkage, modinfop));
2595256Slh155975 }
2605256Slh155975 
2615256Slh155975 /*
2625256Slh155975  *	Standard Driver Entry Point for Unload.
2635256Slh155975  *	It will be called at unload time of driver.
2645256Slh155975  */
2655256Slh155975 int
2665256Slh155975 _fini()
2675256Slh155975 {
2685256Slh155975 	int status;
2695256Slh155975 
2705256Slh155975 	status = mod_remove(&amd8111s_modlinkage);
2715256Slh155975 	if (status == DDI_SUCCESS) {
2725256Slh155975 		mac_fini_ops(&amd8111s_dev_ops);
2735256Slh155975 	}
2745256Slh155975 
2755256Slh155975 	return (status);
2765256Slh155975 }
2775256Slh155975 
2785256Slh155975 /* Adjust Interrupt Coalescing Register to coalesce interrupts */
2795256Slh155975 static void
2805256Slh155975 amd8111s_m_blank(void *arg, time_t ticks, uint32_t count)
2815256Slh155975 {
2825256Slh155975 	_NOTE(ARGUNUSED(arg, ticks, count));
2835256Slh155975 }
2845256Slh155975 
2855256Slh155975 static void
2865256Slh155975 amd8111s_m_resources(void *arg)
2875256Slh155975 {
2885256Slh155975 	struct LayerPointers *adapter = arg;
2895256Slh155975 	mac_rx_fifo_t mrf;
2905256Slh155975 
2915256Slh155975 	mrf.mrf_type = MAC_RX_FIFO;
2925256Slh155975 	mrf.mrf_blank = amd8111s_m_blank;
2935256Slh155975 	mrf.mrf_arg = (void *)adapter;
2945256Slh155975 	mrf.mrf_normal_blank_time = 128;
2955256Slh155975 	mrf.mrf_normal_pkt_count = 8;
2965256Slh155975 
2975256Slh155975 	adapter->pOdl->mrh = mac_resource_add(adapter->pOdl->mh,
2985256Slh155975 	    (mac_resource_t *)&mrf);
2995256Slh155975 }
3005256Slh155975 
3015256Slh155975 /*
3025256Slh155975  * Loopback Support
3035256Slh155975  */
3045256Slh155975 static lb_property_t loopmodes[] = {
3055256Slh155975 	{ normal,	"normal",	AMD8111S_LB_NONE		},
3065256Slh155975 	{ external,	"100Mbps",	AMD8111S_LB_EXTERNAL_100	},
3075256Slh155975 	{ external,	"10Mbps",	AMD8111S_LB_EXTERNAL_10		},
3085256Slh155975 	{ internal,	"MAC",		AMD8111S_LB_INTERNAL_MAC	}
3095256Slh155975 };
3105256Slh155975 
3115256Slh155975 static void
3125256Slh155975 amd8111s_set_loop_mode(struct LayerPointers *adapter, uint32_t mode)
3135256Slh155975 {
3145256Slh155975 
3155256Slh155975 	/*
3165256Slh155975 	 * If the mode isn't being changed, there's nothing to do ...
3175256Slh155975 	 */
3185256Slh155975 	if (mode == adapter->pOdl->loopback_mode)
3195256Slh155975 		return;
3205256Slh155975 
3215256Slh155975 	/*
3225256Slh155975 	 * Validate the requested mode and prepare a suitable message
3235256Slh155975 	 * to explain the link down/up cycle that the change will
3245256Slh155975 	 * probably induce ...
3255256Slh155975 	 */
3265256Slh155975 	switch (mode) {
3275256Slh155975 	default:
3285256Slh155975 		return;
3295256Slh155975 
3305256Slh155975 	case AMD8111S_LB_NONE:
3315256Slh155975 		mdlStopChip(adapter);
3325256Slh155975 		if (adapter->pOdl->loopback_mode == AMD8111S_LB_INTERNAL_MAC) {
3335256Slh155975 			cmn_err(CE_NOTE, "LB_NONE restored from Interanl LB");
3345256Slh155975 			WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD2,
3355256Slh155975 			    INLOOP);
3365256Slh155975 			WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD3,
3375256Slh155975 			    FORCE_FULL_DUPLEX | FORCE_LINK_STATUS);
3385256Slh155975 		} else {
3395256Slh155975 			cmn_err(CE_NOTE, "LB_NONE restored from Exteranl LB");
3405256Slh155975 			WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD2,
3415256Slh155975 			    EXLOOP);
3425256Slh155975 		}
3435256Slh155975 
3445256Slh155975 		amd8111s_reset(adapter);
3455256Slh155975 		adapter->pOdl->LinkStatus = LINK_STATE_DOWN;
3465256Slh155975 		adapter->pOdl->rx_fcs_stripped = B_FALSE;
3475256Slh155975 		mdlStartChip(adapter);
3485256Slh155975 		break;
3495256Slh155975 
3505256Slh155975 	case AMD8111S_LB_EXTERNAL_100:
3515256Slh155975 		cmn_err(CE_NOTE, "amd8111s_set_loop_mode LB_EXTERNAL_100");
3525256Slh155975 		mdlStopChip(adapter);
3535256Slh155975 		amd8111s_reset(adapter);
3545256Slh155975 		SetIntrCoalesc(adapter, B_FALSE);
3555256Slh155975 		mdlPHYAutoNegotiation(adapter, PHY_FORCE_FD_100);
3565256Slh155975 		WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD2,
3575256Slh155975 		    VAL0 | EXLOOP);
3585256Slh155975 		adapter->pOdl->LinkStatus = LINK_STATE_UP;
3595256Slh155975 		adapter->pMdl->Speed = 100;
3605256Slh155975 		adapter->pMdl->FullDuplex = B_TRUE;
3615256Slh155975 		/* Tell GLD the state of the physical link. */
3625256Slh155975 		mac_link_update(adapter->pOdl->mh, LINK_STATE_UP);
3635256Slh155975 
3645256Slh155975 		adapter->pOdl->rx_fcs_stripped = B_TRUE;
3655256Slh155975 
3665256Slh155975 		mdlStartChip(adapter);
3675256Slh155975 		break;
3685256Slh155975 
3695256Slh155975 	case AMD8111S_LB_EXTERNAL_10:
3705256Slh155975 		cmn_err(CE_NOTE, "amd8111s_set_loop_mode LB_EXTERNAL_10");
3715256Slh155975 		mdlStopChip(adapter);
3725256Slh155975 		amd8111s_reset(adapter);
3735256Slh155975 		SetIntrCoalesc(adapter, B_FALSE);
3745256Slh155975 		mdlPHYAutoNegotiation(adapter, PHY_FORCE_FD_10);
3755256Slh155975 		WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD2,
3765256Slh155975 		    VAL0 | EXLOOP);
3775256Slh155975 		adapter->pOdl->LinkStatus = LINK_STATE_UP;
3785256Slh155975 		adapter->pMdl->Speed = 10;
3795256Slh155975 		adapter->pMdl->FullDuplex = B_TRUE;
3805256Slh155975 		/* Tell GLD the state of the physical link. */
3815256Slh155975 		mac_link_update(adapter->pOdl->mh, LINK_STATE_UP);
3825256Slh155975 
3835256Slh155975 		adapter->pOdl->rx_fcs_stripped = B_TRUE;
3845256Slh155975 
3855256Slh155975 		mdlStartChip(adapter);
3865256Slh155975 		break;
3875256Slh155975 
3885256Slh155975 	case AMD8111S_LB_INTERNAL_MAC:
3895256Slh155975 		cmn_err(CE_NOTE, "amd8111s_set_loop_mode LB_INTERNAL_MAC");
3905256Slh155975 		mdlStopChip(adapter);
3915256Slh155975 		amd8111s_reset(adapter);
3925256Slh155975 		SetIntrCoalesc(adapter, B_FALSE);
3935256Slh155975 		/* Disable Port Manager */
3945256Slh155975 		WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD3,
3955256Slh155975 		    EN_PMGR);
3965256Slh155975 		WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD2,
3975256Slh155975 		    VAL0 | INLOOP);
3985256Slh155975 
3995256Slh155975 		WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD3,
4005256Slh155975 		    VAL1 | FORCE_FULL_DUPLEX | FORCE_LINK_STATUS);
4015256Slh155975 
4025256Slh155975 		adapter->pOdl->LinkStatus = LINK_STATE_UP;
4035256Slh155975 		adapter->pMdl->FullDuplex = B_TRUE;
4045256Slh155975 		/* Tell GLD the state of the physical link. */
4055256Slh155975 		mac_link_update(adapter->pOdl->mh, LINK_STATE_UP);
4065256Slh155975 
4075256Slh155975 		adapter->pOdl->rx_fcs_stripped = B_TRUE;
4085256Slh155975 
4095256Slh155975 		mdlStartChip(adapter);
4105256Slh155975 		break;
4115256Slh155975 	}
4125256Slh155975 
4135256Slh155975 	/*
4145256Slh155975 	 * All OK; tell the caller to reprogram
4155256Slh155975 	 * the PHY and/or MAC for the new mode ...
4165256Slh155975 	 */
4175256Slh155975 	adapter->pOdl->loopback_mode = mode;
4185256Slh155975 }
4195256Slh155975 
4205256Slh155975 static enum ioc_reply
4215256Slh155975 amd8111s_loopback_ioctl(struct LayerPointers *adapter, struct iocblk *iocp,
4225256Slh155975     mblk_t *mp)
4235256Slh155975 {
4245256Slh155975 	lb_info_sz_t *lbsp;
4255256Slh155975 	lb_property_t *lbpp;
4265256Slh155975 	uint32_t *lbmp;
4275256Slh155975 	int cmd;
4285256Slh155975 
4295256Slh155975 	/*
4305256Slh155975 	 * Validate format of ioctl
4315256Slh155975 	 */
4325256Slh155975 	if (mp->b_cont == NULL)
4335256Slh155975 		return (IOC_INVAL);
4345256Slh155975 
4355256Slh155975 	cmd = iocp->ioc_cmd;
4365256Slh155975 	switch (cmd) {
4375256Slh155975 	default:
4385256Slh155975 		/* NOTREACHED */
4395256Slh155975 		amd8111s_log(adapter, CE_NOTE,
4405256Slh155975 		    "amd8111s_loop_ioctl: invalid cmd 0x%x", cmd);
4415256Slh155975 		return (IOC_INVAL);
4425256Slh155975 
4435256Slh155975 	case LB_GET_INFO_SIZE:
4445256Slh155975 		if (iocp->ioc_count != sizeof (lb_info_sz_t)) {
4455256Slh155975 			amd8111s_log(adapter, CE_NOTE,
4465256Slh155975 			    "wrong LB_GET_INFO_SIZE size");
4475256Slh155975 			return (IOC_INVAL);
4485256Slh155975 		}
4495256Slh155975 		lbsp = (lb_info_sz_t *)mp->b_cont->b_rptr;
4505256Slh155975 		*lbsp = sizeof (loopmodes);
4515256Slh155975 		break;
4525256Slh155975 
4535256Slh155975 	case LB_GET_INFO:
4545256Slh155975 		if (iocp->ioc_count != sizeof (loopmodes)) {
4555256Slh155975 			amd8111s_log(adapter, CE_NOTE,
4565256Slh155975 			    "Wrong LB_GET_INFO size");
4575256Slh155975 			return (IOC_INVAL);
4585256Slh155975 		}
4595256Slh155975 		lbpp = (lb_property_t *)mp->b_cont->b_rptr;
4605256Slh155975 		bcopy(loopmodes, lbpp, sizeof (loopmodes));
4615256Slh155975 		break;
4625256Slh155975 
4635256Slh155975 	case LB_GET_MODE:
4645256Slh155975 		if (iocp->ioc_count != sizeof (uint32_t)) {
4655256Slh155975 			amd8111s_log(adapter, CE_NOTE,
4665256Slh155975 			    "Wrong LB_GET_MODE size");
4675256Slh155975 			return (IOC_INVAL);
4685256Slh155975 		}
4695256Slh155975 		lbmp = (uint32_t *)mp->b_cont->b_rptr;
4705256Slh155975 		*lbmp = adapter->pOdl->loopback_mode;
4715256Slh155975 		break;
4725256Slh155975 
4735256Slh155975 	case LB_SET_MODE:
4745256Slh155975 		if (iocp->ioc_count != sizeof (uint32_t)) {
4755256Slh155975 			amd8111s_log(adapter, CE_NOTE,
4765256Slh155975 			    "Wrong LB_SET_MODE size");
4775256Slh155975 			return (IOC_INVAL);
4785256Slh155975 		}
4795256Slh155975 		lbmp = (uint32_t *)mp->b_cont->b_rptr;
4805256Slh155975 		amd8111s_set_loop_mode(adapter, *lbmp);
4815256Slh155975 		break;
4825256Slh155975 	}
4835256Slh155975 	return (IOC_REPLY);
4845256Slh155975 }
4855256Slh155975 
4865256Slh155975 static void
4875256Slh155975 amd8111s_m_ioctl(void *arg, queue_t *q, mblk_t *mp)
4885256Slh155975 {
4895256Slh155975 	struct iocblk *iocp;
4905256Slh155975 	struct LayerPointers *adapter;
4915256Slh155975 	enum ioc_reply status;
4925256Slh155975 
4935256Slh155975 	iocp = (struct iocblk *)mp->b_rptr;
4945256Slh155975 	iocp->ioc_error = 0;
4955256Slh155975 	adapter = (struct LayerPointers *)arg;
4965256Slh155975 
4975256Slh155975 	ASSERT(adapter);
4985256Slh155975 	if (adapter == NULL) {
4995256Slh155975 		miocnak(q, mp, 0, EINVAL);
5005256Slh155975 		return;
5015256Slh155975 	}
5025256Slh155975 
5035256Slh155975 	switch (iocp->ioc_cmd) {
5045256Slh155975 
5055256Slh155975 	case LB_GET_INFO_SIZE:
5065256Slh155975 	case LB_GET_INFO:
5075256Slh155975 	case LB_GET_MODE:
5085256Slh155975 	case LB_SET_MODE:
5095256Slh155975 		status = amd8111s_loopback_ioctl(adapter, iocp, mp);
5105256Slh155975 		break;
5115256Slh155975 
5125256Slh155975 	default:
5135256Slh155975 		status = IOC_INVAL;
5145256Slh155975 		break;
5155256Slh155975 	}
5165256Slh155975 
5175256Slh155975 	/*
5185256Slh155975 	 * Decide how to reply
5195256Slh155975 	 */
5205256Slh155975 	switch (status) {
5215256Slh155975 	default:
5225256Slh155975 	case IOC_INVAL:
5235256Slh155975 		/*
5245256Slh155975 		 * Error, reply with a NAK and EINVAL or the specified error
5255256Slh155975 		 */
5265256Slh155975 		miocnak(q, mp, 0, iocp->ioc_error == 0 ?
5275256Slh155975 		    EINVAL : iocp->ioc_error);
5285256Slh155975 		break;
5295256Slh155975 
5305256Slh155975 	case IOC_DONE:
5315256Slh155975 		/*
5325256Slh155975 		 * OK, reply already sent
5335256Slh155975 		 */
5345256Slh155975 		break;
5355256Slh155975 
5365256Slh155975 	case IOC_ACK:
5375256Slh155975 		/*
5385256Slh155975 		 * OK, reply with an ACK
5395256Slh155975 		 */
5405256Slh155975 		miocack(q, mp, 0, 0);
5415256Slh155975 		break;
5425256Slh155975 
5435256Slh155975 	case IOC_REPLY:
5445256Slh155975 		/*
5455256Slh155975 		 * OK, send prepared reply as ACK or NAK
5465256Slh155975 		 */
5475256Slh155975 		mp->b_datap->db_type = iocp->ioc_error == 0 ?
5485256Slh155975 		    M_IOCACK : M_IOCNAK;
5495256Slh155975 		qreply(q, mp);
5505256Slh155975 		break;
5515256Slh155975 	}
5525256Slh155975 }
5535256Slh155975 
5545256Slh155975 /*
5555256Slh155975  * Copy one packet from dma memory to mblk. Inc dma descriptor pointer.
5565256Slh155975  */
5575256Slh155975 static boolean_t
5585256Slh155975 amd8111s_recv_copy(struct LayerPointers *pLayerPointers, mblk_t **last_mp)
5595256Slh155975 {
5605256Slh155975 	int length = 0;
5615256Slh155975 	mblk_t *mp;
5625256Slh155975 	struct rx_desc *descriptor;
5635256Slh155975 	struct odl *pOdl = pLayerPointers->pOdl;
5645256Slh155975 	struct amd8111s_statistics *statistics = &pOdl->statistics;
5655256Slh155975 	struct nonphysical *pNonphysical = pLayerPointers->pMil
5665256Slh155975 	    ->pNonphysical;
5675256Slh155975 
5685256Slh155975 	mutex_enter(&pOdl->mdlRcvLock);
5695256Slh155975 	descriptor = pNonphysical->RxBufDescQRead->descriptor;
5705256Slh155975 	(void) ddi_dma_sync(pOdl->rx_desc_dma_handle,
5715256Slh155975 	    pNonphysical->RxBufDescQRead->descriptor -
5725256Slh155975 	    pNonphysical->RxBufDescQStart->descriptor,
5735256Slh155975 	    sizeof (struct rx_desc), DDI_DMA_SYNC_FORCPU);
5745256Slh155975 	if ((descriptor->Rx_OWN) == 0) {
5755256Slh155975 	/*
5765256Slh155975 	 * If the frame is received with errors, then set MCNT
5775256Slh155975 	 * of that pkt in ReceiveArray to 0. This packet would
5785256Slh155975 	 * be discarded later and not indicated to OS.
5795256Slh155975 	 */
5805256Slh155975 		if (descriptor->Rx_ERR) {
5815256Slh155975 			statistics->rx_desc_err ++;
5825256Slh155975 			descriptor->Rx_ERR = 0;
5835256Slh155975 			if (descriptor->Rx_FRAM == 1) {
5845256Slh155975 				statistics->rx_desc_err_FRAM ++;
5855256Slh155975 				descriptor->Rx_FRAM = 0;
5865256Slh155975 			}
5875256Slh155975 			if (descriptor->Rx_OFLO == 1) {
5885256Slh155975 				statistics->rx_desc_err_OFLO ++;
5895256Slh155975 				descriptor->Rx_OFLO = 0;
5905256Slh155975 				pOdl->rx_overflow_counter ++;
5915256Slh155975 				if ((pOdl->rx_overflow_counter > 5) &&
5925256Slh155975 				    (pOdl->pause_interval == 0)) {
5935256Slh155975 					statistics->rx_double_overflow ++;
5945256Slh155975 					mdlSendPause(pLayerPointers);
5955256Slh155975 					pOdl->rx_overflow_counter = 0;
5965256Slh155975 					pOdl->pause_interval = 25;
5975256Slh155975 				}
5985256Slh155975 			}
5995256Slh155975 			if (descriptor->Rx_CRC == 1) {
6005256Slh155975 				statistics->rx_desc_err_CRC ++;
6015256Slh155975 				descriptor->Rx_CRC = 0;
6025256Slh155975 			}
6035256Slh155975 			if (descriptor->Rx_BUFF == 1) {
6045256Slh155975 				statistics->rx_desc_err_BUFF ++;
6055256Slh155975 				descriptor->Rx_BUFF = 0;
6065256Slh155975 			}
6075256Slh155975 			goto Next_Descriptor;
6085256Slh155975 		}
6095256Slh155975 
6105256Slh155975 		/* Length of incoming packet */
6115256Slh155975 		if (pOdl->rx_fcs_stripped) {
6125256Slh155975 			length = descriptor->Rx_MCNT -4;
6135256Slh155975 		} else {
6145256Slh155975 			length = descriptor->Rx_MCNT;
6155256Slh155975 		}
6165256Slh155975 		if (length < 62) {
6175256Slh155975 			statistics->rx_error_zerosize ++;
6185256Slh155975 		}
6195256Slh155975 
6205256Slh155975 		if ((mp = allocb(length, BPRI_MED)) == NULL) {
6215256Slh155975 			statistics->rx_allocfail ++;
6225256Slh155975 			goto failed;
6235256Slh155975 		}
6245256Slh155975 		/* Copy from virtual address of incoming packet */
6255256Slh155975 		bcopy((long *)*(pNonphysical->RxBufDescQRead->USpaceMap),
6265256Slh155975 		    mp->b_rptr, length);
6275256Slh155975 		mp->b_wptr = mp->b_rptr + length;
6285256Slh155975 		statistics->rx_ok_packets ++;
6295256Slh155975 		if (*last_mp == NULL) {
6305256Slh155975 			*last_mp = mp;
6315256Slh155975 		} else {
6325256Slh155975 			(*last_mp)->b_next = mp;
6335256Slh155975 			*last_mp = mp;
6345256Slh155975 		}
6355256Slh155975 
6365256Slh155975 Next_Descriptor:
6375256Slh155975 		descriptor->Rx_MCNT = 0;
6385256Slh155975 		descriptor->Rx_SOP = 0;
6395256Slh155975 		descriptor->Rx_EOP = 0;
6405256Slh155975 		descriptor->Rx_PAM = 0;
6415256Slh155975 		descriptor->Rx_BAM = 0;
6425256Slh155975 		descriptor->TT = 0;
6435256Slh155975 		descriptor->Rx_OWN = 1;
6445256Slh155975 		pNonphysical->RxBufDescQRead->descriptor++;
6455256Slh155975 		pNonphysical->RxBufDescQRead->USpaceMap++;
6465256Slh155975 		if (pNonphysical->RxBufDescQRead->descriptor >
6475256Slh155975 		    pNonphysical->RxBufDescQEnd->descriptor) {
6485256Slh155975 			pNonphysical->RxBufDescQRead->descriptor =
6495256Slh155975 			    pNonphysical->RxBufDescQStart->descriptor;
6505256Slh155975 			pNonphysical->RxBufDescQRead->USpaceMap =
6515256Slh155975 			    pNonphysical->RxBufDescQStart->USpaceMap;
6525256Slh155975 		}
6535256Slh155975 		mutex_exit(&pOdl->mdlRcvLock);
6545256Slh155975 
6555256Slh155975 		return (B_TRUE);
6565256Slh155975 	}
6575256Slh155975 
6585256Slh155975 failed:
6595256Slh155975 	mutex_exit(&pOdl->mdlRcvLock);
6605256Slh155975 	return (B_FALSE);
6615256Slh155975 }
6625256Slh155975 
6635256Slh155975 /*
6645256Slh155975  * Get the received packets from NIC card and send them to GLD.
6655256Slh155975  */
6665256Slh155975 static void
6675256Slh155975 amd8111s_receive(struct LayerPointers *pLayerPointers)
6685256Slh155975 {
6695256Slh155975 	int numOfPkts = 0;
6705256Slh155975 	struct odl *pOdl;
6715256Slh155975 	mblk_t *ret_mp = NULL, *last_mp = NULL;
6725256Slh155975 
6735256Slh155975 	pOdl = pLayerPointers->pOdl;
6745256Slh155975 
6755256Slh155975 	rw_enter(&pOdl->chip_lock, RW_READER);
6765256Slh155975 	if (!pLayerPointers->run) {
6775256Slh155975 		rw_exit(&pOdl->chip_lock);
6785256Slh155975 		return;
6795256Slh155975 	}
6805256Slh155975 
6815256Slh155975 	if (pOdl->pause_interval > 0)
6825256Slh155975 		pOdl->pause_interval --;
6835256Slh155975 
6845256Slh155975 	while (numOfPkts < RX_RING_SIZE) {
6855256Slh155975 
6865256Slh155975 		if (!amd8111s_recv_copy(pLayerPointers, &last_mp)) {
6875256Slh155975 			break;
6885256Slh155975 		}
6895256Slh155975 		if (ret_mp == NULL)
6905256Slh155975 			ret_mp = last_mp;
6915256Slh155975 		numOfPkts++;
6925256Slh155975 	}
6935256Slh155975 
6945256Slh155975 	if (ret_mp) {
6955256Slh155975 		mac_rx(pOdl->mh, pOdl->mrh, ret_mp);
6965256Slh155975 	}
6975256Slh155975 
6985256Slh155975 	(void) ddi_dma_sync(pOdl->rx_desc_dma_handle, 0, 0,
6995256Slh155975 	    DDI_DMA_SYNC_FORDEV);
7005256Slh155975 
7015256Slh155975 	mdlReceive(pLayerPointers);
7025256Slh155975 
7035256Slh155975 	rw_exit(&pOdl->chip_lock);
7045256Slh155975 
7055256Slh155975 }
7065256Slh155975 
7075256Slh155975 /*
7085256Slh155975  * Print message in release-version driver.
7095256Slh155975  */
7105256Slh155975 static void
7115256Slh155975 amd8111s_log(struct LayerPointers *adapter, int level, char *fmt, ...)
7125256Slh155975 {
7135256Slh155975 	auto char name[32];
7145256Slh155975 	auto char buf[256];
7155256Slh155975 	va_list ap;
7165256Slh155975 
7175256Slh155975 	if (adapter != NULL) {
7185256Slh155975 		(void) sprintf(name, "amd8111s%d",
7195256Slh155975 		    ddi_get_instance(adapter->pOdl->devinfo));
7205256Slh155975 	} else {
7215256Slh155975 		(void) sprintf(name, "amd8111s");
7225256Slh155975 	}
7235256Slh155975 	va_start(ap, fmt);
7245256Slh155975 	(void) vsprintf(buf, fmt, ap);
7255256Slh155975 	va_end(ap);
7265256Slh155975 	cmn_err(level, "%s: %s", name, buf);
7275256Slh155975 }
7285256Slh155975 
7295256Slh155975 /*
7305256Slh155975  * To allocate & initilize all resources.
7315256Slh155975  * Called by amd8111s_attach().
7325256Slh155975  */
7335256Slh155975 static int
7345256Slh155975 amd8111s_odlInit(struct LayerPointers *pLayerPointers)
7355256Slh155975 {
7365256Slh155975 	unsigned long mem_req_array[MEM_REQ_MAX];
7375256Slh155975 	unsigned long mem_set_array[MEM_REQ_MAX];
7385256Slh155975 	unsigned long *pmem_req_array;
7395256Slh155975 	unsigned long *pmem_set_array;
7405256Slh155975 	int i, size;
7415256Slh155975 
7425256Slh155975 	for (i = 0; i < MEM_REQ_MAX; i++) {
7435256Slh155975 		mem_req_array[i] = 0;
7445256Slh155975 		mem_set_array[i] = 0;
7455256Slh155975 	}
7465256Slh155975 
7475256Slh155975 	milRequestResources(mem_req_array);
7485256Slh155975 
7495256Slh155975 	pmem_req_array = mem_req_array;
7505256Slh155975 	pmem_set_array = mem_set_array;
7515256Slh155975 	while (*pmem_req_array) {
7525256Slh155975 		switch (*pmem_req_array) {
7535256Slh155975 		case VIRTUAL:
7545256Slh155975 			*pmem_set_array = VIRTUAL;
7555256Slh155975 			pmem_req_array++;
7565256Slh155975 			pmem_set_array++;
7575256Slh155975 			*(pmem_set_array) = *(pmem_req_array);
7585256Slh155975 			pmem_set_array++;
7595256Slh155975 			*(pmem_set_array) = (unsigned long) kmem_zalloc(
7605256Slh155975 			    *(pmem_req_array), KM_NOSLEEP);
7615256Slh155975 			if (*pmem_set_array == NULL)
7625256Slh155975 				goto odl_init_failure;
7635256Slh155975 			break;
7645256Slh155975 		}
7655256Slh155975 		pmem_req_array++;
7665256Slh155975 		pmem_set_array++;
7675256Slh155975 	}
7685256Slh155975 
7695256Slh155975 	/*
7705256Slh155975 	 * Initilize memory on lower layers
7715256Slh155975 	 */
7725256Slh155975 	milSetResources(pLayerPointers, mem_set_array);
7735256Slh155975 
7745256Slh155975 	/* Allocate Rx/Tx descriptors */
7755256Slh155975 	if (amd8111s_allocate_descriptors(pLayerPointers) != B_TRUE) {
7765256Slh155975 		*pmem_set_array = NULL;
7775256Slh155975 		goto odl_init_failure;
7785256Slh155975 	}
7795256Slh155975 
7805256Slh155975 	/*
7815256Slh155975 	 * Allocate Rx buffer for each Rx descriptor. Then call mil layer
7825256Slh155975 	 * routine to fill physical address of Rx buffer into Rx descriptor.
7835256Slh155975 	 */
7845256Slh155975 	if (amd8111s_allocate_buffers(pLayerPointers) == B_FALSE) {
7855256Slh155975 		amd8111s_free_descriptors(pLayerPointers);
7865256Slh155975 		*pmem_set_array = NULL;
7875256Slh155975 		goto odl_init_failure;
7885256Slh155975 	}
7895256Slh155975 	milInitGlbds(pLayerPointers);
7905256Slh155975 
7915256Slh155975 	return (0);
7925256Slh155975 
7935256Slh155975 odl_init_failure:
7945256Slh155975 	/*
7955256Slh155975 	 * Free All memory allocated so far
7965256Slh155975 	 */
7975256Slh155975 	pmem_req_array = mem_set_array;
7985256Slh155975 	while ((*pmem_req_array) && (pmem_req_array != pmem_set_array)) {
7995256Slh155975 		switch (*pmem_req_array) {
8005256Slh155975 		case VIRTUAL:
8015256Slh155975 			pmem_req_array++;	/* Size */
8025256Slh155975 			size = *(pmem_req_array);
8035256Slh155975 			pmem_req_array++;	/* Virtual Address */
8045256Slh155975 			if (pmem_req_array == NULL)
8055256Slh155975 				return (1);
8065256Slh155975 			kmem_free((int *)*pmem_req_array, size);
8075256Slh155975 			break;
8085256Slh155975 		}
8095256Slh155975 		pmem_req_array++;
8105256Slh155975 	}
8115256Slh155975 	return (1);
8125256Slh155975 }
8135256Slh155975 
8145256Slh155975 /*
8155256Slh155975  * Allocate and initialize Tx/Rx descriptors
8165256Slh155975  */
8175256Slh155975 static boolean_t
8185256Slh155975 amd8111s_allocate_descriptors(struct LayerPointers *pLayerPointers)
8195256Slh155975 {
8205256Slh155975 	struct odl *pOdl = pLayerPointers->pOdl;
8215256Slh155975 	struct mil *pMil = pLayerPointers->pMil;
8225256Slh155975 	dev_info_t *devinfo = pOdl->devinfo;
8235256Slh155975 	uint_t length, count, i;
8245256Slh155975 	size_t real_length;
8255256Slh155975 
8265256Slh155975 	/*
8275256Slh155975 	 * Allocate Rx descriptors
8285256Slh155975 	 */
8295256Slh155975 	if (ddi_dma_alloc_handle(devinfo, &pcn_desc_dma_attr_t, DDI_DMA_SLEEP,
8305256Slh155975 	    NULL, &pOdl->rx_desc_dma_handle) != DDI_SUCCESS) {
8315256Slh155975 		amd8111s_log(pLayerPointers, CE_WARN,
8325256Slh155975 		    "ddi_dma_alloc_handle for Rx desc failed");
8335256Slh155975 		pOdl->rx_desc_dma_handle = NULL;
8345256Slh155975 		return (B_FALSE);
8355256Slh155975 	}
8365256Slh155975 
8375256Slh155975 	length = sizeof (struct rx_desc) * RX_RING_SIZE + ALIGNMENT;
8385256Slh155975 	if (ddi_dma_mem_alloc(pOdl->rx_desc_dma_handle, length,
8395256Slh155975 	    &pcn_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP,
8405256Slh155975 	    NULL, (caddr_t *)&pMil->Rx_desc_original, &real_length,
8415256Slh155975 	    &pOdl->rx_desc_acc_handle) != DDI_SUCCESS) {
8425256Slh155975 
8435256Slh155975 		amd8111s_log(pLayerPointers, CE_WARN,
8445256Slh155975 		    "ddi_dma_mem_handle for Rx desc failed");
8455256Slh155975 		ddi_dma_free_handle(&pOdl->rx_desc_dma_handle);
8465256Slh155975 		pOdl->rx_desc_dma_handle = NULL;
8475256Slh155975 		return (B_FALSE);
8485256Slh155975 	}
8495256Slh155975 
8505256Slh155975 	if (ddi_dma_addr_bind_handle(pOdl->rx_desc_dma_handle,
8515256Slh155975 	    NULL, (caddr_t)pMil->Rx_desc_original, real_length,
8525256Slh155975 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP,
8535256Slh155975 	    NULL, &pOdl->rx_desc_dma_cookie,
8545256Slh155975 	    &count) != DDI_SUCCESS) {
8555256Slh155975 
8565256Slh155975 		amd8111s_log(pLayerPointers, CE_WARN,
8575256Slh155975 		    "ddi_dma_addr_bind_handle for Rx desc failed");
8585256Slh155975 		ddi_dma_mem_free(&pOdl->rx_desc_acc_handle);
8595256Slh155975 		ddi_dma_free_handle(&pOdl->rx_desc_dma_handle);
8605256Slh155975 		pOdl->rx_desc_dma_handle = NULL;
8615256Slh155975 		return (B_FALSE);
8625256Slh155975 	}
8635256Slh155975 	ASSERT(count == 1);
8645256Slh155975 
8655256Slh155975 	/* Initialize Rx descriptors related variables */
8665256Slh155975 	pMil->Rx_desc = (struct rx_desc *)
8675256Slh155975 	    ((pMil->Rx_desc_original + ALIGNMENT) & ~ALIGNMENT);
8685256Slh155975 	pMil->Rx_desc_pa = (unsigned int)
8695256Slh155975 	    ((pOdl->rx_desc_dma_cookie.dmac_laddress + ALIGNMENT) & ~ALIGNMENT);
8705256Slh155975 
8715256Slh155975 	pLayerPointers->pMdl->init_blk->RDRA = pMil->Rx_desc_pa;
8725256Slh155975 
8735256Slh155975 
8745256Slh155975 	/*
8755256Slh155975 	 * Allocate Tx descriptors
8765256Slh155975 	 */
8775256Slh155975 	if (ddi_dma_alloc_handle(devinfo, &pcn_desc_dma_attr_t, DDI_DMA_SLEEP,
8785256Slh155975 	    NULL, &pOdl->tx_desc_dma_handle) != DDI_SUCCESS) {
8795256Slh155975 		amd8111s_log(pLayerPointers, CE_WARN,
8805256Slh155975 		    "ddi_dma_alloc_handle for Tx desc failed");
8815256Slh155975 		goto allocate_desc_fail;
8825256Slh155975 	}
8835256Slh155975 
8845256Slh155975 	length = sizeof (struct tx_desc) * TX_RING_SIZE + ALIGNMENT;
8855256Slh155975 	if (ddi_dma_mem_alloc(pOdl->tx_desc_dma_handle, length,
8865256Slh155975 	    &pcn_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP,
8875256Slh155975 	    NULL, (caddr_t *)&pMil->Tx_desc_original, &real_length,
8885256Slh155975 	    &pOdl->tx_desc_acc_handle) != DDI_SUCCESS) {
8895256Slh155975 
8905256Slh155975 		amd8111s_log(pLayerPointers, CE_WARN,
8915256Slh155975 		    "ddi_dma_mem_handle for Tx desc failed");
8925256Slh155975 		ddi_dma_free_handle(&pOdl->tx_desc_dma_handle);
8935256Slh155975 		goto allocate_desc_fail;
8945256Slh155975 	}
8955256Slh155975 
8965256Slh155975 	if (ddi_dma_addr_bind_handle(pOdl->tx_desc_dma_handle,
8975256Slh155975 	    NULL, (caddr_t)pMil->Tx_desc_original, real_length,
8985256Slh155975 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP,
8995256Slh155975 	    NULL, &pOdl->tx_desc_dma_cookie,
9005256Slh155975 	    &count) != DDI_SUCCESS) {
9015256Slh155975 
9025256Slh155975 		amd8111s_log(pLayerPointers, CE_WARN,
9035256Slh155975 		    "ddi_dma_addr_bind_handle for Tx desc failed");
9045256Slh155975 		ddi_dma_mem_free(&pOdl->tx_desc_acc_handle);
9055256Slh155975 		ddi_dma_free_handle(&pOdl->tx_desc_dma_handle);
9065256Slh155975 		goto allocate_desc_fail;
9075256Slh155975 	}
9085256Slh155975 	ASSERT(count == 1);
9095256Slh155975 	/* Set the DMA area to all zeros */
9105256Slh155975 	bzero((caddr_t)pMil->Tx_desc_original, length);
9115256Slh155975 
9125256Slh155975 	/* Initialize Tx descriptors related variables */
9135256Slh155975 	pMil->Tx_desc = (struct tx_desc *)
9145256Slh155975 	    ((pMil->Tx_desc_original + ALIGNMENT) & ~ALIGNMENT);
9155256Slh155975 	pMil->pNonphysical->TxDescQRead = pMil->Tx_desc;
9165256Slh155975 	pMil->pNonphysical->TxDescQWrite = pMil->Tx_desc;
9175256Slh155975 	pMil->pNonphysical->TxDescQStart = pMil->Tx_desc;
9185256Slh155975 	pMil->pNonphysical->TxDescQEnd = &(pMil->Tx_desc[TX_RING_SIZE -1]);
9195256Slh155975 
9205256Slh155975 	/* Physical Addr of Tx_desc_original & Tx_desc */
9215256Slh155975 	pLayerPointers->pMil->Tx_desc_pa =
9225256Slh155975 	    ((pOdl->tx_desc_dma_cookie.dmac_laddress + ALIGNMENT) &
9235256Slh155975 	    ~ALIGNMENT);
9245256Slh155975 
9255256Slh155975 	/* Setting the reserved bits in the tx descriptors */
9265256Slh155975 	for (i = 0; i < TX_RING_SIZE; i++) {
9275256Slh155975 		pMil->pNonphysical->TxDescQWrite->Tx_RES0 = 0x0f;
9285256Slh155975 		pMil->pNonphysical->TxDescQWrite->Tx_OWN = 0;
9295256Slh155975 		pMil->pNonphysical->TxDescQWrite++;
9305256Slh155975 	}
9315256Slh155975 	pMil->pNonphysical->TxDescQWrite = pMil->pNonphysical->TxDescQStart;
9325256Slh155975 
9335256Slh155975 	pLayerPointers->pMdl->init_blk->TDRA = pMil->Tx_desc_pa;
9345256Slh155975 
9355256Slh155975 	return (B_TRUE);
9365256Slh155975 
9375256Slh155975 allocate_desc_fail:
9385256Slh155975 	pOdl->tx_desc_dma_handle = NULL;
9395256Slh155975 	(void) ddi_dma_unbind_handle(pOdl->rx_desc_dma_handle);
9405256Slh155975 	ddi_dma_mem_free(&pOdl->rx_desc_acc_handle);
9415256Slh155975 	ddi_dma_free_handle(&pOdl->rx_desc_dma_handle);
9425256Slh155975 	pOdl->rx_desc_dma_handle = NULL;
9435256Slh155975 	return (B_FALSE);
9445256Slh155975 }
9455256Slh155975 
9465256Slh155975 /*
9475256Slh155975  * Free Tx/Rx descriptors
9485256Slh155975  */
9495256Slh155975 static void
9505256Slh155975 amd8111s_free_descriptors(struct LayerPointers *pLayerPointers)
9515256Slh155975 {
9525256Slh155975 	struct odl *pOdl = pLayerPointers->pOdl;
9535256Slh155975 
9545256Slh155975 	/* Free Rx descriptors */
9555256Slh155975 	if (pOdl->rx_desc_dma_handle) {
9565256Slh155975 		(void) ddi_dma_unbind_handle(pOdl->rx_desc_dma_handle);
9575256Slh155975 		ddi_dma_mem_free(&pOdl->rx_desc_acc_handle);
9585256Slh155975 		ddi_dma_free_handle(&pOdl->rx_desc_dma_handle);
9595256Slh155975 		pOdl->rx_desc_dma_handle = NULL;
9605256Slh155975 	}
9615256Slh155975 
9625256Slh155975 	/* Free Rx descriptors */
9635256Slh155975 	if (pOdl->tx_desc_dma_handle) {
9645256Slh155975 		(void) ddi_dma_unbind_handle(pOdl->tx_desc_dma_handle);
9655256Slh155975 		ddi_dma_mem_free(&pOdl->tx_desc_acc_handle);
9665256Slh155975 		ddi_dma_free_handle(&pOdl->tx_desc_dma_handle);
9675256Slh155975 		pOdl->tx_desc_dma_handle = NULL;
9685256Slh155975 	}
9695256Slh155975 }
9705256Slh155975 
9715256Slh155975 /*
9725256Slh155975  * Allocate Tx/Rx Ring buffer
9735256Slh155975  */
9745256Slh155975 static boolean_t
9755256Slh155975 amd8111s_alloc_dma_ringbuf(struct LayerPointers *pLayerPointers,
9765256Slh155975 			struct amd8111s_dma_ringbuf *pRing,
9775256Slh155975 			uint32_t ring_size, uint32_t msg_size)
9785256Slh155975 {
9795256Slh155975 	uint32_t idx, msg_idx = 0, msg_acc;
9805256Slh155975 	dev_info_t *devinfo = pLayerPointers->pOdl->devinfo;
9815256Slh155975 	size_t real_length;
9825256Slh155975 	uint_t count = 0;
9835256Slh155975 
9845256Slh155975 	ASSERT(pcn_buff_dma_attr_t.dma_attr_align == 1);
9855256Slh155975 	pRing->dma_buf_sz = msg_size;
9865256Slh155975 	pRing->ring_size = ring_size;
9875256Slh155975 	pRing->trunk_num = AMD8111S_SPLIT;
9885256Slh155975 	pRing->buf_sz = msg_size * ring_size;
9895256Slh155975 	if (ring_size < pRing->trunk_num)
9905256Slh155975 		pRing->trunk_num = ring_size;
9915256Slh155975 	ASSERT((pRing->buf_sz % pRing->trunk_num) == 0);
9925256Slh155975 
9935256Slh155975 	pRing->trunk_sz = pRing->buf_sz / pRing->trunk_num;
9945256Slh155975 	ASSERT((pRing->trunk_sz % pRing->dma_buf_sz) == 0);
9955256Slh155975 
9965256Slh155975 	pRing->msg_buf = kmem_zalloc(sizeof (struct amd8111s_msgbuf) *
9975256Slh155975 	    ring_size, KM_NOSLEEP);
9985256Slh155975 	pRing->dma_hdl = kmem_zalloc(sizeof (ddi_dma_handle_t) *
9995256Slh155975 	    pRing->trunk_num, KM_NOSLEEP);
10005256Slh155975 	pRing->acc_hdl = kmem_zalloc(sizeof (ddi_acc_handle_t) *
10015256Slh155975 	    pRing->trunk_num, KM_NOSLEEP);
10025256Slh155975 	pRing->dma_cookie = kmem_zalloc(sizeof (ddi_dma_cookie_t) *
10035256Slh155975 	    pRing->trunk_num, KM_NOSLEEP);
10045256Slh155975 	pRing->trunk_addr = kmem_zalloc(sizeof (caddr_t) *
10055256Slh155975 	    pRing->trunk_num, KM_NOSLEEP);
10065256Slh155975 	if (pRing->msg_buf == NULL || pRing->dma_hdl == NULL ||
10075256Slh155975 	    pRing->acc_hdl == NULL || pRing->trunk_addr == NULL ||
10085256Slh155975 	    pRing->dma_cookie == NULL) {
10095256Slh155975 		amd8111s_log(pLayerPointers, CE_NOTE,
10105256Slh155975 		    "kmem_zalloc failed");
10115256Slh155975 		goto failed;
10125256Slh155975 	}
10135256Slh155975 
10145256Slh155975 	for (idx = 0; idx < pRing->trunk_num; ++idx) {
10155256Slh155975 		if (ddi_dma_alloc_handle(devinfo, &pcn_buff_dma_attr_t,
10165256Slh155975 		    DDI_DMA_SLEEP, NULL, &(pRing->dma_hdl[idx]))
10175256Slh155975 		    != DDI_SUCCESS) {
10185256Slh155975 
10195256Slh155975 			amd8111s_log(pLayerPointers, CE_WARN,
10205256Slh155975 			    "ddi_dma_alloc_handle failed");
10215256Slh155975 			goto failed;
10225256Slh155975 		} else if (ddi_dma_mem_alloc(pRing->dma_hdl[idx],
10235256Slh155975 		    pRing->trunk_sz, &pcn_acc_attr, DDI_DMA_STREAMING,
10245256Slh155975 		    DDI_DMA_SLEEP, NULL,
10255256Slh155975 		    (caddr_t *)&(pRing->trunk_addr[idx]),
10265256Slh155975 		    (size_t *)(&real_length), &pRing->acc_hdl[idx])
10275256Slh155975 		    != DDI_SUCCESS) {
10285256Slh155975 
10295256Slh155975 			amd8111s_log(pLayerPointers, CE_WARN,
10305256Slh155975 			    "ddi_dma_mem_alloc failed");
10315256Slh155975 			goto failed;
10325256Slh155975 		} else if (real_length != pRing->trunk_sz) {
10335256Slh155975 			amd8111s_log(pLayerPointers, CE_WARN,
10345256Slh155975 			    "ddi_dma_mem_alloc failed");
10355256Slh155975 			goto failed;
10365256Slh155975 		} else if (ddi_dma_addr_bind_handle(pRing->dma_hdl[idx],
10375256Slh155975 		    NULL, (caddr_t)pRing->trunk_addr[idx], real_length,
10385256Slh155975 		    DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL,
10395256Slh155975 		    &pRing->dma_cookie[idx], &count) != DDI_DMA_MAPPED) {
10405256Slh155975 
10415256Slh155975 			amd8111s_log(pLayerPointers, CE_WARN,
10425256Slh155975 			    "ddi_dma_addr_bind_handle failed");
10435256Slh155975 			goto failed;
10445256Slh155975 		} else {
10455256Slh155975 			for (msg_acc = 0;
10465256Slh155975 			    msg_acc < pRing->trunk_sz / pRing->dma_buf_sz;
10475256Slh155975 			    ++ msg_acc) {
10485256Slh155975 				pRing->msg_buf[msg_idx].offset =
10495256Slh155975 				    msg_acc * pRing->dma_buf_sz;
10505256Slh155975 				pRing->msg_buf[msg_idx].vir_addr =
10515256Slh155975 				    pRing->trunk_addr[idx] +
10525256Slh155975 				    pRing->msg_buf[msg_idx].offset;
10535256Slh155975 				pRing->msg_buf[msg_idx].phy_addr =
10545256Slh155975 				    pRing->dma_cookie[idx].dmac_laddress +
10555256Slh155975 				    pRing->msg_buf[msg_idx].offset;
10565256Slh155975 				pRing->msg_buf[msg_idx].p_hdl =
10575256Slh155975 				    pRing->dma_hdl[idx];
10585256Slh155975 				msg_idx ++;
10595256Slh155975 			}
10605256Slh155975 		}
10615256Slh155975 	}
10625256Slh155975 
10635256Slh155975 	pRing->free = pRing->msg_buf;
10645256Slh155975 	pRing->next = pRing->msg_buf;
10655256Slh155975 	pRing->curr = pRing->msg_buf;
10665256Slh155975 
10675256Slh155975 	return (B_TRUE);
10685256Slh155975 failed:
10695256Slh155975 	amd8111s_free_dma_ringbuf(pRing);
10705256Slh155975 	return (B_FALSE);
10715256Slh155975 }
10725256Slh155975 
10735256Slh155975 /*
10745256Slh155975  * Free Tx/Rx ring buffer
10755256Slh155975  */
10765256Slh155975 static void
10775256Slh155975 amd8111s_free_dma_ringbuf(struct amd8111s_dma_ringbuf *pRing)
10785256Slh155975 {
10795256Slh155975 	int idx;
10805256Slh155975 
10815256Slh155975 	if (pRing->dma_cookie != NULL) {
10825256Slh155975 		for (idx = 0; idx < pRing->trunk_num; idx ++) {
10835256Slh155975 			if (pRing->dma_cookie[idx].dmac_laddress == 0) {
10845256Slh155975 				break;
10855256Slh155975 			}
10865256Slh155975 			(void) ddi_dma_unbind_handle(pRing->dma_hdl[idx]);
10875256Slh155975 		}
10885256Slh155975 		kmem_free(pRing->dma_cookie,
10895256Slh155975 		    sizeof (ddi_dma_cookie_t) * pRing->trunk_num);
10905256Slh155975 	}
10915256Slh155975 
10925256Slh155975 	if (pRing->acc_hdl != NULL) {
10935256Slh155975 		for (idx = 0; idx < pRing->trunk_num; idx ++) {
10945256Slh155975 			if (pRing->acc_hdl[idx] == NULL)
10955256Slh155975 				break;
10965256Slh155975 			ddi_dma_mem_free(&pRing->acc_hdl[idx]);
10975256Slh155975 		}
10985256Slh155975 		kmem_free(pRing->acc_hdl,
10995256Slh155975 		    sizeof (ddi_acc_handle_t) * pRing->trunk_num);
11005256Slh155975 	}
11015256Slh155975 
11025256Slh155975 	if (pRing->dma_hdl != NULL) {
11035256Slh155975 		for (idx = 0; idx < pRing->trunk_num; idx ++) {
11045256Slh155975 			if (pRing->dma_hdl[idx] == 0) {
11055256Slh155975 				break;
11065256Slh155975 			}
11075256Slh155975 			ddi_dma_free_handle(&pRing->dma_hdl[idx]);
11085256Slh155975 		}
11095256Slh155975 		kmem_free(pRing->dma_hdl,
11105256Slh155975 		    sizeof (ddi_dma_handle_t) * pRing->trunk_num);
11115256Slh155975 	}
11125256Slh155975 
11135256Slh155975 	if (pRing->msg_buf != NULL) {
11145256Slh155975 		kmem_free(pRing->msg_buf,
11155256Slh155975 		    sizeof (struct amd8111s_msgbuf) * pRing->ring_size);
11165256Slh155975 	}
11175256Slh155975 
11185256Slh155975 	if (pRing->trunk_addr != NULL) {
11195256Slh155975 		kmem_free(pRing->trunk_addr,
11205256Slh155975 		    sizeof (caddr_t) * pRing->trunk_num);
11215256Slh155975 	}
11225256Slh155975 
11235256Slh155975 	bzero(pRing, sizeof (*pRing));
11245256Slh155975 }
11255256Slh155975 
11265256Slh155975 
11275256Slh155975 /*
11285256Slh155975  * Allocate all Tx buffer.
11295256Slh155975  * Allocate a Rx buffer for each Rx descriptor. Then
11305256Slh155975  * call mil routine to fill physical address of Rx
11315256Slh155975  * buffer into Rx descriptors
11325256Slh155975  */
11335256Slh155975 static boolean_t
11345256Slh155975 amd8111s_allocate_buffers(struct LayerPointers *pLayerPointers)
11355256Slh155975 {
11365256Slh155975 	struct odl *pOdl = pLayerPointers->pOdl;
11375256Slh155975 
11385256Slh155975 	/*
11395256Slh155975 	 * Allocate rx Buffers
11405256Slh155975 	 */
11415256Slh155975 	if (amd8111s_alloc_dma_ringbuf(pLayerPointers, &pOdl->rx_buf,
11425256Slh155975 	    RX_RING_SIZE, RX_BUF_SIZE) == B_FALSE) {
11435256Slh155975 		amd8111s_log(pLayerPointers, CE_WARN,
11445256Slh155975 		    "amd8111s_alloc_dma_ringbuf for tx failed");
11455256Slh155975 		goto allocate_buf_fail;
11465256Slh155975 	}
11475256Slh155975 
11485256Slh155975 	/*
11495256Slh155975 	 * Allocate Tx buffers
11505256Slh155975 	 */
11515256Slh155975 	if (amd8111s_alloc_dma_ringbuf(pLayerPointers, &pOdl->tx_buf,
11525256Slh155975 	    TX_COALESC_SIZE, TX_BUF_SIZE) == B_FALSE) {
11535256Slh155975 		amd8111s_log(pLayerPointers, CE_WARN,
11545256Slh155975 		    "amd8111s_alloc_dma_ringbuf for tx failed");
11555256Slh155975 		goto allocate_buf_fail;
11565256Slh155975 	}
11575256Slh155975 
11585256Slh155975 	/*
11595256Slh155975 	 * Initilize the mil Queues
11605256Slh155975 	 */
11615256Slh155975 	milInitGlbds(pLayerPointers);
11625256Slh155975 
11635256Slh155975 	milInitRxQ(pLayerPointers);
11645256Slh155975 
11655256Slh155975 	return (B_TRUE);
11665256Slh155975 
11675256Slh155975 allocate_buf_fail:
11685256Slh155975 
11695256Slh155975 	amd8111s_log(pLayerPointers, CE_WARN,
11705256Slh155975 	    "amd8111s_allocate_buffers failed");
11715256Slh155975 	return (B_FALSE);
11725256Slh155975 }
11735256Slh155975 
11745256Slh155975 /*
11755256Slh155975  * Free all Rx/Tx buffer
11765256Slh155975  */
11775256Slh155975 
11785256Slh155975 static void
11795256Slh155975 amd8111s_free_buffers(struct LayerPointers *pLayerPointers)
11805256Slh155975 {
11815256Slh155975 	/* Free Tx buffers */
11825256Slh155975 	amd8111s_free_dma_ringbuf(&pLayerPointers->pOdl->tx_buf);
11835256Slh155975 
11845256Slh155975 	/* Free Rx Buffers */
11855256Slh155975 	amd8111s_free_dma_ringbuf(&pLayerPointers->pOdl->rx_buf);
11865256Slh155975 }
11875256Slh155975 
11885256Slh155975 /*
11895256Slh155975  * Try to recycle all the descriptors and Tx buffers
11905256Slh155975  * which are already freed by hardware.
11915256Slh155975  */
11925256Slh155975 static int
11935256Slh155975 amd8111s_recycle_tx(struct LayerPointers *pLayerPointers)
11945256Slh155975 {
11955256Slh155975 	struct nonphysical *pNonphysical;
11965256Slh155975 	uint32_t count = 0;
11975256Slh155975 
11985256Slh155975 	pNonphysical = pLayerPointers->pMil->pNonphysical;
11995256Slh155975 	while (pNonphysical->TxDescQRead->Tx_OWN == 0 &&
12005256Slh155975 	    pNonphysical->TxDescQRead != pNonphysical->TxDescQWrite) {
12015256Slh155975 		pLayerPointers->pOdl->tx_buf.free =
12025256Slh155975 		    NEXT(pLayerPointers->pOdl->tx_buf, free);
12035256Slh155975 		pNonphysical->TxDescQRead++;
12045256Slh155975 		if (pNonphysical->TxDescQRead > pNonphysical->TxDescQEnd) {
12055256Slh155975 			pNonphysical->TxDescQRead = pNonphysical->TxDescQStart;
12065256Slh155975 		}
12075256Slh155975 		count ++;
12085256Slh155975 	}
12095256Slh155975 
12105256Slh155975 	if (pLayerPointers->pMil->tx_reschedule)
12115256Slh155975 		ddi_trigger_softintr(pLayerPointers->pOdl->drain_id);
12125256Slh155975 
12135256Slh155975 	return (count);
12145256Slh155975 }
12155256Slh155975 
12165256Slh155975 /*
12175256Slh155975  * Get packets in the Tx buffer, then copy them to the send buffer.
12185256Slh155975  * Trigger hardware to send out packets.
12195256Slh155975  */
12205256Slh155975 static void
12215256Slh155975 amd8111s_send_serial(struct LayerPointers *pLayerPointers)
12225256Slh155975 {
12235256Slh155975 	struct nonphysical *pNonphysical;
12245256Slh155975 	uint32_t count;
12255256Slh155975 
12265256Slh155975 	pNonphysical = pLayerPointers->pMil->pNonphysical;
12275256Slh155975 
12285256Slh155975 	mutex_enter(&pLayerPointers->pOdl->mdlSendLock);
12295256Slh155975 
12305256Slh155975 	for (count = 0; count < AMD8111S_SEND_MAX; count ++) {
12315256Slh155975 		if (pLayerPointers->pOdl->tx_buf.curr ==
12325256Slh155975 		    pLayerPointers->pOdl->tx_buf.next) {
12335256Slh155975 			break;
12345256Slh155975 		}
12355256Slh155975 		/* to verify if it needs to recycle the tx Buf */
12365256Slh155975 		if (((pNonphysical->TxDescQWrite + 1 >
12375256Slh155975 		    pNonphysical->TxDescQEnd) ? pNonphysical->TxDescQStart :
12385256Slh155975 		    (pNonphysical->TxDescQWrite + 1)) ==
12395256Slh155975 		    pNonphysical->TxDescQRead)
12405256Slh155975 			if (amd8111s_recycle_tx(pLayerPointers) == 0) {
12415256Slh155975 				pLayerPointers->pOdl
12425256Slh155975 				    ->statistics.tx_no_descriptor ++;
12435256Slh155975 				break;
12445256Slh155975 			}
12455256Slh155975 
12465256Slh155975 		/* Fill packet length */
12475256Slh155975 		pNonphysical->TxDescQWrite->Tx_BCNT = (uint16_t)pLayerPointers
12485256Slh155975 		    ->pOdl->tx_buf.curr->msg_size;
12495256Slh155975 
12505256Slh155975 		/* Fill physical buffer address */
12515256Slh155975 		pNonphysical->TxDescQWrite->Tx_Base_Addr = (unsigned int)
12525256Slh155975 		    pLayerPointers->pOdl->tx_buf.curr->phy_addr;
12535256Slh155975 
12545256Slh155975 		pNonphysical->TxDescQWrite->Tx_SOP = 1;
12555256Slh155975 		pNonphysical->TxDescQWrite->Tx_EOP = 1;
12565256Slh155975 		pNonphysical->TxDescQWrite->Tx_ADD_FCS = 1;
12575256Slh155975 		pNonphysical->TxDescQWrite->Tx_LTINT = 1;
12585256Slh155975 		pNonphysical->TxDescQWrite->Tx_USPACE = 0;
12595256Slh155975 		pNonphysical->TxDescQWrite->Tx_OWN = 1;
12605256Slh155975 
12615256Slh155975 		pNonphysical->TxDescQWrite++;
12625256Slh155975 		if (pNonphysical->TxDescQWrite > pNonphysical->TxDescQEnd) {
12635256Slh155975 			pNonphysical->TxDescQWrite = pNonphysical->TxDescQStart;
12645256Slh155975 		}
12655256Slh155975 
12665256Slh155975 		pLayerPointers->pOdl->tx_buf.curr =
12675256Slh155975 		    NEXT(pLayerPointers->pOdl->tx_buf, curr);
12685256Slh155975 
12695256Slh155975 	}
12705256Slh155975 
12715256Slh155975 	pLayerPointers->pOdl->statistics.tx_ok_packets += count;
12725256Slh155975 
12735256Slh155975 	mutex_exit(&pLayerPointers->pOdl->mdlSendLock);
12745256Slh155975 
12755256Slh155975 	/* Call mdlTransmit to send the pkt out on the network */
12765256Slh155975 	mdlTransmit(pLayerPointers);
12775256Slh155975 
12785256Slh155975 }
12795256Slh155975 
12805256Slh155975 /*
12815256Slh155975  * Softintr entrance. try to send out packets in the Tx buffer.
12825256Slh155975  * If reschedule is True, call mac_tx_update to re-enable the
12835256Slh155975  * transmit
12845256Slh155975  */
12855256Slh155975 static uint_t
12865256Slh155975 amd8111s_send_drain(caddr_t arg)
12875256Slh155975 {
12885256Slh155975 	struct LayerPointers *pLayerPointers = (struct LayerPointers *)arg;
12895256Slh155975 
12905256Slh155975 	amd8111s_send_serial(pLayerPointers);
12915256Slh155975 
12925256Slh155975 	if (pLayerPointers->pMil->tx_reschedule &&
12935256Slh155975 	    NEXT(pLayerPointers->pOdl->tx_buf, next) !=
12945256Slh155975 	    pLayerPointers->pOdl->tx_buf.free) {
12955256Slh155975 		mac_tx_update(pLayerPointers->pOdl->mh);
12965256Slh155975 		pLayerPointers->pMil->tx_reschedule = B_FALSE;
12975256Slh155975 	}
12985256Slh155975 
12995256Slh155975 	return (DDI_INTR_CLAIMED);
13005256Slh155975 }
13015256Slh155975 
13025256Slh155975 /*
13035256Slh155975  * Get a Tx buffer
13045256Slh155975  */
13055256Slh155975 static struct amd8111s_msgbuf *
13065256Slh155975 amd8111s_getTxbuf(struct LayerPointers *pLayerPointers)
13075256Slh155975 {
13085256Slh155975 	struct amd8111s_msgbuf *tmp, *next;
13095256Slh155975 
13105256Slh155975 	mutex_enter(&pLayerPointers->pOdl->mdlSendLock);
13115256Slh155975 	next = NEXT(pLayerPointers->pOdl->tx_buf, next);
13125256Slh155975 	if (next == pLayerPointers->pOdl->tx_buf.free) {
13135256Slh155975 		tmp = NULL;
13145256Slh155975 	} else {
13155256Slh155975 		tmp = pLayerPointers->pOdl->tx_buf.next;
13165256Slh155975 		pLayerPointers->pOdl->tx_buf.next = next;
13175256Slh155975 	}
13185256Slh155975 	mutex_exit(&pLayerPointers->pOdl->mdlSendLock);
13195256Slh155975 
13205256Slh155975 	return (tmp);
13215256Slh155975 }
13225256Slh155975 
13235256Slh155975 static boolean_t
13245256Slh155975 amd8111s_send(struct LayerPointers *pLayerPointers, mblk_t *mp)
13255256Slh155975 {
13265256Slh155975 	struct odl *pOdl;
13275256Slh155975 	size_t frag_len;
13285256Slh155975 	mblk_t *tmp;
13295256Slh155975 	struct amd8111s_msgbuf *txBuf;
13305256Slh155975 	uint8_t *pMsg;
13315256Slh155975 
13325256Slh155975 	pOdl = pLayerPointers->pOdl;
13335256Slh155975 
13345256Slh155975 	/* alloc send buffer */
13355256Slh155975 	txBuf = amd8111s_getTxbuf(pLayerPointers);
13365256Slh155975 	if (txBuf == NULL) {
13375256Slh155975 		pOdl->statistics.tx_no_buffer ++;
13385256Slh155975 		pLayerPointers->pMil->tx_reschedule = B_TRUE;
13395256Slh155975 		amd8111s_send_serial(pLayerPointers);
13405256Slh155975 		return (B_FALSE);
13415256Slh155975 	}
13425256Slh155975 
13435256Slh155975 	/* copy packet to send buffer */
13445256Slh155975 	txBuf->msg_size = 0;
13455256Slh155975 	pMsg = (uint8_t *)txBuf->vir_addr;
13465256Slh155975 	for (tmp = mp; tmp; tmp = tmp->b_cont) {
13475256Slh155975 		frag_len = MBLKL(tmp);
13485256Slh155975 		bcopy(tmp->b_rptr, pMsg, frag_len);
13495256Slh155975 		txBuf->msg_size += frag_len;
13505256Slh155975 		pMsg += frag_len;
13515256Slh155975 	}
13525256Slh155975 	freemsg(mp);
13535256Slh155975 
13545256Slh155975 	amd8111s_send_serial(pLayerPointers);
13555256Slh155975 
13565256Slh155975 	return (B_TRUE);
13575256Slh155975 }
13585256Slh155975 
13595256Slh155975 /*
13605256Slh155975  * (GLD Entry Point) Send the message block to lower layer
13615256Slh155975  */
13625256Slh155975 static mblk_t *
13635256Slh155975 amd8111s_m_tx(void *arg, mblk_t *mp)
13645256Slh155975 {
13655256Slh155975 	struct LayerPointers *pLayerPointers = arg;
13665256Slh155975 	mblk_t *next;
13675256Slh155975 
13685256Slh155975 	rw_enter(&pLayerPointers->pOdl->chip_lock, RW_READER);
13695256Slh155975 	if (!pLayerPointers->run) {
13705256Slh155975 		pLayerPointers->pOdl->statistics.tx_afterunplumb ++;
13715256Slh155975 		freemsgchain(mp);
13725256Slh155975 		mp = NULL;
13735256Slh155975 	}
13745256Slh155975 
13755256Slh155975 	while (mp != NULL) {
13765256Slh155975 		next = mp->b_next;
13775256Slh155975 		mp->b_next = NULL;
13785256Slh155975 		if (!amd8111s_send(pLayerPointers, mp)) {
13795256Slh155975 			/* Send fail */
13805256Slh155975 			mp->b_next = next;
13815256Slh155975 			break;
13825256Slh155975 		}
13835256Slh155975 		mp = next;
13845256Slh155975 	}
13855256Slh155975 
13865256Slh155975 	rw_exit(&pLayerPointers->pOdl->chip_lock);
13875256Slh155975 	return (mp);
13885256Slh155975 }
13895256Slh155975 
13905256Slh155975 /*
13915256Slh155975  * (GLD Entry Point) Interrupt Service Routine
13925256Slh155975  */
13935256Slh155975 static uint_t
13945256Slh155975 amd8111s_intr(caddr_t arg)
13955256Slh155975 {
13965256Slh155975 	unsigned int intrCauses;
13975256Slh155975 	struct LayerPointers *pLayerPointers = (struct LayerPointers *)arg;
13985256Slh155975 
13995256Slh155975 	/* Read the interrupt status from mdl */
14005256Slh155975 	intrCauses = mdlReadInterrupt(pLayerPointers);
14015256Slh155975 
14025256Slh155975 	if (intrCauses == 0) {
14035256Slh155975 		pLayerPointers->pOdl->statistics.intr_OTHER ++;
14045256Slh155975 		return (DDI_INTR_UNCLAIMED);
14055256Slh155975 	}
14065256Slh155975 
14075256Slh155975 	if (intrCauses & LCINT) {
14085256Slh155975 		if (mdlReadLink(pLayerPointers) == LINK_UP) {
14095256Slh155975 			mdlGetActiveMediaInfo(pLayerPointers);
14105256Slh155975 			/* Link status changed */
14115256Slh155975 			if (pLayerPointers->pOdl->LinkStatus !=
14125256Slh155975 			    LINK_STATE_UP) {
14135256Slh155975 				pLayerPointers->pOdl->LinkStatus =
14145256Slh155975 				    LINK_STATE_UP;
14155256Slh155975 				mac_link_update(pLayerPointers->pOdl->mh,
14165256Slh155975 				    LINK_STATE_UP);
14175256Slh155975 			}
14185256Slh155975 		} else {
14195256Slh155975 			if (pLayerPointers->pOdl->LinkStatus !=
14205256Slh155975 			    LINK_STATE_DOWN) {
14215256Slh155975 				pLayerPointers->pOdl->LinkStatus =
14225256Slh155975 				    LINK_STATE_DOWN;
14235256Slh155975 				mac_link_update(pLayerPointers->pOdl->mh,
14245256Slh155975 				    LINK_STATE_DOWN);
14255256Slh155975 			}
14265256Slh155975 		}
14275256Slh155975 	}
14285256Slh155975 	/*
14295256Slh155975 	 * RINT0: Receive Interrupt is set by the controller after the last
14305256Slh155975 	 * descriptor of a receive frame for this ring has been updated by
14315256Slh155975 	 * writing a 0 to the OWNership bit.
14325256Slh155975 	 */
14335256Slh155975 	if (intrCauses & RINT0) {
14345256Slh155975 		pLayerPointers->pOdl->statistics.intr_RINT0 ++;
14355256Slh155975 		amd8111s_receive(pLayerPointers);
14365256Slh155975 	}
14375256Slh155975 
14385256Slh155975 	/*
14395256Slh155975 	 * TINT0: Transmit Interrupt is set by the controller after the OWN bit
14405256Slh155975 	 * in the last descriptor of a transmit frame in this particular ring
14415256Slh155975 	 * has been cleared to indicate the frame has been copied to the
14425256Slh155975 	 * transmit FIFO.
14435256Slh155975 	 */
14445256Slh155975 	if (intrCauses & TINT0) {
14455256Slh155975 		pLayerPointers->pOdl->statistics.intr_TINT0 ++;
14465256Slh155975 		/*
14475256Slh155975 		 * if desc ring is NULL and tx buf is not NULL, it should
14485256Slh155975 		 * drain tx buffer
14495256Slh155975 		 */
14505256Slh155975 		amd8111s_send_serial(pLayerPointers);
14515256Slh155975 	}
14525256Slh155975 
14535256Slh155975 	if (intrCauses & STINT) {
14545256Slh155975 		pLayerPointers->pOdl->statistics.intr_STINT ++;
14555256Slh155975 	}
14565256Slh155975 
14575256Slh155975 
14585256Slh155975 	return (DDI_INTR_CLAIMED);
14595256Slh155975 }
14605256Slh155975 
14615256Slh155975 /*
14625256Slh155975  * To re-initilize data structures.
14635256Slh155975  */
14645256Slh155975 static void
14655256Slh155975 amd8111s_sw_reset(struct LayerPointers *pLayerPointers)
14665256Slh155975 {
14675256Slh155975 	/* Reset all Tx/Rx queues and descriptors */
14685256Slh155975 	milResetTxQ(pLayerPointers);
14695256Slh155975 	milInitRxQ(pLayerPointers);
14705256Slh155975 }
14715256Slh155975 
14725256Slh155975 /*
14735256Slh155975  * Send all pending tx packets
14745256Slh155975  */
14755256Slh155975 static void
14765256Slh155975 amd8111s_tx_drain(struct LayerPointers *adapter)
14775256Slh155975 {
14785256Slh155975 	struct tx_desc *pTx_desc = adapter->pMil->pNonphysical->TxDescQStart;
14795256Slh155975 	int i, desc_count = 0;
14805256Slh155975 	for (i = 0; i < 30; i++) {
14815256Slh155975 		while ((pTx_desc->Tx_OWN == 0) && (desc_count < TX_RING_SIZE)) {
14825256Slh155975 			/* This packet has been transmitted */
14835256Slh155975 			pTx_desc ++;
14845256Slh155975 			desc_count ++;
14855256Slh155975 		}
14865256Slh155975 		if (desc_count == TX_RING_SIZE) {
14875256Slh155975 			break;
14885256Slh155975 		}
14895256Slh155975 		/* Wait 1 ms */
14905256Slh155975 		drv_usecwait(1000);
14915256Slh155975 	}
14925256Slh155975 	adapter->pOdl->statistics.tx_draintime = i;
14935256Slh155975 }
14945256Slh155975 
14955256Slh155975 /*
14965256Slh155975  * (GLD Entry Point) To start card will be called at
14975256Slh155975  * ifconfig plumb
14985256Slh155975  */
14995256Slh155975 static int
15005256Slh155975 amd8111s_m_start(void *arg)
15015256Slh155975 {
15025256Slh155975 	struct LayerPointers *pLayerPointers = arg;
15035256Slh155975 	struct odl *pOdl = pLayerPointers->pOdl;
15045256Slh155975 
15055256Slh155975 	amd8111s_sw_reset(pLayerPointers);
15065256Slh155975 	mdlHWReset(pLayerPointers);
15075256Slh155975 	rw_enter(&pOdl->chip_lock, RW_WRITER);
15085256Slh155975 	pLayerPointers->run = B_TRUE;
15095256Slh155975 	rw_exit(&pOdl->chip_lock);
15105256Slh155975 	return (0);
15115256Slh155975 }
15125256Slh155975 
15135256Slh155975 /*
15145256Slh155975  * (GLD Entry Point) To stop card will be called at
15155256Slh155975  * ifconfig unplumb
15165256Slh155975  */
15175256Slh155975 static void
15185256Slh155975 amd8111s_m_stop(void *arg)
15195256Slh155975 {
15205256Slh155975 	struct LayerPointers *pLayerPointers = (struct LayerPointers *)arg;
15215256Slh155975 	struct odl *pOdl = pLayerPointers->pOdl;
15225256Slh155975 
15235256Slh155975 	/* Ensure send all pending tx packets */
15245256Slh155975 	amd8111s_tx_drain(pLayerPointers);
15255256Slh155975 	/*
15265256Slh155975 	 * Stop the controller and disable the controller interrupt
15275256Slh155975 	 */
15285256Slh155975 	rw_enter(&pOdl->chip_lock, RW_WRITER);
15295256Slh155975 	mdlStopChip(pLayerPointers);
15305256Slh155975 	pLayerPointers->run = B_FALSE;
15315256Slh155975 	rw_exit(&pOdl->chip_lock);
15325256Slh155975 }
15335256Slh155975 
15345256Slh155975 /*
15355256Slh155975  *	To clean up all
15365256Slh155975  */
15375256Slh155975 static void
15385256Slh155975 amd8111s_free_resource(struct LayerPointers *pLayerPointers)
15395256Slh155975 {
15405256Slh155975 	unsigned long mem_free_array[100];
15415256Slh155975 	unsigned long *pmem_free_array, size;
15425256Slh155975 
15435256Slh155975 	/* Free Rx/Tx descriptors */
15445256Slh155975 	amd8111s_free_descriptors(pLayerPointers);
15455256Slh155975 
15465256Slh155975 	/* Free memory on lower layers */
15475256Slh155975 	milFreeResources(pLayerPointers, mem_free_array);
15485256Slh155975 	pmem_free_array = mem_free_array;
15495256Slh155975 	while (*pmem_free_array) {
15505256Slh155975 		switch (*pmem_free_array) {
15515256Slh155975 		case VIRTUAL:
15525256Slh155975 			size = *(++pmem_free_array);
15535256Slh155975 			pmem_free_array++;
15545256Slh155975 			kmem_free((void *)*(pmem_free_array), size);
15555256Slh155975 			break;
15565256Slh155975 		}
15575256Slh155975 		pmem_free_array++;
15585256Slh155975 	}
15595256Slh155975 
15605256Slh155975 	amd8111s_free_buffers(pLayerPointers);
15615256Slh155975 }
15625256Slh155975 
15635256Slh155975 /*
15645256Slh155975  * (GLD Enty pointer) To add/delete multi cast addresses
15655256Slh155975  *
15665256Slh155975  */
15675256Slh155975 static int
15685256Slh155975 amd8111s_m_multicst(void *arg, boolean_t add, const uint8_t *addr)
15695256Slh155975 {
15705256Slh155975 	struct LayerPointers *pLayerPointers = arg;
15715256Slh155975 
15725256Slh155975 	if (add) {
15735256Slh155975 		/* Add a multicast entry */
15745256Slh155975 		mdlAddMulticastAddress(pLayerPointers, (UCHAR *)addr);
15755256Slh155975 	} else {
15765256Slh155975 		/* Delete a multicast entry */
15775256Slh155975 		mdlDeleteMulticastAddress(pLayerPointers, (UCHAR *)addr);
15785256Slh155975 	}
15795256Slh155975 
15805256Slh155975 	return (0);
15815256Slh155975 }
15825256Slh155975 
15835256Slh155975 #ifdef AMD8111S_DEBUG
15845256Slh155975 /*
15855256Slh155975  * The size of MIB registers is only 32 bits. Dump them before one
15865256Slh155975  * of them overflows.
15875256Slh155975  */
15885256Slh155975 static void
15895256Slh155975 amd8111s_dump_mib(struct LayerPointers *pLayerPointers)
15905256Slh155975 {
15915256Slh155975 	struct amd8111s_statistics *adapterStat;
15925256Slh155975 
15935256Slh155975 	adapterStat = &pLayerPointers->pOdl->statistics;
15945256Slh155975 
15955256Slh155975 	adapterStat->mib_dump_counter ++;
15965256Slh155975 
15975256Slh155975 	/*
15985256Slh155975 	 * Rx Counters
15995256Slh155975 	 */
16005256Slh155975 	adapterStat->rx_mib_unicst_packets +=
16015256Slh155975 	    mdlReadMib(pLayerPointers, RcvUniCastPkts);
16025256Slh155975 	adapterStat->rx_mib_multicst_packets +=
16035256Slh155975 	    mdlReadMib(pLayerPointers, RcvMultiCastPkts);
16045256Slh155975 	adapterStat->rx_mib_broadcst_packets +=
16055256Slh155975 	    mdlReadMib(pLayerPointers, RcvBroadCastPkts);
16065256Slh155975 	adapterStat->rx_mib_macctrl_packets +=
16075256Slh155975 	    mdlReadMib(pLayerPointers, RcvMACCtrl);
16085256Slh155975 	adapterStat->rx_mib_flowctrl_packets +=
16095256Slh155975 	    mdlReadMib(pLayerPointers, RcvFlowCtrl);
16105256Slh155975 
16115256Slh155975 	adapterStat->rx_mib_bytes +=
16125256Slh155975 	    mdlReadMib(pLayerPointers, RcvOctets);
16135256Slh155975 	adapterStat->rx_mib_good_bytes +=
16145256Slh155975 	    mdlReadMib(pLayerPointers, RcvGoodOctets);
16155256Slh155975 
16165256Slh155975 	adapterStat->rx_mib_undersize_packets +=
16175256Slh155975 	    mdlReadMib(pLayerPointers, RcvUndersizePkts);
16185256Slh155975 	adapterStat->rx_mib_oversize_packets +=
16195256Slh155975 	    mdlReadMib(pLayerPointers, RcvOversizePkts);
16205256Slh155975 
16215256Slh155975 	adapterStat->rx_mib_drop_packets +=
16225256Slh155975 	    mdlReadMib(pLayerPointers, RcvDropPktsRing0);
16235256Slh155975 	adapterStat->rx_mib_align_err_packets +=
16245256Slh155975 	    mdlReadMib(pLayerPointers, RcvAlignmentErrors);
16255256Slh155975 	adapterStat->rx_mib_fcs_err_packets +=
16265256Slh155975 	    mdlReadMib(pLayerPointers, RcvFCSErrors);
16275256Slh155975 	adapterStat->rx_mib_symbol_err_packets +=
16285256Slh155975 	    mdlReadMib(pLayerPointers, RcvSymbolErrors);
16295256Slh155975 	adapterStat->rx_mib_miss_packets +=
16305256Slh155975 	    mdlReadMib(pLayerPointers, RcvMissPkts);
16315256Slh155975 
16325256Slh155975 	/*
16335256Slh155975 	 * Tx Counters
16345256Slh155975 	 */
16355256Slh155975 	adapterStat->tx_mib_packets +=
16365256Slh155975 	    mdlReadMib(pLayerPointers, XmtPackets);
16375256Slh155975 	adapterStat->tx_mib_multicst_packets +=
16385256Slh155975 	    mdlReadMib(pLayerPointers, XmtMultiCastPkts);
16395256Slh155975 	adapterStat->tx_mib_broadcst_packets +=
16405256Slh155975 	    mdlReadMib(pLayerPointers, XmtBroadCastPkts);
16415256Slh155975 	adapterStat->tx_mib_flowctrl_packets +=
16425256Slh155975 	    mdlReadMib(pLayerPointers, XmtFlowCtrl);
16435256Slh155975 
16445256Slh155975 	adapterStat->tx_mib_bytes +=
16455256Slh155975 	    mdlReadMib(pLayerPointers, XmtOctets);
16465256Slh155975 
16475256Slh155975 	adapterStat->tx_mib_defer_trans_packets +=
16485256Slh155975 	    mdlReadMib(pLayerPointers, XmtDeferredTransmit);
16495256Slh155975 	adapterStat->tx_mib_collision_packets +=
16505256Slh155975 	    mdlReadMib(pLayerPointers, XmtCollisions);
16515256Slh155975 	adapterStat->tx_mib_one_coll_packets +=
16525256Slh155975 	    mdlReadMib(pLayerPointers, XmtOneCollision);
16535256Slh155975 	adapterStat->tx_mib_multi_coll_packets +=
16545256Slh155975 	    mdlReadMib(pLayerPointers, XmtMultipleCollision);
16555256Slh155975 	adapterStat->tx_mib_late_coll_packets +=
16565256Slh155975 	    mdlReadMib(pLayerPointers, XmtLateCollision);
16575256Slh155975 	adapterStat->tx_mib_ex_coll_packets +=
16585256Slh155975 	    mdlReadMib(pLayerPointers, XmtExcessiveCollision);
16595256Slh155975 
16605256Slh155975 
16615256Slh155975 	/* Clear all MIB registers */
16625256Slh155975 	WRITE_REG16(pLayerPointers, pLayerPointers->pMdl->Mem_Address
16635256Slh155975 	    + MIB_ADDR, MIB_CLEAR);
16645256Slh155975 }
16655256Slh155975 #endif
16665256Slh155975 
16675256Slh155975 /*
16685256Slh155975  * (GLD Entry Point) set/unset promiscus mode
16695256Slh155975  */
16705256Slh155975 static int
16715256Slh155975 amd8111s_m_promisc(void *arg, boolean_t on)
16725256Slh155975 {
16735256Slh155975 	struct LayerPointers *pLayerPointers = arg;
16745256Slh155975 
16755256Slh155975 	if (on) {
16765256Slh155975 		mdlSetPromiscuous(pLayerPointers);
16775256Slh155975 	} else {
16785256Slh155975 		mdlDisablePromiscuous(pLayerPointers);
16795256Slh155975 	}
16805256Slh155975 
16815256Slh155975 	return (0);
16825256Slh155975 }
16835256Slh155975 
16845256Slh155975 /*
16855256Slh155975  * (Gld Entry point) Changes the Mac address of card
16865256Slh155975  */
16875256Slh155975 static int
16885256Slh155975 amd8111s_m_unicst(void *arg, const uint8_t *macaddr)
16895256Slh155975 {
16905256Slh155975 	struct LayerPointers *pLayerPointers = arg;
16915256Slh155975 
16925256Slh155975 	mdlDisableInterrupt(pLayerPointers);
16935256Slh155975 	mdlSetMacAddress(pLayerPointers, (unsigned char *)macaddr);
16945256Slh155975 	mdlEnableInterrupt(pLayerPointers);
16955256Slh155975 
16965256Slh155975 	return (0);
16975256Slh155975 }
16985256Slh155975 
16995256Slh155975 /*
17005256Slh155975  * Reset the card
17015256Slh155975  */
17025256Slh155975 void
17035256Slh155975 amd8111s_reset(struct LayerPointers *pLayerPointers)
17045256Slh155975 {
17055256Slh155975 	amd8111s_sw_reset(pLayerPointers);
17065256Slh155975 	mdlHWReset(pLayerPointers);
17075256Slh155975 }
17085256Slh155975 
17095256Slh155975 /*
17105256Slh155975  * attach(9E) -- Attach a device to the system
17115256Slh155975  *
17125256Slh155975  * Called once for each board after successfully probed.
17135256Slh155975  * will do
17145256Slh155975  * 	a. creating minor device node for the instance.
17155256Slh155975  *	b. allocate & Initilize four layers (call odlInit)
17165256Slh155975  *	c. get MAC address
17175256Slh155975  *	d. initilize pLayerPointers to gld private pointer
17185256Slh155975  *	e. register with GLD
17195256Slh155975  * if any action fails does clean up & returns DDI_FAILURE
17205256Slh155975  * else retursn DDI_SUCCESS
17215256Slh155975  */
17225256Slh155975 static int
17235256Slh155975 amd8111s_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
17245256Slh155975 {
17255256Slh155975 	mac_register_t *macp;
17265256Slh155975 	struct LayerPointers *pLayerPointers;
17275256Slh155975 	struct odl *pOdl;
17285256Slh155975 	ddi_acc_handle_t *pci_handle;
17295256Slh155975 	ddi_device_acc_attr_t dev_attr;
17305256Slh155975 	caddr_t addrp = NULL;
17315256Slh155975 
17325256Slh155975 	switch (cmd) {
17335256Slh155975 	case DDI_ATTACH:
17345256Slh155975 		break;
17355256Slh155975 	default:
17365256Slh155975 		return (DDI_FAILURE);
17375256Slh155975 	}
17385256Slh155975 
17395256Slh155975 	pLayerPointers = (struct LayerPointers *)
17405256Slh155975 	    kmem_zalloc(sizeof (struct LayerPointers), KM_SLEEP);
17415256Slh155975 	amd8111sadapter = pLayerPointers;
17425256Slh155975 
17435256Slh155975 	/* Get device instance number */
17445256Slh155975 	pLayerPointers->instance = ddi_get_instance(devinfo);
17455256Slh155975 	ddi_set_driver_private(devinfo, (caddr_t)pLayerPointers);
17465256Slh155975 
17475256Slh155975 	pOdl = (struct odl *)kmem_zalloc(sizeof (struct odl), KM_SLEEP);
17485256Slh155975 	pLayerPointers->pOdl = pOdl;
17495256Slh155975 
17505256Slh155975 	pOdl->devinfo = devinfo;
17515256Slh155975 
17525256Slh155975 	/*
17535256Slh155975 	 * Here, we only allocate memory for struct odl and initilize it.
17545256Slh155975 	 * All other memory allocation & initilization will be done in odlInit
17555256Slh155975 	 * later on this routine.
17565256Slh155975 	 */
17575256Slh155975 	if (ddi_get_iblock_cookie(devinfo, 0, &pLayerPointers->pOdl->iblock)
17585256Slh155975 	    != DDI_SUCCESS) {
17595256Slh155975 		amd8111s_log(pLayerPointers, CE_NOTE,
17605256Slh155975 		    "attach: get iblock cookies failed");
17615256Slh155975 		goto attach_failure;
17625256Slh155975 	}
17635256Slh155975 
17645256Slh155975 	rw_init(&pOdl->chip_lock, NULL, RW_DRIVER, (void *)pOdl->iblock);
17655256Slh155975 	mutex_init(&pOdl->mdlSendLock, "amd8111s Send Protection Lock",
17665256Slh155975 	    MUTEX_DRIVER, (void *)pOdl->iblock);
17675256Slh155975 	mutex_init(&pOdl->mdlRcvLock, "amd8111s Rcv Protection Lock",
17685256Slh155975 	    MUTEX_DRIVER, (void *)pOdl->iblock);
17695256Slh155975 
17705256Slh155975 	/* Setup PCI space */
17715256Slh155975 	if (pci_config_setup(devinfo, &pOdl->pci_handle) != DDI_SUCCESS) {
17725256Slh155975 		return (DDI_FAILURE);
17735256Slh155975 	}
17745256Slh155975 	pLayerPointers->attach_progress = AMD8111S_ATTACH_PCI;
17755256Slh155975 	pci_handle = &pOdl->pci_handle;
17765256Slh155975 
17775256Slh155975 	pOdl->vendor_id = pci_config_get16(*pci_handle, PCI_CONF_VENID);
17785256Slh155975 	pOdl->device_id = pci_config_get16(*pci_handle, PCI_CONF_DEVID);
17795256Slh155975 
17805256Slh155975 	/*
17815256Slh155975 	 * Allocate and initialize all resource and map device registers.
17825256Slh155975 	 * If failed, it returns a non-zero value.
17835256Slh155975 	 */
17845256Slh155975 	if (amd8111s_odlInit(pLayerPointers) != 0) {
17855256Slh155975 		goto attach_failure;
17865256Slh155975 	}
17875256Slh155975 	pLayerPointers->attach_progress |= AMD8111S_ATTACH_RESOURCE;
17885256Slh155975 
17895256Slh155975 	dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
17905256Slh155975 	dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
17915256Slh155975 	dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
17925256Slh155975 
17935256Slh155975 	if (ddi_regs_map_setup(devinfo, 1, &addrp, 0,  4096, &dev_attr,
17945256Slh155975 	    &(pLayerPointers->pOdl->MemBasehandle)) != 0) {
17955256Slh155975 		amd8111s_log(pLayerPointers, CE_NOTE,
17965256Slh155975 		    "attach: ddi_regs_map_setup failed");
17975256Slh155975 		goto attach_failure;
17985256Slh155975 	}
17995256Slh155975 	pLayerPointers->pMdl->Mem_Address = (unsigned long)addrp;
18005256Slh155975 
18015256Slh155975 	/* Initialize HW */
18025256Slh155975 	mdlOpen(pLayerPointers);
18035256Slh155975 	mdlGetActiveMediaInfo(pLayerPointers);
18045256Slh155975 	pLayerPointers->attach_progress |= AMD8111S_ATTACH_REGS;
18055256Slh155975 
18065256Slh155975 	/*
18075256Slh155975 	 * Setup the interrupt
18085256Slh155975 	 */
18095256Slh155975 	if (ddi_add_intr(devinfo, 0, &pOdl->iblock, 0, amd8111s_intr,
18105256Slh155975 	    (caddr_t)pLayerPointers) != DDI_SUCCESS) {
18115256Slh155975 		goto attach_failure;
18125256Slh155975 	}
18135256Slh155975 	pLayerPointers->attach_progress |= AMD8111S_ATTACH_INTRADDED;
18145256Slh155975 
18155256Slh155975 	/*
18165256Slh155975 	 * Setup soft intr
18175256Slh155975 	 */
18185256Slh155975 	if (ddi_add_softintr(devinfo, DDI_SOFTINT_LOW, &pOdl->drain_id,
18195256Slh155975 	    NULL, NULL, amd8111s_send_drain,
18205256Slh155975 	    (caddr_t)pLayerPointers) != DDI_SUCCESS) {
18215256Slh155975 		goto attach_failure;
18225256Slh155975 	}
18235256Slh155975 	pLayerPointers->attach_progress |= AMD8111S_ATTACH_RESCHED;
18245256Slh155975 
18255256Slh155975 	/*
18265256Slh155975 	 * Initilize the mac structure
18275256Slh155975 	 */
18285256Slh155975 	if ((macp = mac_alloc(MAC_VERSION)) == NULL)
18295256Slh155975 		goto attach_failure;
18305256Slh155975 
18315256Slh155975 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
18325256Slh155975 	macp->m_driver = pLayerPointers;
18335256Slh155975 	macp->m_dip = devinfo;
18345256Slh155975 	/* Get MAC address */
18355256Slh155975 	mdlGetMacAddress(pLayerPointers, (unsigned char *)pOdl->MacAddress);
18365256Slh155975 	macp->m_src_addr = pOdl->MacAddress;
18375256Slh155975 	macp->m_callbacks = &amd8111s_m_callbacks;
18385256Slh155975 	macp->m_min_sdu = 0;
18395256Slh155975 	/* 1518 - 14 (ether header) - 4 (CRC) */
18405256Slh155975 	macp->m_max_sdu = ETHERMTU;
1841*5895Syz147064 	macp->m_margin = VLAN_TAGSZ;
18425256Slh155975 
18435256Slh155975 	/*
18445256Slh155975 	 * Finally, we're ready to register ourselves with the MAC layer
18455256Slh155975 	 * interface; if this succeeds, we're ready to start.
18465256Slh155975 	 */
18475256Slh155975 	if (mac_register(macp, &pOdl->mh) != DDI_SUCCESS) {
18485256Slh155975 		mac_free(macp);
18495256Slh155975 		goto attach_failure;
18505256Slh155975 	}
18515256Slh155975 	mac_free(macp);
18525256Slh155975 
18535256Slh155975 	pLayerPointers->attach_progress |= AMD8111S_ATTACH_MACREGED;
18545256Slh155975 
18555256Slh155975 	return (DDI_SUCCESS);
18565256Slh155975 
18575256Slh155975 attach_failure:
18585256Slh155975 	(void) amd8111s_unattach(devinfo, pLayerPointers);
18595256Slh155975 	return (DDI_FAILURE);
18605256Slh155975 
18615256Slh155975 }
18625256Slh155975 
18635256Slh155975 /*
18645256Slh155975  * detach(9E) -- Detach a device from the system
18655256Slh155975  *
18665256Slh155975  * It is called for each device instance when the system is preparing to
18675256Slh155975  * unload a dynamically unloadable driver.
18685256Slh155975  * will Do
18695256Slh155975  * 	a. check if any driver buffers are held by OS.
18705256Slh155975  *	b. do clean up of all allocated memory if it is not in use by OS.
18715256Slh155975  *	c. un register with GLD
18725256Slh155975  *	d. return DDI_SUCCESS on succes full free & unregister
18735256Slh155975  *	else GLD_FAILURE
18745256Slh155975  */
18755256Slh155975 static int
18765256Slh155975 amd8111s_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
18775256Slh155975 {
18785256Slh155975 	struct LayerPointers *pLayerPointers;
18795256Slh155975 
18805256Slh155975 	switch (cmd) {
18815256Slh155975 	case DDI_DETACH:
18825256Slh155975 		break;
18835256Slh155975 	default:
18845256Slh155975 		return (DDI_FAILURE);
18855256Slh155975 	}
18865256Slh155975 
18875256Slh155975 	/*
18885256Slh155975 	 * Get the driver private (struct LayerPointers *) structure
18895256Slh155975 	 */
18905256Slh155975 	if ((pLayerPointers = (struct LayerPointers *)ddi_get_driver_private
18915256Slh155975 	    (devinfo)) == NULL) {
18925256Slh155975 		return (DDI_FAILURE);
18935256Slh155975 	}
18945256Slh155975 
18955256Slh155975 	return (amd8111s_unattach(devinfo, pLayerPointers));
18965256Slh155975 }
18975256Slh155975 
18985256Slh155975 static int
18995256Slh155975 amd8111s_unattach(dev_info_t *devinfo, struct LayerPointers *pLayerPointers)
19005256Slh155975 {
19015256Slh155975 	struct odl *pOdl = pLayerPointers->pOdl;
19025256Slh155975 
19035256Slh155975 	if (pLayerPointers->attach_progress & AMD8111S_ATTACH_MACREGED) {
19045256Slh155975 		/* Unregister driver from the GLD interface */
19055256Slh155975 		if (mac_unregister(pOdl->mh) != DDI_SUCCESS) {
19065256Slh155975 			return (DDI_FAILURE);
19075256Slh155975 		}
19085256Slh155975 	}
19095256Slh155975 
19105256Slh155975 	if (pLayerPointers->attach_progress & AMD8111S_ATTACH_INTRADDED) {
19115256Slh155975 		ddi_remove_intr(devinfo, 0, pOdl->iblock);
19125256Slh155975 	}
19135256Slh155975 
19145256Slh155975 	if (pLayerPointers->attach_progress & AMD8111S_ATTACH_RESCHED) {
19155256Slh155975 		ddi_remove_softintr(pOdl->drain_id);
19165256Slh155975 	}
19175256Slh155975 
19185256Slh155975 	if (pLayerPointers->attach_progress & AMD8111S_ATTACH_REGS) {
19195256Slh155975 		/* Stop HW */
19205256Slh155975 		mdlStopChip(pLayerPointers);
19215256Slh155975 		ddi_regs_map_free(&(pOdl->MemBasehandle));
19225256Slh155975 	}
19235256Slh155975 
19245256Slh155975 	if (pLayerPointers->attach_progress & AMD8111S_ATTACH_RESOURCE) {
19255256Slh155975 		/* Free All memory allocated */
19265256Slh155975 		amd8111s_free_resource(pLayerPointers);
19275256Slh155975 	}
19285256Slh155975 
19295256Slh155975 	if (pLayerPointers->attach_progress & AMD8111S_ATTACH_PCI) {
19305256Slh155975 		pci_config_teardown(&pOdl->pci_handle);
19315256Slh155975 		mutex_destroy(&pOdl->mdlSendLock);
19325256Slh155975 		mutex_destroy(&pOdl->mdlRcvLock);
19335256Slh155975 		rw_destroy(&pOdl->chip_lock);
19345256Slh155975 	}
19355256Slh155975 
19365256Slh155975 	kmem_free(pOdl, sizeof (struct odl));
19375256Slh155975 	kmem_free(pLayerPointers, sizeof (struct LayerPointers));
19385256Slh155975 
19395256Slh155975 	return (DDI_SUCCESS);
19405256Slh155975 }
19415256Slh155975 
19425256Slh155975 /*
19435256Slh155975  * (GLD Entry Point)GLD will call this entry point perodicaly to
19445256Slh155975  * get driver statistices.
19455256Slh155975  */
19465256Slh155975 static int
19475256Slh155975 amd8111s_m_stat(void *arg, uint_t stat, uint64_t *val)
19485256Slh155975 {
19495256Slh155975 	struct LayerPointers *pLayerPointers = arg;
19505256Slh155975 	struct amd8111s_statistics *adapterStat;
19515256Slh155975 
19525256Slh155975 	adapterStat = &pLayerPointers->pOdl->statistics;
19535256Slh155975 
19545256Slh155975 	switch (stat) {
19555256Slh155975 
19565256Slh155975 	/*
19575256Slh155975 	 * Current Status
19585256Slh155975 	 */
19595256Slh155975 	case MAC_STAT_IFSPEED:
19605256Slh155975 		*val = 	pLayerPointers->pMdl->Speed * 1000000;
19615256Slh155975 		break;
19625256Slh155975 
19635256Slh155975 	case ETHER_STAT_LINK_DUPLEX:
19645256Slh155975 		if (pLayerPointers->pMdl->FullDuplex) {
19655256Slh155975 			*val = LINK_DUPLEX_FULL;
19665256Slh155975 		} else {
19675256Slh155975 			*val = LINK_DUPLEX_HALF;
19685256Slh155975 		}
19695256Slh155975 		break;
19705256Slh155975 
19715256Slh155975 	/*
19725256Slh155975 	 * Capabilities
19735256Slh155975 	 */
19745256Slh155975 	case ETHER_STAT_CAP_1000FDX:
19755256Slh155975 		*val = 0;
19765256Slh155975 		break;
19775256Slh155975 
19785256Slh155975 	case ETHER_STAT_CAP_1000HDX:
19795256Slh155975 		*val = 0;
19805256Slh155975 		break;
19815256Slh155975 
19825256Slh155975 	case ETHER_STAT_CAP_100FDX:
19835256Slh155975 		*val = 1;
19845256Slh155975 		break;
19855256Slh155975 
19865256Slh155975 	case ETHER_STAT_CAP_100HDX:
19875256Slh155975 		*val = 1;
19885256Slh155975 		break;
19895256Slh155975 
19905256Slh155975 	case ETHER_STAT_CAP_10FDX:
19915256Slh155975 		*val = 1;
19925256Slh155975 		break;
19935256Slh155975 
19945256Slh155975 	case ETHER_STAT_CAP_10HDX:
19955256Slh155975 		*val = 1;
19965256Slh155975 		break;
19975256Slh155975 
19985256Slh155975 	case ETHER_STAT_CAP_ASMPAUSE:
19995256Slh155975 		*val = 1;
20005256Slh155975 		break;
20015256Slh155975 
20025256Slh155975 	case ETHER_STAT_CAP_PAUSE:
20035256Slh155975 		*val = 1;
20045256Slh155975 		break;
20055256Slh155975 
20065256Slh155975 	case ETHER_STAT_CAP_AUTONEG:
20075256Slh155975 		*val = 1;
20085256Slh155975 		break;
20095256Slh155975 
20105256Slh155975 	case ETHER_STAT_ADV_CAP_1000FDX:
20115256Slh155975 		*val = 0;
20125256Slh155975 		break;
20135256Slh155975 
20145256Slh155975 	case ETHER_STAT_ADV_CAP_1000HDX:
20155256Slh155975 		*val = 0;
20165256Slh155975 		break;
20175256Slh155975 
20185256Slh155975 	case ETHER_STAT_ADV_CAP_100FDX:
20195256Slh155975 		*val = 1;
20205256Slh155975 		break;
20215256Slh155975 
20225256Slh155975 	case ETHER_STAT_ADV_CAP_100HDX:
20235256Slh155975 		*val = 1;
20245256Slh155975 		break;
20255256Slh155975 
20265256Slh155975 	case ETHER_STAT_ADV_CAP_10FDX:
20275256Slh155975 		*val = 1;
20285256Slh155975 		break;
20295256Slh155975 
20305256Slh155975 	case ETHER_STAT_ADV_CAP_10HDX:
20315256Slh155975 		*val = 1;
20325256Slh155975 		break;
20335256Slh155975 
20345256Slh155975 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
20355256Slh155975 		*val = 1;
20365256Slh155975 		break;
20375256Slh155975 
20385256Slh155975 	case ETHER_STAT_ADV_CAP_PAUSE:
20395256Slh155975 		*val = 1;
20405256Slh155975 		break;
20415256Slh155975 
20425256Slh155975 	case ETHER_STAT_ADV_CAP_AUTONEG:
20435256Slh155975 		*val = 1;
20445256Slh155975 		break;
20455256Slh155975 
20465256Slh155975 	/*
20475256Slh155975 	 * Rx Counters
20485256Slh155975 	 */
20495256Slh155975 	case MAC_STAT_IPACKETS:
20505256Slh155975 		*val = adapterStat->rx_mib_unicst_packets +
20515256Slh155975 		    adapterStat->rx_mib_multicst_packets +
20525256Slh155975 		    adapterStat->rx_mib_broadcst_packets +
20535256Slh155975 		    mdlReadMib(pLayerPointers, RcvUniCastPkts) +
20545256Slh155975 		    mdlReadMib(pLayerPointers, RcvMultiCastPkts) +
20555256Slh155975 		    mdlReadMib(pLayerPointers, RcvBroadCastPkts);
20565256Slh155975 		break;
20575256Slh155975 
20585256Slh155975 	case MAC_STAT_RBYTES:
20595256Slh155975 		*val = adapterStat->rx_mib_bytes +
20605256Slh155975 		    mdlReadMib(pLayerPointers, RcvOctets);
20615256Slh155975 		break;
20625256Slh155975 
20635256Slh155975 	case MAC_STAT_MULTIRCV:
20645256Slh155975 		*val = adapterStat->rx_mib_multicst_packets +
20655256Slh155975 		    mdlReadMib(pLayerPointers, RcvMultiCastPkts);
20665256Slh155975 		break;
20675256Slh155975 
20685256Slh155975 	case MAC_STAT_BRDCSTRCV:
20695256Slh155975 		*val = adapterStat->rx_mib_broadcst_packets +
20705256Slh155975 		    mdlReadMib(pLayerPointers, RcvBroadCastPkts);
20715256Slh155975 		break;
20725256Slh155975 
20735256Slh155975 	case MAC_STAT_NORCVBUF:
20745256Slh155975 		*val = adapterStat->rx_allocfail +
20755256Slh155975 		    adapterStat->rx_mib_drop_packets +
20765256Slh155975 		    mdlReadMib(pLayerPointers, RcvDropPktsRing0);
20775256Slh155975 		break;
20785256Slh155975 
20795256Slh155975 	case MAC_STAT_IERRORS:
20805256Slh155975 		*val = adapterStat->rx_mib_align_err_packets +
20815256Slh155975 		    adapterStat->rx_mib_fcs_err_packets +
20825256Slh155975 		    adapterStat->rx_mib_symbol_err_packets +
20835256Slh155975 		    mdlReadMib(pLayerPointers, RcvAlignmentErrors) +
20845256Slh155975 		    mdlReadMib(pLayerPointers, RcvFCSErrors) +
20855256Slh155975 		    mdlReadMib(pLayerPointers, RcvSymbolErrors);
20865256Slh155975 		break;
20875256Slh155975 
20885256Slh155975 	case ETHER_STAT_ALIGN_ERRORS:
20895256Slh155975 		*val = adapterStat->rx_mib_align_err_packets +
20905256Slh155975 		    mdlReadMib(pLayerPointers, RcvAlignmentErrors);
20915256Slh155975 		break;
20925256Slh155975 
20935256Slh155975 	case ETHER_STAT_FCS_ERRORS:
20945256Slh155975 		*val = adapterStat->rx_mib_fcs_err_packets +
20955256Slh155975 		    mdlReadMib(pLayerPointers, RcvFCSErrors);
20965256Slh155975 		break;
20975256Slh155975 
20985256Slh155975 	/*
20995256Slh155975 	 * Tx Counters
21005256Slh155975 	 */
21015256Slh155975 	case MAC_STAT_OPACKETS:
21025256Slh155975 		*val = adapterStat->tx_mib_packets +
21035256Slh155975 		    mdlReadMib(pLayerPointers, XmtPackets);
21045256Slh155975 		break;
21055256Slh155975 
21065256Slh155975 	case MAC_STAT_OBYTES:
21075256Slh155975 		*val = adapterStat->tx_mib_bytes +
21085256Slh155975 		    mdlReadMib(pLayerPointers, XmtOctets);
21095256Slh155975 		break;
21105256Slh155975 
21115256Slh155975 	case MAC_STAT_MULTIXMT:
21125256Slh155975 		*val = adapterStat->tx_mib_multicst_packets +
21135256Slh155975 		    mdlReadMib(pLayerPointers, XmtMultiCastPkts);
21145256Slh155975 		break;
21155256Slh155975 
21165256Slh155975 	case MAC_STAT_BRDCSTXMT:
21175256Slh155975 		*val = adapterStat->tx_mib_broadcst_packets +
21185256Slh155975 		    mdlReadMib(pLayerPointers, XmtBroadCastPkts);
21195256Slh155975 		break;
21205256Slh155975 
21215256Slh155975 	case MAC_STAT_NOXMTBUF:
21225256Slh155975 		*val = adapterStat->tx_no_descriptor;
21235256Slh155975 		break;
21245256Slh155975 
21255256Slh155975 	case MAC_STAT_OERRORS:
21265256Slh155975 		*val = adapterStat->tx_mib_ex_coll_packets +
21275256Slh155975 		    mdlReadMib(pLayerPointers, XmtExcessiveCollision);
21285256Slh155975 		break;
21295256Slh155975 
21305256Slh155975 	case MAC_STAT_COLLISIONS:
21315256Slh155975 		*val = adapterStat->tx_mib_ex_coll_packets +
21325256Slh155975 		    mdlReadMib(pLayerPointers, XmtCollisions);
21335256Slh155975 		break;
21345256Slh155975 
21355256Slh155975 	case ETHER_STAT_FIRST_COLLISIONS:
21365256Slh155975 		*val = adapterStat->tx_mib_one_coll_packets +
21375256Slh155975 		    mdlReadMib(pLayerPointers, XmtOneCollision);
21385256Slh155975 		break;
21395256Slh155975 
21405256Slh155975 	case ETHER_STAT_MULTI_COLLISIONS:
21415256Slh155975 		*val = adapterStat->tx_mib_multi_coll_packets +
21425256Slh155975 		    mdlReadMib(pLayerPointers, XmtMultipleCollision);
21435256Slh155975 		break;
21445256Slh155975 
21455256Slh155975 	case ETHER_STAT_EX_COLLISIONS:
21465256Slh155975 		*val = adapterStat->tx_mib_ex_coll_packets +
21475256Slh155975 		    mdlReadMib(pLayerPointers, XmtExcessiveCollision);
21485256Slh155975 		break;
21495256Slh155975 
21505256Slh155975 	case ETHER_STAT_TX_LATE_COLLISIONS:
21515256Slh155975 		*val = adapterStat->tx_mib_late_coll_packets +
21525256Slh155975 		    mdlReadMib(pLayerPointers, XmtLateCollision);
21535256Slh155975 		break;
21545256Slh155975 
21555256Slh155975 	case ETHER_STAT_DEFER_XMTS:
21565256Slh155975 		*val = adapterStat->tx_mib_defer_trans_packets +
21575256Slh155975 		    mdlReadMib(pLayerPointers, XmtDeferredTransmit);
21585256Slh155975 		break;
21595256Slh155975 
21605256Slh155975 	default:
21615256Slh155975 		return (ENOTSUP);
21625256Slh155975 	}
21635256Slh155975 	return (0);
21645256Slh155975 }
21655256Slh155975 
21665256Slh155975 /*
21675256Slh155975  *	Memory Read Function Used by MDL to set card registers.
21685256Slh155975  */
21695256Slh155975 unsigned char
21705256Slh155975 READ_REG8(struct LayerPointers *pLayerPointers, long x)
21715256Slh155975 {
21725256Slh155975 	return (ddi_get8(pLayerPointers->pOdl->MemBasehandle, (uint8_t *)x));
21735256Slh155975 }
21745256Slh155975 
21755256Slh155975 int
21765256Slh155975 READ_REG16(struct LayerPointers *pLayerPointers, long x)
21775256Slh155975 {
21785256Slh155975 	return (ddi_get16(pLayerPointers->pOdl->MemBasehandle,
21795256Slh155975 	    (uint16_t *)(x)));
21805256Slh155975 }
21815256Slh155975 
21825256Slh155975 long
21835256Slh155975 READ_REG32(struct LayerPointers *pLayerPointers, long x)
21845256Slh155975 {
21855256Slh155975 	return (ddi_get32(pLayerPointers->pOdl->MemBasehandle,
21865256Slh155975 	    (uint32_t *)(x)));
21875256Slh155975 }
21885256Slh155975 
21895256Slh155975 void
21905256Slh155975 WRITE_REG8(struct LayerPointers *pLayerPointers, long x, int y)
21915256Slh155975 {
21925256Slh155975 	ddi_put8(pLayerPointers->pOdl->MemBasehandle, (uint8_t *)(x), y);
21935256Slh155975 }
21945256Slh155975 
21955256Slh155975 void
21965256Slh155975 WRITE_REG16(struct LayerPointers *pLayerPointers, long x, int y)
21975256Slh155975 {
21985256Slh155975 	ddi_put16(pLayerPointers->pOdl->MemBasehandle, (uint16_t *)(x), y);
21995256Slh155975 }
22005256Slh155975 
22015256Slh155975 void
22025256Slh155975 WRITE_REG32(struct LayerPointers *pLayerPointers, long x, int y)
22035256Slh155975 {
22045256Slh155975 	ddi_put32(pLayerPointers->pOdl->MemBasehandle, (uint32_t *)(x), y);
22055256Slh155975 }
22065256Slh155975 
22075256Slh155975 void
22085256Slh155975 WRITE_REG64(struct LayerPointers *pLayerPointers, long x, char *y)
22095256Slh155975 {
22105256Slh155975 	int i;
22115256Slh155975 	for (i = 0; i < 8; i++) {
22125256Slh155975 		WRITE_REG8(pLayerPointers, (x + i), y[i]);
22135256Slh155975 	}
22145256Slh155975 }
2215