xref: /onnv-gate/usr/src/uts/common/io/fibre-channel/fca/oce/oce_main.c (revision 13020:1b6086d6d5a1)
111374SSukumar.Swaminathan@Sun.COM /*
211374SSukumar.Swaminathan@Sun.COM  * CDDL HEADER START
311374SSukumar.Swaminathan@Sun.COM  *
411374SSukumar.Swaminathan@Sun.COM  * The contents of this file are subject to the terms of the
511374SSukumar.Swaminathan@Sun.COM  * Common Development and Distribution License (the "License").
611374SSukumar.Swaminathan@Sun.COM  * You may not use this file except in compliance with the License.
711374SSukumar.Swaminathan@Sun.COM  *
811374SSukumar.Swaminathan@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911374SSukumar.Swaminathan@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1011374SSukumar.Swaminathan@Sun.COM  * See the License for the specific language governing permissions
1111374SSukumar.Swaminathan@Sun.COM  * and limitations under the License.
1211374SSukumar.Swaminathan@Sun.COM  *
1311374SSukumar.Swaminathan@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1411374SSukumar.Swaminathan@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1511374SSukumar.Swaminathan@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1611374SSukumar.Swaminathan@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1711374SSukumar.Swaminathan@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1811374SSukumar.Swaminathan@Sun.COM  *
1911374SSukumar.Swaminathan@Sun.COM  * CDDL HEADER END
2011374SSukumar.Swaminathan@Sun.COM  */
2111374SSukumar.Swaminathan@Sun.COM 
2211374SSukumar.Swaminathan@Sun.COM /*
2312043SSukumar.Swaminathan@Sun.COM  * Copyright 2010 Emulex.  All rights reserved.
2411374SSukumar.Swaminathan@Sun.COM  * Use is subject to license terms.
2511374SSukumar.Swaminathan@Sun.COM  */
2611374SSukumar.Swaminathan@Sun.COM 
2711374SSukumar.Swaminathan@Sun.COM /*
2811374SSukumar.Swaminathan@Sun.COM  * Source file containing the implementation of the driver entry points
2911374SSukumar.Swaminathan@Sun.COM  * and related helper functions
3011374SSukumar.Swaminathan@Sun.COM  */
3111374SSukumar.Swaminathan@Sun.COM 
3211374SSukumar.Swaminathan@Sun.COM #include <oce_impl.h>
3311374SSukumar.Swaminathan@Sun.COM #include <oce_stat.h>
3411374SSukumar.Swaminathan@Sun.COM #include <oce_ioctl.h>
3511374SSukumar.Swaminathan@Sun.COM 
3611374SSukumar.Swaminathan@Sun.COM #define	ATTACH_DEV_INIT 	0x1
3711374SSukumar.Swaminathan@Sun.COM #define	ATTACH_FM_INIT		0x2
3811723SSukumar.Swaminathan@Sun.COM #define	ATTACH_LOCK_INIT	0x4
3911723SSukumar.Swaminathan@Sun.COM #define	ATTACH_PCI_INIT 	0x8
4011723SSukumar.Swaminathan@Sun.COM #define	ATTACH_HW_INIT		0x10
4111723SSukumar.Swaminathan@Sun.COM #define	ATTACH_SETUP_TXRX 	0x20
4211723SSukumar.Swaminathan@Sun.COM #define	ATTACH_SETUP_ADAP	0x40
43*13020SSukumar.Swaminathan@Sun.COM #define	ATTACH_SETUP_INTR	0x80
4411374SSukumar.Swaminathan@Sun.COM #define	ATTACH_STAT_INIT	0x100
4511374SSukumar.Swaminathan@Sun.COM #define	ATTACH_MAC_REG		0x200
4611374SSukumar.Swaminathan@Sun.COM 
4711374SSukumar.Swaminathan@Sun.COM /* ---[ globals and externs ]-------------------------------------------- */
4811374SSukumar.Swaminathan@Sun.COM const char oce_ident_string[] = OCE_IDENT_STRING;
4911374SSukumar.Swaminathan@Sun.COM const char oce_mod_name[] = OCE_MOD_NAME;
5011374SSukumar.Swaminathan@Sun.COM 
5111374SSukumar.Swaminathan@Sun.COM /* driver properties */
52*13020SSukumar.Swaminathan@Sun.COM static const char flow_control[]	 = "flow_control";
53*13020SSukumar.Swaminathan@Sun.COM static const char mtu_prop_name[]	 = "oce_default_mtu";
54*13020SSukumar.Swaminathan@Sun.COM static const char tx_ring_size_name[]	 = "tx_ring_size";
55*13020SSukumar.Swaminathan@Sun.COM static const char tx_bcopy_limit_name[]	 = "tx_bcopy_limit";
56*13020SSukumar.Swaminathan@Sun.COM static const char rx_bcopy_limit_name[]	 = "rx_bcopy_limit";
57*13020SSukumar.Swaminathan@Sun.COM static const char rx_frag_size_name[]	 = "rx_frag_size";
58*13020SSukumar.Swaminathan@Sun.COM static const char rx_max_bufs_name[]	 = "rx_max_bufs";
59*13020SSukumar.Swaminathan@Sun.COM static const char fm_cap_name[]		 = "oce_fm_capability";
60*13020SSukumar.Swaminathan@Sun.COM static const char log_level_name[]	 = "oce_log_level";
61*13020SSukumar.Swaminathan@Sun.COM static const char lso_capable_name[]	 = "lso_capable";
62*13020SSukumar.Swaminathan@Sun.COM static const char rx_pkt_per_intr_name[] = "rx_pkts_per_intr";
63*13020SSukumar.Swaminathan@Sun.COM static const char tx_reclaim_threshold_name[] = "tx_reclaim_threshold";
64*13020SSukumar.Swaminathan@Sun.COM static const char rx_rings_name[]	 = "max_rx_rings";
65*13020SSukumar.Swaminathan@Sun.COM static const char tx_rings_name[]	 = "max_tx_rings";
6611374SSukumar.Swaminathan@Sun.COM 
6711374SSukumar.Swaminathan@Sun.COM /* --[ static function prototypes here ]------------------------------- */
6811374SSukumar.Swaminathan@Sun.COM static int oce_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd);
6911374SSukumar.Swaminathan@Sun.COM static int oce_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
7011374SSukumar.Swaminathan@Sun.COM static int oce_quiesce(dev_info_t *dip);
7111374SSukumar.Swaminathan@Sun.COM static int oce_suspend(dev_info_t *dip);
7211374SSukumar.Swaminathan@Sun.COM static int oce_resume(dev_info_t *dip);
7311374SSukumar.Swaminathan@Sun.COM static void oce_unconfigure(struct oce_dev *dev);
7411374SSukumar.Swaminathan@Sun.COM static void oce_init_locks(struct oce_dev *dev);
7511374SSukumar.Swaminathan@Sun.COM static void oce_destroy_locks(struct oce_dev *dev);
7611374SSukumar.Swaminathan@Sun.COM static void oce_get_params(struct oce_dev *dev);
77*13020SSukumar.Swaminathan@Sun.COM static int oce_get_prop(struct oce_dev *dev, char *propname, int minval,
78*13020SSukumar.Swaminathan@Sun.COM     int maxval, int defval, uint32_t *values);
7911374SSukumar.Swaminathan@Sun.COM 
8011374SSukumar.Swaminathan@Sun.COM static struct cb_ops oce_cb_ops = {
8111374SSukumar.Swaminathan@Sun.COM 	nulldev,		/* cb_open */
8211374SSukumar.Swaminathan@Sun.COM 	nulldev,		/* cb_close */
8311374SSukumar.Swaminathan@Sun.COM 	nodev,			/* cb_strategy */
8411374SSukumar.Swaminathan@Sun.COM 	nodev,			/* cb_print */
8511374SSukumar.Swaminathan@Sun.COM 	nodev,			/* cb_dump */
8611374SSukumar.Swaminathan@Sun.COM 	nodev,			/* cb_read */
8711374SSukumar.Swaminathan@Sun.COM 	nodev,			/* cb_write */
8811374SSukumar.Swaminathan@Sun.COM 	nodev,			/* cb_ioctl */
8911374SSukumar.Swaminathan@Sun.COM 	nodev,			/* cb_devmap */
9011374SSukumar.Swaminathan@Sun.COM 	nodev,			/* cb_mmap */
9111374SSukumar.Swaminathan@Sun.COM 	nodev,			/* cb_segmap */
9211374SSukumar.Swaminathan@Sun.COM 	nochpoll,		/* cb_chpoll */
9311374SSukumar.Swaminathan@Sun.COM 	ddi_prop_op,	/* cb_prop_op */
9411374SSukumar.Swaminathan@Sun.COM 	NULL,			/* cb_stream */
9511374SSukumar.Swaminathan@Sun.COM 	D_MP,			/* cb_flag */
9611374SSukumar.Swaminathan@Sun.COM 	CB_REV,			/* cb_rev */
9711374SSukumar.Swaminathan@Sun.COM 	nodev,			/* cb_aread */
9811374SSukumar.Swaminathan@Sun.COM 	nodev			/* cb_awrite */
9911374SSukumar.Swaminathan@Sun.COM };
10011374SSukumar.Swaminathan@Sun.COM 
10111374SSukumar.Swaminathan@Sun.COM static struct dev_ops oce_dev_ops = {
10211374SSukumar.Swaminathan@Sun.COM 	DEVO_REV,	/* devo_rev */
10311374SSukumar.Swaminathan@Sun.COM 	0,		/* devo_refcnt */
10411374SSukumar.Swaminathan@Sun.COM 	NULL,		/* devo_getinfo */
10511374SSukumar.Swaminathan@Sun.COM 	NULL,		/* devo_identify */
10611374SSukumar.Swaminathan@Sun.COM 	nulldev,	/* devo_probe */
10711374SSukumar.Swaminathan@Sun.COM 	oce_attach,	/* devo_attach */
10811374SSukumar.Swaminathan@Sun.COM 	oce_detach,	/* devo_detach */
10911374SSukumar.Swaminathan@Sun.COM 	nodev,		/* devo_reset */
11011374SSukumar.Swaminathan@Sun.COM 	&oce_cb_ops,	/* devo_cb_ops */
11111374SSukumar.Swaminathan@Sun.COM 	NULL,		/* devo_bus_ops */
11211374SSukumar.Swaminathan@Sun.COM 	nodev,		/* devo_power */
11311374SSukumar.Swaminathan@Sun.COM 	oce_quiesce	/* devo_quiesce */
11411374SSukumar.Swaminathan@Sun.COM };
11511374SSukumar.Swaminathan@Sun.COM 
11611374SSukumar.Swaminathan@Sun.COM static struct modldrv oce_drv = {
11711374SSukumar.Swaminathan@Sun.COM 	&mod_driverops,	/* Type of module.  This one is a driver */
11811374SSukumar.Swaminathan@Sun.COM 	(char *)oce_ident_string, /* Description string */
11911374SSukumar.Swaminathan@Sun.COM 	&oce_dev_ops,	/* driver ops */
12011374SSukumar.Swaminathan@Sun.COM };
12111374SSukumar.Swaminathan@Sun.COM 
12211374SSukumar.Swaminathan@Sun.COM static struct modlinkage oce_mod_linkage = {
12311374SSukumar.Swaminathan@Sun.COM 	MODREV_1, &oce_drv, NULL
12411374SSukumar.Swaminathan@Sun.COM };
12511374SSukumar.Swaminathan@Sun.COM 
12611878SVenu.Iyer@Sun.COM #define	OCE_M_CB_FLAGS	(MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | \
12711878SVenu.Iyer@Sun.COM     MC_PROPINFO)
12811374SSukumar.Swaminathan@Sun.COM static mac_callbacks_t oce_mac_cb = {
12911374SSukumar.Swaminathan@Sun.COM 	OCE_M_CB_FLAGS,		/* mc_callbacks */
13011374SSukumar.Swaminathan@Sun.COM 	oce_m_stat,		/* mc_getstat */
13111374SSukumar.Swaminathan@Sun.COM 	oce_m_start,		/* mc_start */
13211374SSukumar.Swaminathan@Sun.COM 	oce_m_stop,		/* mc_stop */
13311374SSukumar.Swaminathan@Sun.COM 	oce_m_promiscuous,	/* mc_setpromisc */
13411374SSukumar.Swaminathan@Sun.COM 	oce_m_multicast,	/* mc_multicast */
13511374SSukumar.Swaminathan@Sun.COM 	oce_m_unicast,		/* mc_unicast */
13611374SSukumar.Swaminathan@Sun.COM 	oce_m_send,		/* mc_tx */
13712043SSukumar.Swaminathan@Sun.COM 	NULL,			/* mc_reserve */
13811374SSukumar.Swaminathan@Sun.COM 	oce_m_ioctl,		/* mc_ioctl */
13911374SSukumar.Swaminathan@Sun.COM 	oce_m_getcap,		/* mc_getcapab */
14011374SSukumar.Swaminathan@Sun.COM 	NULL,			/* open */
14111374SSukumar.Swaminathan@Sun.COM 	NULL,			/* close */
14211374SSukumar.Swaminathan@Sun.COM 	oce_m_setprop,		/* set properties */
14311878SVenu.Iyer@Sun.COM 	oce_m_getprop,		/* get properties */
14411878SVenu.Iyer@Sun.COM 	oce_m_propinfo		/* properties info */
14511374SSukumar.Swaminathan@Sun.COM };
14611374SSukumar.Swaminathan@Sun.COM 
14711878SVenu.Iyer@Sun.COM extern char *oce_priv_props[];
14811374SSukumar.Swaminathan@Sun.COM 
14911374SSukumar.Swaminathan@Sun.COM /* Module Init */
15011374SSukumar.Swaminathan@Sun.COM int
_info(struct modinfo * modinfop)15111374SSukumar.Swaminathan@Sun.COM _info(struct modinfo *modinfop)
15211374SSukumar.Swaminathan@Sun.COM {
15311374SSukumar.Swaminathan@Sun.COM 	return (mod_info(&oce_mod_linkage, modinfop));
15411374SSukumar.Swaminathan@Sun.COM } /* _info */
15511374SSukumar.Swaminathan@Sun.COM 
15611374SSukumar.Swaminathan@Sun.COM int
_init(void)15711374SSukumar.Swaminathan@Sun.COM _init(void)
15811374SSukumar.Swaminathan@Sun.COM {
15911374SSukumar.Swaminathan@Sun.COM 	int ret = 0;
16011374SSukumar.Swaminathan@Sun.COM 
16111374SSukumar.Swaminathan@Sun.COM 	/* install the module */
16211374SSukumar.Swaminathan@Sun.COM 	mac_init_ops(&oce_dev_ops, "oce");
16311374SSukumar.Swaminathan@Sun.COM 
16411374SSukumar.Swaminathan@Sun.COM 	ret = mod_install(&oce_mod_linkage);
16511374SSukumar.Swaminathan@Sun.COM 	if (ret) {
16611374SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "mod_install failed  rval=%x", ret);
16711374SSukumar.Swaminathan@Sun.COM 	}
16811374SSukumar.Swaminathan@Sun.COM 
16911374SSukumar.Swaminathan@Sun.COM 	return (ret);
17011374SSukumar.Swaminathan@Sun.COM } /* _init */
17111374SSukumar.Swaminathan@Sun.COM 
17211374SSukumar.Swaminathan@Sun.COM 
17311374SSukumar.Swaminathan@Sun.COM int
_fini(void)17411374SSukumar.Swaminathan@Sun.COM _fini(void)
17511374SSukumar.Swaminathan@Sun.COM {
17611374SSukumar.Swaminathan@Sun.COM 	int ret = 0;
17711374SSukumar.Swaminathan@Sun.COM 	/* remove the module */
17811374SSukumar.Swaminathan@Sun.COM 	ret = mod_remove(&oce_mod_linkage);
17911374SSukumar.Swaminathan@Sun.COM 	if (ret != 0) {
18011374SSukumar.Swaminathan@Sun.COM 		return (ret);
18111374SSukumar.Swaminathan@Sun.COM 	}
18211374SSukumar.Swaminathan@Sun.COM 
18311374SSukumar.Swaminathan@Sun.COM 	mac_fini_ops(&oce_dev_ops);
18411374SSukumar.Swaminathan@Sun.COM 
18511374SSukumar.Swaminathan@Sun.COM 	return (ret);
18611374SSukumar.Swaminathan@Sun.COM } /* _fini */
18711374SSukumar.Swaminathan@Sun.COM 
18811374SSukumar.Swaminathan@Sun.COM 
18911374SSukumar.Swaminathan@Sun.COM static int
oce_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)19011374SSukumar.Swaminathan@Sun.COM oce_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
19111374SSukumar.Swaminathan@Sun.COM {
19211374SSukumar.Swaminathan@Sun.COM 	int ret = 0;
19311374SSukumar.Swaminathan@Sun.COM 	struct oce_dev *dev = NULL;
19411374SSukumar.Swaminathan@Sun.COM 	mac_register_t *mac;
19511374SSukumar.Swaminathan@Sun.COM 
19611374SSukumar.Swaminathan@Sun.COM 	switch (cmd) {
19711374SSukumar.Swaminathan@Sun.COM 	case DDI_RESUME:
19811374SSukumar.Swaminathan@Sun.COM 		return (oce_resume(dip));
19911374SSukumar.Swaminathan@Sun.COM 	default:
20011374SSukumar.Swaminathan@Sun.COM 		return (DDI_FAILURE);
20111374SSukumar.Swaminathan@Sun.COM 
20211374SSukumar.Swaminathan@Sun.COM 	case DDI_ATTACH:
20311374SSukumar.Swaminathan@Sun.COM 		break;
20411374SSukumar.Swaminathan@Sun.COM 	}
20511374SSukumar.Swaminathan@Sun.COM 
20611374SSukumar.Swaminathan@Sun.COM 	/* allocate dev */
207*13020SSukumar.Swaminathan@Sun.COM 	dev = kmem_zalloc(sizeof (struct oce_dev), KM_SLEEP);
20811374SSukumar.Swaminathan@Sun.COM 
20911374SSukumar.Swaminathan@Sun.COM 	/* populate the dev structure */
21011374SSukumar.Swaminathan@Sun.COM 	dev->dip = dip;
21111374SSukumar.Swaminathan@Sun.COM 	dev->dev_id = ddi_get_instance(dip);
21211374SSukumar.Swaminathan@Sun.COM 	dev->suspended = B_FALSE;
21311374SSukumar.Swaminathan@Sun.COM 
21411374SSukumar.Swaminathan@Sun.COM 	/* get the parameters */
21511374SSukumar.Swaminathan@Sun.COM 	oce_get_params(dev);
21611374SSukumar.Swaminathan@Sun.COM 
21711374SSukumar.Swaminathan@Sun.COM 	/*
21811374SSukumar.Swaminathan@Sun.COM 	 * set the ddi driver private data pointer. This is
21911374SSukumar.Swaminathan@Sun.COM 	 * sent to all mac callback entry points
22011374SSukumar.Swaminathan@Sun.COM 	 */
22111374SSukumar.Swaminathan@Sun.COM 	ddi_set_driver_private(dip, dev);
22211374SSukumar.Swaminathan@Sun.COM 
22311374SSukumar.Swaminathan@Sun.COM 	dev->attach_state |= ATTACH_DEV_INIT;
22411374SSukumar.Swaminathan@Sun.COM 
22511374SSukumar.Swaminathan@Sun.COM 	oce_fm_init(dev);
22611374SSukumar.Swaminathan@Sun.COM 	dev->attach_state |= ATTACH_FM_INIT;
22711374SSukumar.Swaminathan@Sun.COM 
22811374SSukumar.Swaminathan@Sun.COM 	/* setup PCI bars */
22911374SSukumar.Swaminathan@Sun.COM 	ret = oce_pci_init(dev);
23011374SSukumar.Swaminathan@Sun.COM 	if (ret != DDI_SUCCESS) {
23111374SSukumar.Swaminathan@Sun.COM 		oce_log(dev, CE_WARN, MOD_CONFIG,
23211374SSukumar.Swaminathan@Sun.COM 		    "PCI initialization failed with %d", ret);
23311374SSukumar.Swaminathan@Sun.COM 		goto attach_fail;
23411374SSukumar.Swaminathan@Sun.COM 	}
23511374SSukumar.Swaminathan@Sun.COM 	dev->attach_state |= ATTACH_PCI_INIT;
23611374SSukumar.Swaminathan@Sun.COM 
237*13020SSukumar.Swaminathan@Sun.COM 	ret = oce_setup_intr(dev);
238*13020SSukumar.Swaminathan@Sun.COM 	if (ret != DDI_SUCCESS) {
239*13020SSukumar.Swaminathan@Sun.COM 		oce_log(dev, CE_WARN, MOD_CONFIG,
240*13020SSukumar.Swaminathan@Sun.COM 		    "Interrupt setup failed with %d", ret);
241*13020SSukumar.Swaminathan@Sun.COM 		goto attach_fail;
242*13020SSukumar.Swaminathan@Sun.COM 
243*13020SSukumar.Swaminathan@Sun.COM 	}
244*13020SSukumar.Swaminathan@Sun.COM 	dev->attach_state |= ATTACH_SETUP_INTR;
245*13020SSukumar.Swaminathan@Sun.COM 
246*13020SSukumar.Swaminathan@Sun.COM 	/* initialize locks */
247*13020SSukumar.Swaminathan@Sun.COM 	oce_init_locks(dev);
248*13020SSukumar.Swaminathan@Sun.COM 	dev->attach_state |= ATTACH_LOCK_INIT;
249*13020SSukumar.Swaminathan@Sun.COM 
250*13020SSukumar.Swaminathan@Sun.COM 
25111723SSukumar.Swaminathan@Sun.COM 	/* HW init */
25211723SSukumar.Swaminathan@Sun.COM 	ret = oce_hw_init(dev);
25311723SSukumar.Swaminathan@Sun.COM 	if (ret != DDI_SUCCESS) {
25411374SSukumar.Swaminathan@Sun.COM 		oce_log(dev, CE_WARN, MOD_CONFIG,
25511723SSukumar.Swaminathan@Sun.COM 		    "HW initialization failed with %d", ret);
25611374SSukumar.Swaminathan@Sun.COM 		goto attach_fail;
25711374SSukumar.Swaminathan@Sun.COM 	}
25811723SSukumar.Swaminathan@Sun.COM 	dev->attach_state |= ATTACH_HW_INIT;
25911374SSukumar.Swaminathan@Sun.COM 
26011723SSukumar.Swaminathan@Sun.COM 	ret = oce_init_txrx(dev);
26111723SSukumar.Swaminathan@Sun.COM 	if (ret  != DDI_SUCCESS) {
26211723SSukumar.Swaminathan@Sun.COM 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
26311723SSukumar.Swaminathan@Sun.COM 		    "Failed to init rings");
26411374SSukumar.Swaminathan@Sun.COM 		goto attach_fail;
26511374SSukumar.Swaminathan@Sun.COM 	}
26611723SSukumar.Swaminathan@Sun.COM 	dev->attach_state |= ATTACH_SETUP_TXRX;
26711374SSukumar.Swaminathan@Sun.COM 
26811723SSukumar.Swaminathan@Sun.COM 	ret = oce_setup_adapter(dev);
26911723SSukumar.Swaminathan@Sun.COM 	if (ret != DDI_SUCCESS) {
27011723SSukumar.Swaminathan@Sun.COM 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
27111723SSukumar.Swaminathan@Sun.COM 		    "Failed to setup adapter");
27211374SSukumar.Swaminathan@Sun.COM 		goto attach_fail;
27311374SSukumar.Swaminathan@Sun.COM 	}
27411723SSukumar.Swaminathan@Sun.COM 	dev->attach_state |=  ATTACH_SETUP_ADAP;
27511374SSukumar.Swaminathan@Sun.COM 
27611374SSukumar.Swaminathan@Sun.COM 
27711374SSukumar.Swaminathan@Sun.COM 	ret = oce_stat_init(dev);
27811374SSukumar.Swaminathan@Sun.COM 	if (ret != DDI_SUCCESS) {
27911374SSukumar.Swaminathan@Sun.COM 		oce_log(dev, CE_WARN, MOD_CONFIG,
28011374SSukumar.Swaminathan@Sun.COM 		    "kstat setup Failed with %d", ret);
28111374SSukumar.Swaminathan@Sun.COM 		goto attach_fail;
28211374SSukumar.Swaminathan@Sun.COM 	}
28311374SSukumar.Swaminathan@Sun.COM 	dev->attach_state |= ATTACH_STAT_INIT;
28411374SSukumar.Swaminathan@Sun.COM 
28511374SSukumar.Swaminathan@Sun.COM 	/* mac_register_t */
28611374SSukumar.Swaminathan@Sun.COM 	oce_log(dev, CE_NOTE, MOD_CONFIG,
28711374SSukumar.Swaminathan@Sun.COM 	    "MAC_VERSION = 0x%x", MAC_VERSION);
28811374SSukumar.Swaminathan@Sun.COM 	mac = mac_alloc(MAC_VERSION);
28911374SSukumar.Swaminathan@Sun.COM 	if (mac == NULL) {
29011374SSukumar.Swaminathan@Sun.COM 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
29111374SSukumar.Swaminathan@Sun.COM 		    "MAC allocation Failed");
29211374SSukumar.Swaminathan@Sun.COM 		goto attach_fail;
29311374SSukumar.Swaminathan@Sun.COM 	}
29411374SSukumar.Swaminathan@Sun.COM 	/*
29511374SSukumar.Swaminathan@Sun.COM 	 * fill the mac structure before calling mac_register
29611374SSukumar.Swaminathan@Sun.COM 	 */
29711374SSukumar.Swaminathan@Sun.COM 	mac->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
29811374SSukumar.Swaminathan@Sun.COM 	mac->m_driver = dev;
29911374SSukumar.Swaminathan@Sun.COM 	mac->m_dip = dip;
30011374SSukumar.Swaminathan@Sun.COM 	mac->m_src_addr = dev->mac_addr;
30111374SSukumar.Swaminathan@Sun.COM 	mac->m_callbacks = &oce_mac_cb;
30211374SSukumar.Swaminathan@Sun.COM 	mac->m_min_sdu = 0;
30311374SSukumar.Swaminathan@Sun.COM 	mac->m_max_sdu = dev->mtu;
30411374SSukumar.Swaminathan@Sun.COM 	mac->m_margin = VLAN_TAGSZ;
30511374SSukumar.Swaminathan@Sun.COM 	mac->m_priv_props = oce_priv_props;
30611374SSukumar.Swaminathan@Sun.COM 
30711374SSukumar.Swaminathan@Sun.COM 	oce_log(dev, CE_NOTE, MOD_CONFIG,
30811374SSukumar.Swaminathan@Sun.COM 	    "Driver Private structure = 0x%p", (void *)dev);
30911374SSukumar.Swaminathan@Sun.COM 
31011374SSukumar.Swaminathan@Sun.COM 	/* now register with GLDv3 */
31111374SSukumar.Swaminathan@Sun.COM 	ret = mac_register(mac, (mac_handle_t *)&dev->mac_handle);
31211374SSukumar.Swaminathan@Sun.COM 	/* regardless of the status, free mac_register */
31311374SSukumar.Swaminathan@Sun.COM 	mac_free(mac);
31411374SSukumar.Swaminathan@Sun.COM 	mac = NULL;
31511374SSukumar.Swaminathan@Sun.COM 	if (ret != DDI_SUCCESS) {
31611374SSukumar.Swaminathan@Sun.COM 		oce_log(dev, CE_WARN, MOD_CONFIG,
31711374SSukumar.Swaminathan@Sun.COM 		    "MAC registration failed :0x%x", ret);
31811374SSukumar.Swaminathan@Sun.COM 		goto attach_fail;
31911374SSukumar.Swaminathan@Sun.COM 
32011374SSukumar.Swaminathan@Sun.COM 	}
32111374SSukumar.Swaminathan@Sun.COM 
32211374SSukumar.Swaminathan@Sun.COM 	/* correct link status only after start */
323*13020SSukumar.Swaminathan@Sun.COM 	dev->link_status = LINK_STATE_UNKNOWN;
324*13020SSukumar.Swaminathan@Sun.COM 	mac_link_update(dev->mac_handle, dev->link_status);
32511374SSukumar.Swaminathan@Sun.COM 
32611374SSukumar.Swaminathan@Sun.COM 	dev->attach_state |= ATTACH_MAC_REG;
32711374SSukumar.Swaminathan@Sun.COM 	dev->state |= STATE_INIT;
32812043SSukumar.Swaminathan@Sun.COM 
32911374SSukumar.Swaminathan@Sun.COM 	oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
33011374SSukumar.Swaminathan@Sun.COM 	    "ATTACH SUCCESS");
33111374SSukumar.Swaminathan@Sun.COM 
33211374SSukumar.Swaminathan@Sun.COM 	return (DDI_SUCCESS);
33311374SSukumar.Swaminathan@Sun.COM 
33411374SSukumar.Swaminathan@Sun.COM attach_fail:
33511374SSukumar.Swaminathan@Sun.COM 	oce_unconfigure(dev);
33611374SSukumar.Swaminathan@Sun.COM 	return (DDI_FAILURE);
33711374SSukumar.Swaminathan@Sun.COM } /* oce_attach */
33811374SSukumar.Swaminathan@Sun.COM 
33911374SSukumar.Swaminathan@Sun.COM static int
oce_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)34011374SSukumar.Swaminathan@Sun.COM oce_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
34111374SSukumar.Swaminathan@Sun.COM {
34211723SSukumar.Swaminathan@Sun.COM 	struct oce_dev *dev;
34311723SSukumar.Swaminathan@Sun.COM 	int pcnt = 0;
344*13020SSukumar.Swaminathan@Sun.COM 	int qid;
34511374SSukumar.Swaminathan@Sun.COM 
34611723SSukumar.Swaminathan@Sun.COM 	dev = ddi_get_driver_private(dip);
34711723SSukumar.Swaminathan@Sun.COM 	if (dev == NULL) {
34811723SSukumar.Swaminathan@Sun.COM 		return (DDI_FAILURE);
34911723SSukumar.Swaminathan@Sun.COM 	}
35011374SSukumar.Swaminathan@Sun.COM 	oce_log(dev, CE_NOTE, MOD_CONFIG,
35111374SSukumar.Swaminathan@Sun.COM 	    "Detaching driver: cmd = 0x%x", cmd);
35211374SSukumar.Swaminathan@Sun.COM 
35311374SSukumar.Swaminathan@Sun.COM 	switch (cmd) {
35411723SSukumar.Swaminathan@Sun.COM 	default:
35511723SSukumar.Swaminathan@Sun.COM 		return (DDI_FAILURE);
35611374SSukumar.Swaminathan@Sun.COM 	case DDI_SUSPEND:
35711374SSukumar.Swaminathan@Sun.COM 		return (oce_suspend(dip));
35811723SSukumar.Swaminathan@Sun.COM 	case DDI_DETACH:
35911723SSukumar.Swaminathan@Sun.COM 		break;
36011723SSukumar.Swaminathan@Sun.COM 	} /* switch cmd */
36111374SSukumar.Swaminathan@Sun.COM 
36211723SSukumar.Swaminathan@Sun.COM 	/* Fail detach if MAC unregister is unsuccessfule */
36311723SSukumar.Swaminathan@Sun.COM 	if (mac_unregister(dev->mac_handle) != 0) {
36411723SSukumar.Swaminathan@Sun.COM 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
36511723SSukumar.Swaminathan@Sun.COM 		    "Failed to unregister MAC ");
36611723SSukumar.Swaminathan@Sun.COM 	}
36711723SSukumar.Swaminathan@Sun.COM 	dev->attach_state &= ~ATTACH_MAC_REG;
36811723SSukumar.Swaminathan@Sun.COM 
36911723SSukumar.Swaminathan@Sun.COM 	/* check if the detach is called with out stopping */
37011723SSukumar.Swaminathan@Sun.COM 	DEV_LOCK(dev);
37111723SSukumar.Swaminathan@Sun.COM 	if (dev->state & STATE_MAC_STARTED) {
37211723SSukumar.Swaminathan@Sun.COM 		dev->state &= ~STATE_MAC_STARTED;
37311723SSukumar.Swaminathan@Sun.COM 		oce_stop(dev);
37411723SSukumar.Swaminathan@Sun.COM 		DEV_UNLOCK(dev);
37511723SSukumar.Swaminathan@Sun.COM 	} else
37611723SSukumar.Swaminathan@Sun.COM 		DEV_UNLOCK(dev);
37711723SSukumar.Swaminathan@Sun.COM 
37811723SSukumar.Swaminathan@Sun.COM 	/*
37911723SSukumar.Swaminathan@Sun.COM 	 * Wait for Packets sent up to be freed
38011723SSukumar.Swaminathan@Sun.COM 	 */
381*13020SSukumar.Swaminathan@Sun.COM 	for (qid = 0; qid < dev->rx_rings; qid++) {
382*13020SSukumar.Swaminathan@Sun.COM 		pcnt = oce_rx_pending(dev, dev->rq[qid], DEFAULT_DRAIN_TIME);
383*13020SSukumar.Swaminathan@Sun.COM 		if (pcnt != 0) {
384*13020SSukumar.Swaminathan@Sun.COM 			oce_log(dev, CE_WARN, MOD_CONFIG,
385*13020SSukumar.Swaminathan@Sun.COM 			    "%d Pending Buffers Detach failed", pcnt);
386*13020SSukumar.Swaminathan@Sun.COM 			return (DDI_FAILURE);
387*13020SSukumar.Swaminathan@Sun.COM 		}
38811723SSukumar.Swaminathan@Sun.COM 	}
38911723SSukumar.Swaminathan@Sun.COM 	oce_unconfigure(dev);
39011723SSukumar.Swaminathan@Sun.COM 
39111374SSukumar.Swaminathan@Sun.COM 	return (DDI_SUCCESS);
39211374SSukumar.Swaminathan@Sun.COM } /* oce_detach */
39311374SSukumar.Swaminathan@Sun.COM 
39411374SSukumar.Swaminathan@Sun.COM static int
oce_quiesce(dev_info_t * dip)39511374SSukumar.Swaminathan@Sun.COM oce_quiesce(dev_info_t *dip)
39611374SSukumar.Swaminathan@Sun.COM {
39711374SSukumar.Swaminathan@Sun.COM 	int ret = DDI_SUCCESS;
39811374SSukumar.Swaminathan@Sun.COM 	struct oce_dev *dev = ddi_get_driver_private(dip);
39911374SSukumar.Swaminathan@Sun.COM 
40011374SSukumar.Swaminathan@Sun.COM 	if (dev == NULL) {
40111374SSukumar.Swaminathan@Sun.COM 		return (DDI_FAILURE);
40211374SSukumar.Swaminathan@Sun.COM 	}
40311374SSukumar.Swaminathan@Sun.COM 	if (dev->suspended) {
40411374SSukumar.Swaminathan@Sun.COM 		return (DDI_SUCCESS);
40511374SSukumar.Swaminathan@Sun.COM 	}
40611374SSukumar.Swaminathan@Sun.COM 
40711723SSukumar.Swaminathan@Sun.COM 	oce_chip_di(dev);
40811374SSukumar.Swaminathan@Sun.COM 
40911374SSukumar.Swaminathan@Sun.COM 	ret = oce_reset_fun(dev);
41011374SSukumar.Swaminathan@Sun.COM 
41111374SSukumar.Swaminathan@Sun.COM 	return (ret);
41211374SSukumar.Swaminathan@Sun.COM }
41311374SSukumar.Swaminathan@Sun.COM 
41411374SSukumar.Swaminathan@Sun.COM static int
oce_suspend(dev_info_t * dip)41511374SSukumar.Swaminathan@Sun.COM oce_suspend(dev_info_t *dip)
41611374SSukumar.Swaminathan@Sun.COM {
41711374SSukumar.Swaminathan@Sun.COM 	struct oce_dev *dev = ddi_get_driver_private(dip);
41811374SSukumar.Swaminathan@Sun.COM 
41911374SSukumar.Swaminathan@Sun.COM 	mutex_enter(&dev->dev_lock);
42011374SSukumar.Swaminathan@Sun.COM 	/* Suspend the card */
42111374SSukumar.Swaminathan@Sun.COM 	dev->suspended = B_TRUE;
42211374SSukumar.Swaminathan@Sun.COM 	/* stop the adapter */
42311374SSukumar.Swaminathan@Sun.COM 	if (dev->state & STATE_MAC_STARTED) {
42411374SSukumar.Swaminathan@Sun.COM 		oce_stop(dev);
42511723SSukumar.Swaminathan@Sun.COM 		oce_unsetup_adapter(dev);
42611374SSukumar.Swaminathan@Sun.COM 	}
42711374SSukumar.Swaminathan@Sun.COM 	dev->state &= ~STATE_MAC_STARTED;
42811374SSukumar.Swaminathan@Sun.COM 	mutex_exit(&dev->dev_lock);
42911374SSukumar.Swaminathan@Sun.COM 	return (DDI_SUCCESS);
43011374SSukumar.Swaminathan@Sun.COM } /* oce_suspend */
43111374SSukumar.Swaminathan@Sun.COM 
43211374SSukumar.Swaminathan@Sun.COM static int
oce_resume(dev_info_t * dip)43311374SSukumar.Swaminathan@Sun.COM oce_resume(dev_info_t *dip)
43411374SSukumar.Swaminathan@Sun.COM {
43511374SSukumar.Swaminathan@Sun.COM 	struct oce_dev *dev;
43611374SSukumar.Swaminathan@Sun.COM 	int ret;
43711374SSukumar.Swaminathan@Sun.COM 
43811374SSukumar.Swaminathan@Sun.COM 	/* get the dev pointer from dip */
43911374SSukumar.Swaminathan@Sun.COM 	dev = ddi_get_driver_private(dip);
44011374SSukumar.Swaminathan@Sun.COM 	mutex_enter(&dev->dev_lock);
44111374SSukumar.Swaminathan@Sun.COM 	if (!dev->suspended) {
44211374SSukumar.Swaminathan@Sun.COM 		mutex_exit(&dev->dev_lock);
44311374SSukumar.Swaminathan@Sun.COM 		return (DDI_SUCCESS);
44411374SSukumar.Swaminathan@Sun.COM 	}
445*13020SSukumar.Swaminathan@Sun.COM 	if (!(dev->state & STATE_MAC_STARTED)) {
44611723SSukumar.Swaminathan@Sun.COM 		ret = oce_setup_adapter(dev);
44711723SSukumar.Swaminathan@Sun.COM 		if (ret != DDI_SUCCESS) {
44811723SSukumar.Swaminathan@Sun.COM 			mutex_exit(&dev->dev_lock);
44911723SSukumar.Swaminathan@Sun.COM 			return (DDI_FAILURE);
45011723SSukumar.Swaminathan@Sun.COM 		}
45111374SSukumar.Swaminathan@Sun.COM 		ret = oce_start(dev);
45211374SSukumar.Swaminathan@Sun.COM 		if (ret != DDI_SUCCESS) {
45311374SSukumar.Swaminathan@Sun.COM 			mutex_exit(&dev->dev_lock);
45411374SSukumar.Swaminathan@Sun.COM 			return (DDI_FAILURE);
45511374SSukumar.Swaminathan@Sun.COM 		}
45611374SSukumar.Swaminathan@Sun.COM 	}
45711374SSukumar.Swaminathan@Sun.COM 	dev->suspended = B_FALSE;
45811374SSukumar.Swaminathan@Sun.COM 	dev->state |= STATE_MAC_STARTED;
45911374SSukumar.Swaminathan@Sun.COM 	mutex_exit(&dev->dev_lock);
46011374SSukumar.Swaminathan@Sun.COM 	return (ret);
46111374SSukumar.Swaminathan@Sun.COM } /* oce_resume */
46211374SSukumar.Swaminathan@Sun.COM 
46311374SSukumar.Swaminathan@Sun.COM static void
oce_init_locks(struct oce_dev * dev)46411374SSukumar.Swaminathan@Sun.COM oce_init_locks(struct oce_dev *dev)
46511374SSukumar.Swaminathan@Sun.COM {
46611374SSukumar.Swaminathan@Sun.COM 	/* initialize locks */
46711374SSukumar.Swaminathan@Sun.COM 	mutex_init(&dev->dev_lock, NULL, MUTEX_DRIVER,
46811374SSukumar.Swaminathan@Sun.COM 	    DDI_INTR_PRI(dev->intr_pri));
46911374SSukumar.Swaminathan@Sun.COM 	mutex_init(&dev->bmbx_lock, NULL, MUTEX_DRIVER,
47011374SSukumar.Swaminathan@Sun.COM 	    DDI_INTR_PRI(dev->intr_pri));
47111374SSukumar.Swaminathan@Sun.COM } /* oce_init_locks */
47211374SSukumar.Swaminathan@Sun.COM 
47311374SSukumar.Swaminathan@Sun.COM static void
oce_destroy_locks(struct oce_dev * dev)47411374SSukumar.Swaminathan@Sun.COM oce_destroy_locks(struct oce_dev *dev)
47511374SSukumar.Swaminathan@Sun.COM {
47611374SSukumar.Swaminathan@Sun.COM 	mutex_destroy(&dev->dev_lock);
47711374SSukumar.Swaminathan@Sun.COM 	mutex_destroy(&dev->bmbx_lock);
47811374SSukumar.Swaminathan@Sun.COM } /* oce_destroy_locks */
47911374SSukumar.Swaminathan@Sun.COM 
48011374SSukumar.Swaminathan@Sun.COM static void
oce_unconfigure(struct oce_dev * dev)48111374SSukumar.Swaminathan@Sun.COM oce_unconfigure(struct oce_dev *dev)
48211374SSukumar.Swaminathan@Sun.COM {
48311374SSukumar.Swaminathan@Sun.COM 	uint32_t state = dev->attach_state;
48411374SSukumar.Swaminathan@Sun.COM 
48511374SSukumar.Swaminathan@Sun.COM 	if (state & ATTACH_MAC_REG) {
48611374SSukumar.Swaminathan@Sun.COM 		(void) mac_unregister(dev->mac_handle);
48711374SSukumar.Swaminathan@Sun.COM 	}
48811374SSukumar.Swaminathan@Sun.COM 	if (state & ATTACH_STAT_INIT) {
48911374SSukumar.Swaminathan@Sun.COM 		oce_stat_fini(dev);
49011374SSukumar.Swaminathan@Sun.COM 	}
49111723SSukumar.Swaminathan@Sun.COM 	if (state & ATTACH_SETUP_ADAP) {
49211723SSukumar.Swaminathan@Sun.COM 		oce_unsetup_adapter(dev);
49311723SSukumar.Swaminathan@Sun.COM 	}
49411723SSukumar.Swaminathan@Sun.COM 
49511723SSukumar.Swaminathan@Sun.COM 	if (state & ATTACH_SETUP_TXRX) {
49611723SSukumar.Swaminathan@Sun.COM 		oce_fini_txrx(dev);
49711723SSukumar.Swaminathan@Sun.COM 	}
49811723SSukumar.Swaminathan@Sun.COM 
49911723SSukumar.Swaminathan@Sun.COM 	if (state & ATTACH_HW_INIT) {
50011723SSukumar.Swaminathan@Sun.COM 		oce_hw_fini(dev);
50111374SSukumar.Swaminathan@Sun.COM 	}
502*13020SSukumar.Swaminathan@Sun.COM 	if (state & ATTACH_LOCK_INIT) {
503*13020SSukumar.Swaminathan@Sun.COM 		oce_destroy_locks(dev);
504*13020SSukumar.Swaminathan@Sun.COM 	}
505*13020SSukumar.Swaminathan@Sun.COM 
506*13020SSukumar.Swaminathan@Sun.COM 	if (state & ATTACH_SETUP_INTR) {
507*13020SSukumar.Swaminathan@Sun.COM 		(void) oce_teardown_intr(dev);
508*13020SSukumar.Swaminathan@Sun.COM 	}
50911374SSukumar.Swaminathan@Sun.COM 	if (state & ATTACH_PCI_INIT) {
51011374SSukumar.Swaminathan@Sun.COM 		oce_pci_fini(dev);
51111374SSukumar.Swaminathan@Sun.COM 	}
51211374SSukumar.Swaminathan@Sun.COM 	if (state & ATTACH_FM_INIT) {
51311374SSukumar.Swaminathan@Sun.COM 		oce_fm_fini(dev);
51411374SSukumar.Swaminathan@Sun.COM 	}
51511374SSukumar.Swaminathan@Sun.COM 	if (state & ATTACH_DEV_INIT) {
51611374SSukumar.Swaminathan@Sun.COM 		ddi_set_driver_private(dev->dip, NULL);
51711374SSukumar.Swaminathan@Sun.COM 		kmem_free(dev, sizeof (struct oce_dev));
51811374SSukumar.Swaminathan@Sun.COM 	}
51911374SSukumar.Swaminathan@Sun.COM } /* oce_unconfigure */
52011374SSukumar.Swaminathan@Sun.COM 
52111374SSukumar.Swaminathan@Sun.COM static void
oce_get_params(struct oce_dev * dev)52211374SSukumar.Swaminathan@Sun.COM oce_get_params(struct oce_dev *dev)
52311374SSukumar.Swaminathan@Sun.COM {
52411374SSukumar.Swaminathan@Sun.COM 	uint32_t log_level;
52511374SSukumar.Swaminathan@Sun.COM 	uint16_t mod_mask;
52611374SSukumar.Swaminathan@Sun.COM 	uint16_t severity;
527*13020SSukumar.Swaminathan@Sun.COM 	/*
528*13020SSukumar.Swaminathan@Sun.COM 	 * Allowed values for the driver parameters. If all values in a range
529*13020SSukumar.Swaminathan@Sun.COM 	 * is allowed, the the array has only one value.
530*13020SSukumar.Swaminathan@Sun.COM 	 */
531*13020SSukumar.Swaminathan@Sun.COM 	uint32_t fc_values[] = {OCE_FC_NONE, OCE_FC_TX, OCE_FC_RX,
532*13020SSukumar.Swaminathan@Sun.COM 	    OCE_DEFAULT_FLOW_CONTROL, END};
533*13020SSukumar.Swaminathan@Sun.COM 	uint32_t mtu_values[] = {OCE_MIN_MTU, OCE_MAX_MTU, END};
534*13020SSukumar.Swaminathan@Sun.COM 	uint32_t tx_rs_values[] = {SIZE_256, SIZE_512, SIZE_1K, SIZE_2K, END};
535*13020SSukumar.Swaminathan@Sun.COM 	uint32_t tx_bcl_values[] = {SIZE_128, SIZE_256, SIZE_512, SIZE_1K,
536*13020SSukumar.Swaminathan@Sun.COM 	    SIZE_2K, END};
537*13020SSukumar.Swaminathan@Sun.COM 	uint32_t rx_bcl_values[] = {SIZE_128, SIZE_256, SIZE_512, SIZE_1K,
538*13020SSukumar.Swaminathan@Sun.COM 	    SIZE_2K, END};
539*13020SSukumar.Swaminathan@Sun.COM 	uint32_t rq_fs_values[] = {SIZE_2K, SIZE_4K, SIZE_8K, END};
540*13020SSukumar.Swaminathan@Sun.COM 	uint32_t rq_mb_values[] = {SIZE_2K, SIZE_4K, SIZE_8K, END};
541*13020SSukumar.Swaminathan@Sun.COM 	uint32_t lso_capable_values[] = {0, 1, END};
542*13020SSukumar.Swaminathan@Sun.COM 	uint32_t fm_caps_values[] = {DDI_FM_NOT_CAPABLE, OCE_FM_CAPABILITY,
543*13020SSukumar.Swaminathan@Sun.COM 	    END};
544*13020SSukumar.Swaminathan@Sun.COM 	uint32_t tx_rt_values[] = {END};
545*13020SSukumar.Swaminathan@Sun.COM 	uint32_t rx_ppi_values[] = {END};
546*13020SSukumar.Swaminathan@Sun.COM 	uint32_t rx_rings_values[] = {END};
547*13020SSukumar.Swaminathan@Sun.COM 	uint32_t tx_rings_values[] = {END};
548*13020SSukumar.Swaminathan@Sun.COM 	uint32_t log_level_values[] = {END};
54911374SSukumar.Swaminathan@Sun.COM 
55011374SSukumar.Swaminathan@Sun.COM 	/* non tunables  */
55111374SSukumar.Swaminathan@Sun.COM 	dev->rx_ring_size = OCE_DEFAULT_RX_RING_SIZE;
55211374SSukumar.Swaminathan@Sun.COM 
55311374SSukumar.Swaminathan@Sun.COM 	/* configurable parameters */
554*13020SSukumar.Swaminathan@Sun.COM 	dev->flow_control = oce_get_prop(dev, (char *)flow_control, OCE_FC_NONE,
555*13020SSukumar.Swaminathan@Sun.COM 	    OCE_DEFAULT_FLOW_CONTROL, OCE_DEFAULT_FLOW_CONTROL, fc_values);
55611374SSukumar.Swaminathan@Sun.COM 
557*13020SSukumar.Swaminathan@Sun.COM 	dev->mtu = oce_get_prop(dev, (char *)mtu_prop_name, OCE_MIN_MTU,
558*13020SSukumar.Swaminathan@Sun.COM 	    OCE_MAX_MTU, OCE_MIN_MTU, mtu_values);
559*13020SSukumar.Swaminathan@Sun.COM 
560*13020SSukumar.Swaminathan@Sun.COM 	dev->tx_ring_size = oce_get_prop(dev, (char *)tx_ring_size_name,
561*13020SSukumar.Swaminathan@Sun.COM 	    SIZE_256, SIZE_2K, OCE_DEFAULT_TX_RING_SIZE, tx_rs_values);
562*13020SSukumar.Swaminathan@Sun.COM 
563*13020SSukumar.Swaminathan@Sun.COM 	dev->tx_bcopy_limit = oce_get_prop(dev, (char *)tx_bcopy_limit_name,
564*13020SSukumar.Swaminathan@Sun.COM 	    SIZE_128, SIZE_2K, OCE_DEFAULT_TX_BCOPY_LIMIT, tx_bcl_values);
56511374SSukumar.Swaminathan@Sun.COM 
566*13020SSukumar.Swaminathan@Sun.COM 	dev->rx_bcopy_limit = oce_get_prop(dev, (char *)rx_bcopy_limit_name,
567*13020SSukumar.Swaminathan@Sun.COM 	    SIZE_128, SIZE_2K, OCE_DEFAULT_RX_BCOPY_LIMIT, rx_bcl_values);
568*13020SSukumar.Swaminathan@Sun.COM 
569*13020SSukumar.Swaminathan@Sun.COM 	dev->rq_frag_size = oce_get_prop(dev, (char *)rx_frag_size_name,
570*13020SSukumar.Swaminathan@Sun.COM 	    SIZE_2K, SIZE_8K, OCE_RQ_BUF_SIZE, rq_fs_values);
571*13020SSukumar.Swaminathan@Sun.COM 
572*13020SSukumar.Swaminathan@Sun.COM 	dev->rq_max_bufs = oce_get_prop(dev, (char *)rx_max_bufs_name, SIZE_2K,
573*13020SSukumar.Swaminathan@Sun.COM 	    SIZE_8K, OCE_RQ_NUM_BUFFERS, rq_mb_values);
57411374SSukumar.Swaminathan@Sun.COM 
575*13020SSukumar.Swaminathan@Sun.COM 	dev->lso_capable = oce_get_prop(dev, (char *)lso_capable_name, 0,
576*13020SSukumar.Swaminathan@Sun.COM 	    1, 1, lso_capable_values);
577*13020SSukumar.Swaminathan@Sun.COM 
578*13020SSukumar.Swaminathan@Sun.COM 	dev->fm_caps = oce_get_prop(dev, (char *)fm_cap_name,
579*13020SSukumar.Swaminathan@Sun.COM 	    DDI_FM_NOT_CAPABLE, OCE_FM_CAPABILITY, OCE_FM_CAPABILITY,
580*13020SSukumar.Swaminathan@Sun.COM 	    fm_caps_values);
581*13020SSukumar.Swaminathan@Sun.COM 
582*13020SSukumar.Swaminathan@Sun.COM 	dev->tx_reclaim_threshold = oce_get_prop(dev,
583*13020SSukumar.Swaminathan@Sun.COM 	    (char *)tx_reclaim_threshold_name, 0, dev->tx_ring_size/2,
584*13020SSukumar.Swaminathan@Sun.COM 	    OCE_DEFAULT_TX_RECLAIM_THRESHOLD, tx_rt_values);
58511374SSukumar.Swaminathan@Sun.COM 
586*13020SSukumar.Swaminathan@Sun.COM 	dev->rx_pkt_per_intr = oce_get_prop(dev, (char *)rx_pkt_per_intr_name,
587*13020SSukumar.Swaminathan@Sun.COM 	    0, dev->rx_ring_size/2, OCE_DEFAULT_RX_PKT_PER_INTR, rx_ppi_values);
588*13020SSukumar.Swaminathan@Sun.COM 
589*13020SSukumar.Swaminathan@Sun.COM 	dev->rx_rings = oce_get_prop(dev, (char *)rx_rings_name,
590*13020SSukumar.Swaminathan@Sun.COM 	    OCE_DEFAULT_RQS, OCE_MAX_RQS, OCE_DEFAULT_RQS, rx_rings_values);
59111374SSukumar.Swaminathan@Sun.COM 
592*13020SSukumar.Swaminathan@Sun.COM 	dev->tx_rings = oce_get_prop(dev, (char *)tx_rings_name,
593*13020SSukumar.Swaminathan@Sun.COM 	    OCE_DEFAULT_WQS, OCE_DEFAULT_WQS, OCE_DEFAULT_WQS, tx_rings_values);
59411374SSukumar.Swaminathan@Sun.COM 
595*13020SSukumar.Swaminathan@Sun.COM 	log_level = oce_get_prop(dev, (char *)log_level_name, 0,
596*13020SSukumar.Swaminathan@Sun.COM 	    OCE_MAX_LOG_SETTINGS, OCE_DEFAULT_LOG_SETTINGS, log_level_values);
597*13020SSukumar.Swaminathan@Sun.COM 
59811374SSukumar.Swaminathan@Sun.COM 	severity = (uint16_t)(log_level & 0xffff);
59911374SSukumar.Swaminathan@Sun.COM 	mod_mask = (uint16_t)(log_level >> 16);
60011374SSukumar.Swaminathan@Sun.COM 	if (mod_mask > MOD_ISR) {
60111374SSukumar.Swaminathan@Sun.COM 		mod_mask = 0;
60211374SSukumar.Swaminathan@Sun.COM 	}
60311374SSukumar.Swaminathan@Sun.COM 	if (severity > CE_IGNORE) {
60411374SSukumar.Swaminathan@Sun.COM 		severity = 0;
60511374SSukumar.Swaminathan@Sun.COM 	}
60611374SSukumar.Swaminathan@Sun.COM 
60711374SSukumar.Swaminathan@Sun.COM 	dev->mod_mask = mod_mask;
60811374SSukumar.Swaminathan@Sun.COM 	dev->severity = severity;
60911374SSukumar.Swaminathan@Sun.COM } /* oce_get_params */
610*13020SSukumar.Swaminathan@Sun.COM 
611*13020SSukumar.Swaminathan@Sun.COM static int
oce_get_prop(struct oce_dev * dev,char * propname,int minval,int maxval,int defval,uint32_t * values)612*13020SSukumar.Swaminathan@Sun.COM oce_get_prop(struct oce_dev *dev, char *propname, int minval, int maxval,
613*13020SSukumar.Swaminathan@Sun.COM     int defval, uint32_t *values)
614*13020SSukumar.Swaminathan@Sun.COM {
615*13020SSukumar.Swaminathan@Sun.COM 	int value = 0;
616*13020SSukumar.Swaminathan@Sun.COM 	int i = 0;
617*13020SSukumar.Swaminathan@Sun.COM 
618*13020SSukumar.Swaminathan@Sun.COM 	value = ddi_prop_get_int(DDI_DEV_T_ANY, dev->dip,
619*13020SSukumar.Swaminathan@Sun.COM 	    DDI_PROP_DONTPASS, propname, defval);
620*13020SSukumar.Swaminathan@Sun.COM 
621*13020SSukumar.Swaminathan@Sun.COM 	if (value > maxval)
622*13020SSukumar.Swaminathan@Sun.COM 		value = maxval;
623*13020SSukumar.Swaminathan@Sun.COM 
624*13020SSukumar.Swaminathan@Sun.COM 	if (value < minval)
625*13020SSukumar.Swaminathan@Sun.COM 		value = minval;
626*13020SSukumar.Swaminathan@Sun.COM 
627*13020SSukumar.Swaminathan@Sun.COM 	while (values[i] != 0xdeadface) {
628*13020SSukumar.Swaminathan@Sun.COM 		if (values[i] == value) {
629*13020SSukumar.Swaminathan@Sun.COM 			break;
630*13020SSukumar.Swaminathan@Sun.COM 		}
631*13020SSukumar.Swaminathan@Sun.COM 		i++;
632*13020SSukumar.Swaminathan@Sun.COM 	}
633*13020SSukumar.Swaminathan@Sun.COM 
634*13020SSukumar.Swaminathan@Sun.COM 	if ((i != 0) && (values[i] == 0xdeadface)) {
635*13020SSukumar.Swaminathan@Sun.COM 		value = defval;
636*13020SSukumar.Swaminathan@Sun.COM 	}
637*13020SSukumar.Swaminathan@Sun.COM 
638*13020SSukumar.Swaminathan@Sun.COM 	return (value);
639*13020SSukumar.Swaminathan@Sun.COM }
640