xref: /illumos-gate/usr/src/uts/common/io/xge/drv/xge.c (revision da14cebe)
1a23fd118Syl /*
2a23fd118Syl  * CDDL HEADER START
3a23fd118Syl  *
4a23fd118Syl  * The contents of this file are subject to the terms of the
5a23fd118Syl  * Common Development and Distribution License (the "License").
6a23fd118Syl  * You may not use this file except in compliance with the License.
7a23fd118Syl  *
8a23fd118Syl  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9a23fd118Syl  * or http://www.opensolaris.org/os/licensing.
10a23fd118Syl  * See the License for the specific language governing permissions
11a23fd118Syl  * and limitations under the License.
12a23fd118Syl  *
13a23fd118Syl  * When distributing Covered Code, include this CDDL HEADER in each
14a23fd118Syl  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15a23fd118Syl  * If applicable, add the following below this CDDL HEADER, with the
16a23fd118Syl  * fields enclosed by brackets "[]" replaced with your own identifying
17a23fd118Syl  * information: Portions Copyright [yyyy] [name of copyright owner]
18a23fd118Syl  *
19a23fd118Syl  * CDDL HEADER END
20a23fd118Syl  */
21a23fd118Syl 
22a23fd118Syl /*
237eced415Sxw  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24a23fd118Syl  * Use is subject to license terms.
25a23fd118Syl  */
26a23fd118Syl 
27a23fd118Syl /*
28a23fd118Syl  *  Copyright (c) 2002-2005 Neterion, Inc.
29a23fd118Syl  *  All right Reserved.
30a23fd118Syl  *
31a23fd118Syl  *  FileName :    xge.c
32a23fd118Syl  *
33a23fd118Syl  *  Description:  Xge main Solaris specific initialization & routines
34a23fd118Syl  *		  for upper layer driver
35a23fd118Syl  *
36a23fd118Syl  */
37a23fd118Syl #include "xgell.h"
38a23fd118Syl 
39a23fd118Syl static int xge_attach(dev_info_t *dev_info, ddi_attach_cmd_t cmd);
40a23fd118Syl static int xge_detach(dev_info_t *dev_info, ddi_detach_cmd_t cmd);
4119397407SSherry Moore static int xge_quiesce(dev_info_t *dev_info);
42a23fd118Syl 
43a23fd118Syl DDI_DEFINE_STREAM_OPS(xge_ops, nulldev, nulldev, xge_attach, xge_detach,
4419397407SSherry Moore     nodev, NULL, D_MP, NULL, xge_quiesce);
45a23fd118Syl 
46a23fd118Syl /* Standard Module linkage initialization for a Streams driver */
47a23fd118Syl extern struct mod_ops mod_driverops;
48a23fd118Syl 
49a23fd118Syl static struct modldrv modldrv = {
50a23fd118Syl 	&mod_driverops,		/* Type of module.  This one is a driver */
51a23fd118Syl 	XGELL_DESC,		/* short description */
52a23fd118Syl 	&xge_ops		/* driver specific ops */
53a23fd118Syl };
54a23fd118Syl 
55a23fd118Syl static struct modlinkage modlinkage = {
56a23fd118Syl 	MODREV_1, {(void *)&modldrv, NULL}
57a23fd118Syl };
58a23fd118Syl 
59a23fd118Syl /* Xge device attributes */
60a23fd118Syl ddi_device_acc_attr_t xge_dev_attr = {
61a23fd118Syl 	DDI_DEVICE_ATTR_V0,
62a23fd118Syl 	DDI_NEVERSWAP_ACC,
63a23fd118Syl 	DDI_STRICTORDER_ACC
64a23fd118Syl };
65a23fd118Syl ddi_device_acc_attr_t *p_xge_dev_attr = &xge_dev_attr;
66a23fd118Syl 
67a23fd118Syl /*
68a23fd118Syl  * xgell_callback_crit_err
69a23fd118Syl  *
70a23fd118Syl  * This function called by HAL on Serious Error event. XGE_HAL_EVENT_SERR.
71a23fd118Syl  * Upper layer must analyze it based on %type.
72a23fd118Syl  */
73a23fd118Syl static void
xge_callback_crit_err(void * userdata,xge_hal_event_e type,u64 serr_data)74a23fd118Syl xge_callback_crit_err(void *userdata, xge_hal_event_e type, u64 serr_data)
75a23fd118Syl {
76a23fd118Syl 	(void) xgell_onerr_reset(userdata);
77a23fd118Syl }
78a23fd118Syl 
797eced415Sxw /*
807eced415Sxw  * xge_xpak_alarm_log
817eced415Sxw  * This function called by HAL on XPAK alarms. Upper layer must log the msg
827eced415Sxw  * based on the xpak alarm type
837eced415Sxw  */
847eced415Sxw static void
xge_xpak_alarm_log(void * userdata,xge_hal_xpak_alarm_type_e type)857eced415Sxw xge_xpak_alarm_log(void *userdata, xge_hal_xpak_alarm_type_e type)
867eced415Sxw {
877eced415Sxw 	switch (type) {
887eced415Sxw 	case XGE_HAL_XPAK_ALARM_EXCESS_TEMP:
897eced415Sxw 		xge_debug_osdep(XGE_ERR, "%s", "Take Xframe NIC out of "
907eced415Sxw 		    "service. Excessive temperatures may result in "
917eced415Sxw 		    "premature transceiver failure \n");
927eced415Sxw 
937eced415Sxw 		break;
947eced415Sxw 	case XGE_HAL_XPAK_ALARM_EXCESS_BIAS_CURRENT:
957eced415Sxw 		xge_debug_osdep(XGE_ERR, "%s", "Take Xframe NIC out of "
967eced415Sxw 		    "service Excessive bias currents may indicate "
977eced415Sxw 		    "imminent laser diode failure \n");
987eced415Sxw 
997eced415Sxw 		break;
1007eced415Sxw 	case XGE_HAL_XPAK_ALARM_EXCESS_LASER_OUTPUT:
1017eced415Sxw 		xge_debug_osdep(XGE_ERR, "%s", "Take Xframe NIC out of "
1027eced415Sxw 		    "service Excessive laser output power may saturate "
1037eced415Sxw 		    "far-end receiver\n");
1047eced415Sxw 
1057eced415Sxw 		break;
1067eced415Sxw 	default:
1077eced415Sxw 		xge_debug_osdep(XGE_ERR, "%s", "Undefined Xpak Alarm");
1087eced415Sxw 		break;
1097eced415Sxw 	}
1107eced415Sxw 
1117eced415Sxw }
1127eced415Sxw 
113a23fd118Syl /*
114a23fd118Syl  * xge_driver_init_hal
115a23fd118Syl  *
116a23fd118Syl  * To initialize HAL portion of driver.
117a23fd118Syl  */
118a23fd118Syl static xge_hal_status_e
xge_driver_init_hal(void)119a23fd118Syl xge_driver_init_hal(void)
120a23fd118Syl {
121a23fd118Syl 	static xge_hal_driver_config_t driver_config;
122a23fd118Syl 	xge_hal_uld_cbs_t uld_callbacks;
123a23fd118Syl 
124a23fd118Syl 	driver_config.queue_size_initial = 1;
125a23fd118Syl 	driver_config.queue_size_max = 4;
126a23fd118Syl 
127a23fd118Syl 	uld_callbacks.link_up = xgell_callback_link_up;
128a23fd118Syl 	uld_callbacks.link_down = xgell_callback_link_down;
129a23fd118Syl 	uld_callbacks.crit_err = xge_callback_crit_err;
130*da14cebeSEric Cheng 	uld_callbacks.event = NULL;
131*da14cebeSEric Cheng 	uld_callbacks.event_queued = NULL;
132a23fd118Syl 	uld_callbacks.before_device_poll = NULL;
133a23fd118Syl 	uld_callbacks.after_device_poll = NULL;
134a23fd118Syl 	uld_callbacks.sched_timer = NULL;
1357eced415Sxw 	uld_callbacks.xpak_alarm_log = xge_xpak_alarm_log;
136a23fd118Syl 
137a23fd118Syl 	return (xge_hal_driver_initialize(&driver_config, &uld_callbacks));
138a23fd118Syl 
139a23fd118Syl }
140a23fd118Syl 
141a23fd118Syl /*
142a23fd118Syl  * _init
143a23fd118Syl  *
144a23fd118Syl  * Solaris standard _init function for a device driver
145a23fd118Syl  */
146a23fd118Syl int
_init(void)147a23fd118Syl _init(void)
148a23fd118Syl {
149a23fd118Syl 	int ret = 0;
150a23fd118Syl 	xge_hal_status_e status;
151a23fd118Syl 
152a23fd118Syl 	status = xge_driver_init_hal();
153a23fd118Syl 	if (status != XGE_HAL_OK) {
154a23fd118Syl 		xge_debug_osdep(XGE_ERR, "can't initialize the driver (%d)",
155a23fd118Syl 		    status);
156a23fd118Syl 		return (EINVAL);
157a23fd118Syl 	}
158a23fd118Syl 
159a23fd118Syl 	xge_hal_driver_debug_module_mask_set(0xffffffff);
160a23fd118Syl 	xge_hal_driver_debug_level_set(XGE_TRACE);
161a23fd118Syl 
162a23fd118Syl 	mac_init_ops(&xge_ops, "xge");
163a23fd118Syl 	if ((ret = mod_install(&modlinkage)) != 0) {
164a23fd118Syl 		xge_hal_driver_terminate();
165a23fd118Syl 		mac_fini_ops(&xge_ops);
166a23fd118Syl 		xge_debug_osdep(XGE_ERR, "%s",
167a23fd118Syl 		    "Unable to install the driver");
168a23fd118Syl 		return (ret);
169a23fd118Syl 	}
170a23fd118Syl 
171a23fd118Syl 	return (0);
172a23fd118Syl }
173a23fd118Syl 
174a23fd118Syl /*
175a23fd118Syl  * _fini
176a23fd118Syl  *
177a23fd118Syl  * Solaris standard _fini function for device driver
178a23fd118Syl  */
179a23fd118Syl int
_fini(void)180a23fd118Syl _fini(void)
181a23fd118Syl {
182a23fd118Syl 	int ret;
183a23fd118Syl 
184a23fd118Syl 	ret = mod_remove(&modlinkage);
185a23fd118Syl 	if (ret == 0) {
186a23fd118Syl 		xge_hal_driver_terminate();
187a23fd118Syl 		mac_fini_ops(&xge_ops);
188a23fd118Syl 	}
189a23fd118Syl 
190a23fd118Syl 	return (ret);
191a23fd118Syl }
192a23fd118Syl 
193a23fd118Syl /*
194a23fd118Syl  * _info
195a23fd118Syl  *
196a23fd118Syl  * Solaris standard _info function for device driver
197a23fd118Syl  */
198a23fd118Syl int
_info(struct modinfo * pModinfo)199a23fd118Syl _info(struct modinfo *pModinfo)
200a23fd118Syl {
201a23fd118Syl 	return (mod_info(&modlinkage, pModinfo));
202a23fd118Syl }
203a23fd118Syl 
204a23fd118Syl /*
205a23fd118Syl  * xge_isr
206a23fd118Syl  * @arg: pointer to device private strucutre(hldev)
207a23fd118Syl  *
208a23fd118Syl  * This is the ISR scheduled by the OS to indicate to the
209a23fd118Syl  * driver that the receive/transmit operation is completed.
210a23fd118Syl  */
211*da14cebeSEric Cheng /* ARGSUSED */
212a23fd118Syl static uint_t
xge_isr(caddr_t arg0,caddr_t arg1)2137eced415Sxw xge_isr(caddr_t arg0, caddr_t arg1)
214a23fd118Syl {
215a23fd118Syl 	xge_hal_status_e status;
2167eced415Sxw 	xge_hal_device_t *hldev = (xge_hal_device_t *)arg0;
217a23fd118Syl 	xgelldev_t *lldev = xge_hal_device_private(hldev);
218a23fd118Syl 
219a23fd118Syl 	if (!lldev->is_initialized) {
2207eced415Sxw 		return (DDI_INTR_UNCLAIMED);
221a23fd118Syl 	}
222a23fd118Syl 
223a23fd118Syl 	status = xge_hal_device_handle_irq(hldev);
224a23fd118Syl 
225a23fd118Syl 	return ((status == XGE_HAL_ERR_WRONG_IRQ) ?
226a23fd118Syl 	    DDI_INTR_UNCLAIMED : DDI_INTR_CLAIMED);
227a23fd118Syl }
228a23fd118Syl 
2297eced415Sxw /*
2307eced415Sxw  * Interrupt handler for transmit when MSI-X interrupt mechasnism is used
2317eced415Sxw  */
2327eced415Sxw /* ARGSUSED */
2337eced415Sxw static uint_t
xge_fifo_msix_isr(caddr_t arg0,caddr_t arg1)2347eced415Sxw xge_fifo_msix_isr(caddr_t arg0, caddr_t arg1)
2357eced415Sxw {
2367eced415Sxw 	int got_tx;
2377eced415Sxw 	xge_hal_channel_t *channel = (xge_hal_channel_t *)arg0;
2387eced415Sxw 	xgelldev_t *lldev = xge_hal_device_private(channel->devh);
2397eced415Sxw 
2407eced415Sxw 	if (!lldev->is_initialized) {
2417eced415Sxw 		return (DDI_INTR_UNCLAIMED);
2427eced415Sxw 	}
2437eced415Sxw 	(void) xge_hal_device_poll_tx_channel(channel, &got_tx);
2447eced415Sxw 
2457eced415Sxw 	return (DDI_INTR_CLAIMED);
2467eced415Sxw }
2477eced415Sxw 
2487eced415Sxw /*
2497eced415Sxw  * Interrupt handler for receive when MSI-X interrupt mechasnism is used
2507eced415Sxw  */
2517eced415Sxw /* ARGSUSED */
2527eced415Sxw static uint_t
xge_ring_msix_isr(caddr_t arg0,caddr_t arg1)2537eced415Sxw xge_ring_msix_isr(caddr_t arg0, caddr_t arg1)
2547eced415Sxw {
2557eced415Sxw 	int got_rx;
2567eced415Sxw 	xge_hal_channel_t *channel = (xge_hal_channel_t *)arg0;
2577eced415Sxw 	xgelldev_t *lldev = xge_hal_device_private(channel->devh);
2587eced415Sxw 
2597eced415Sxw 	if (!lldev->is_initialized) {
2607eced415Sxw 		return (DDI_INTR_UNCLAIMED);
2617eced415Sxw 	}
2627eced415Sxw 	(void) xge_hal_device_poll_rx_channel(channel, &got_rx);
2637eced415Sxw 
2647eced415Sxw 	return (DDI_INTR_CLAIMED);
2657eced415Sxw }
2667eced415Sxw 
2677eced415Sxw /*
2687eced415Sxw  * Configure single ring
2697eced415Sxw  */
2707eced415Sxw static void
xge_ring_config(dev_info_t * dev_info,xge_hal_device_config_t * device_config,int index)271*da14cebeSEric Cheng xge_ring_config(dev_info_t *dev_info, xge_hal_device_config_t *device_config,
272*da14cebeSEric Cheng     int index)
2737eced415Sxw {
2747eced415Sxw 	char msg[MSG_SIZE];
2757eced415Sxw 
276*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_configured", index);
277*da14cebeSEric Cheng 	device_config->ring.queue[index].configured =
2787eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS,
279*da14cebeSEric Cheng 	    msg, index < XGELL_RX_RING_NUM_MAX ? 1 : 0);
2807eced415Sxw 
2817eced415Sxw 	/* no point to configure it further if unconfigured */
282*da14cebeSEric Cheng 	if (!device_config->ring.queue[index].configured)
2837eced415Sxw 		return;
2847eced415Sxw 
2857eced415Sxw #if defined(__sparc)
286*da14cebeSEric Cheng 	device_config->ring.queue[index].no_snoop_bits = 1;
2877eced415Sxw #endif
2887eced415Sxw 
289*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_max", index);
290*da14cebeSEric Cheng 	device_config->ring.queue[index].max =
2917eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY,
2927eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
2937eced415Sxw 	    XGE_HAL_DEFAULT_USE_HARDCODE);
2947eced415Sxw 
295*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_initial", index);
296*da14cebeSEric Cheng 	device_config->ring.queue[index].initial =
2977eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY,
2987eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
2997eced415Sxw 	    XGE_HAL_DEFAULT_USE_HARDCODE);
3007eced415Sxw 
301*da14cebeSEric Cheng 	if (device_config->ring.queue[index].initial ==
3027eced415Sxw 	    XGE_HAL_DEFAULT_USE_HARDCODE) {
303*da14cebeSEric Cheng 		device_config->ring.queue[index].initial =
304*da14cebeSEric Cheng 		    device_config->ring.queue[index].max =
305*da14cebeSEric Cheng 		    XGE_HAL_DEFAULT_RING_QUEUE_BLOCKS;
3067eced415Sxw 	}
3077eced415Sxw 
308*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_buffer_mode", index);
309*da14cebeSEric Cheng 	device_config->ring.queue[index].buffer_mode =
3107eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY,
3117eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
3127eced415Sxw 	    XGE_HAL_RING_QUEUE_BUFFER_MODE_DEFAULT);
3137eced415Sxw 
314*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_dram_size_mb", index);
315*da14cebeSEric Cheng 	device_config->ring.queue[index].dram_size_mb =
3167eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY,
3177eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
3187eced415Sxw 	    XGE_HAL_DEFAULT_USE_HARDCODE);
3197eced415Sxw 
3207eced415Sxw 	(void) xge_os_snprintf(msg, MSG_SIZE,
321*da14cebeSEric Cheng 	    "ring%d_backoff_interval_us", index);
322*da14cebeSEric Cheng 	device_config->ring.queue[index].backoff_interval_us =
3237eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY,
3247eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
3257eced415Sxw 	    XGE_HAL_DEFAULT_BACKOFF_INTERVAL_US);
3267eced415Sxw 
327*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_max_frm_len", index);
328*da14cebeSEric Cheng 	device_config->ring.queue[index].max_frm_len =
3297eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY,
3307eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
3317eced415Sxw 	    XGE_HAL_RING_USE_MTU);
3327eced415Sxw 
3337eced415Sxw 
334*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_priority", index);
335*da14cebeSEric Cheng 	device_config->ring.queue[index].priority =
3367eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY,
3377eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
3387eced415Sxw 	    XGE_HAL_DEFAULT_RING_PRIORITY);
3397eced415Sxw 
340*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_urange_a", index);
341*da14cebeSEric Cheng 	device_config->ring.queue[index].rti.urange_a =
3427eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY,
3437eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
3447eced415Sxw 	    XGE_HAL_DEFAULT_RX_URANGE_A);
3457eced415Sxw 
346*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_ufc_a", index);
347*da14cebeSEric Cheng 	device_config->ring.queue[index].rti.ufc_a =
3487eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY,
3497eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
3507eced415Sxw 	    XGE_HAL_DEFAULT_RX_UFC_A);
3517eced415Sxw 
352*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_urange_b", index);
353*da14cebeSEric Cheng 	device_config->ring.queue[index].rti.urange_b =
3547eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY,
3557eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
3567eced415Sxw 	    XGE_HAL_DEFAULT_RX_URANGE_B);
3577eced415Sxw 
358*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_ufc_b", index);
359*da14cebeSEric Cheng 	device_config->ring.queue[index].rti.ufc_b =
3607eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY,
3617eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
3627eced415Sxw 	    device_config->mtu > XGE_HAL_DEFAULT_MTU ?
3637eced415Sxw 	    XGE_HAL_DEFAULT_RX_UFC_B_J:
3647eced415Sxw 	    XGE_HAL_DEFAULT_RX_UFC_B_N);
3657eced415Sxw 
366*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_urange_c", index);
367*da14cebeSEric Cheng 	device_config->ring.queue[index].rti.urange_c =
3687eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY,
3697eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
3707eced415Sxw 	    XGE_HAL_DEFAULT_RX_URANGE_C);
3717eced415Sxw 
372*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_ufc_c", index);
373*da14cebeSEric Cheng 	device_config->ring.queue[index].rti.ufc_c =
3747eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY,
3757eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
3767eced415Sxw 	    device_config->mtu > XGE_HAL_DEFAULT_MTU ?
3777eced415Sxw 	    XGE_HAL_DEFAULT_RX_UFC_C_J:
3787eced415Sxw 	    XGE_HAL_DEFAULT_RX_UFC_C_N);
3797eced415Sxw 
380*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_ufc_d", index);
381*da14cebeSEric Cheng 	device_config->ring.queue[index].rti.ufc_d =
3827eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY,
3837eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
3847eced415Sxw 	    XGE_HAL_DEFAULT_RX_UFC_D);
3857eced415Sxw 
386*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_timer_val", index);
387*da14cebeSEric Cheng 	device_config->ring.queue[index].rti.timer_val_us =
3887eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY,
3897eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
3907eced415Sxw 	    XGE_HAL_DEFAULT_RX_TIMER_VAL);
3917eced415Sxw 
392*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_timer_ac_en", index);
393*da14cebeSEric Cheng 	device_config->ring.queue[index].rti.timer_ac_en =
3947eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY,
3957eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
3967eced415Sxw 	    XGE_HAL_DEFAULT_RX_TIMER_AC_EN);
3977eced415Sxw 
398*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_indicate_max_pkts",
399*da14cebeSEric Cheng 	    index);
400*da14cebeSEric Cheng 	device_config->ring.queue[index].indicate_max_pkts =
4017eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY,
4027eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
4037eced415Sxw 	    (device_config->bimodal_interrupts ?
4047eced415Sxw 	    XGE_HAL_DEFAULT_INDICATE_MAX_PKTS_B :
4057eced415Sxw 	    XGE_HAL_DEFAULT_INDICATE_MAX_PKTS_N));
4067eced415Sxw 
407*da14cebeSEric Cheng 	/*
408*da14cebeSEric Cheng 	 * Enable RTH steering if needed HERE!!!!
409*da14cebeSEric Cheng 	 */
410*da14cebeSEric Cheng 	if (device_config->rth_en == XGE_HAL_RTH_ENABLE)
411*da14cebeSEric Cheng 		device_config->ring.queue[index].rth_en = 1;
4127eced415Sxw }
4137eced415Sxw 
4147eced415Sxw /*
4157eced415Sxw  * Configure single fifo
4167eced415Sxw  */
4177eced415Sxw static void
xge_fifo_config(dev_info_t * dev_info,xge_hal_device_config_t * device_config,int index)418*da14cebeSEric Cheng xge_fifo_config(dev_info_t *dev_info, xge_hal_device_config_t *device_config,
419*da14cebeSEric Cheng     int index)
4207eced415Sxw {
4217eced415Sxw 	char msg[MSG_SIZE];
4227eced415Sxw 
423*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_configured", index);
424*da14cebeSEric Cheng 	device_config->fifo.queue[index].configured =
4257eced415Sxw 	    ddi_prop_get_int(DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS,
426*da14cebeSEric Cheng 	    msg, index < XGELL_TX_RING_NUM_MAX ? 1 : 0);
4277eced415Sxw 
4287eced415Sxw 	/* no point to configure it further */
429*da14cebeSEric Cheng 	if (!device_config->fifo.queue[index].configured)
4307eced415Sxw 		return;
4317eced415Sxw 
4327eced415Sxw #if defined(__sparc)
433*da14cebeSEric Cheng 	device_config->fifo.queue[index].no_snoop_bits = 1;
4347eced415Sxw #endif
4357eced415Sxw 
436*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_max", index);
437*da14cebeSEric Cheng 	device_config->fifo.queue[index].max = ddi_prop_get_int(DDI_DEV_T_ANY,
4387eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
4397eced415Sxw 	    XGE_HAL_DEFAULT_USE_HARDCODE);
4407eced415Sxw 
441*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_initial", index);
442*da14cebeSEric Cheng 	device_config->fifo.queue[index].initial =
443*da14cebeSEric Cheng 	    ddi_prop_get_int(DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg,
4447eced415Sxw 	    XGE_HAL_DEFAULT_USE_HARDCODE);
4457eced415Sxw 
446*da14cebeSEric Cheng #if 0
447*da14cebeSEric Cheng 	if (device_config->fifo.queue[index].initial ==
4487eced415Sxw 	    XGE_HAL_DEFAULT_USE_HARDCODE) {
4497eced415Sxw 		if (device_config->mtu > XGE_HAL_DEFAULT_MTU) {
450*da14cebeSEric Cheng 			device_config->fifo.queue[index].initial =
451*da14cebeSEric Cheng 			    device_config->fifo.queue[index].max =
4527eced415Sxw 			    XGE_HAL_DEFAULT_FIFO_QUEUE_LENGTH_J;
4537eced415Sxw 		} else {
454*da14cebeSEric Cheng 			device_config->fifo.queue[index].initial =
455*da14cebeSEric Cheng 			    device_config->fifo.queue[index].max =
4567eced415Sxw 			    XGE_HAL_DEFAULT_FIFO_QUEUE_LENGTH_N;
4577eced415Sxw 		}
4587eced415Sxw 	}
459*da14cebeSEric Cheng #else
460*da14cebeSEric Cheng 	if (device_config->fifo.queue[index].initial ==
461*da14cebeSEric Cheng 	    XGE_HAL_DEFAULT_USE_HARDCODE) {
462*da14cebeSEric Cheng 		device_config->fifo.queue[index].max =
463*da14cebeSEric Cheng 		    device_config->fifo.queue[index].initial =
464*da14cebeSEric Cheng 		    XGE_HAL_DEFAULT_FIFO_QUEUE_LENGTH_A;
465*da14cebeSEric Cheng 	}
466*da14cebeSEric Cheng #endif
4677eced415Sxw 
468*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_intr", index);
469*da14cebeSEric Cheng 	device_config->fifo.queue[index].intr = ddi_prop_get_int(DDI_DEV_T_ANY,
4707eced415Sxw 	    dev_info, DDI_PROP_DONTPASS, msg,
4717eced415Sxw 	    XGE_HAL_DEFAULT_FIFO_QUEUE_INTR);
4727eced415Sxw 
4737eced415Sxw 	/*
4747eced415Sxw 	 * TTI 0 configuration
4757eced415Sxw 	 */
476*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_enable", index);
477*da14cebeSEric Cheng 	device_config->fifo.queue[index].tti[index].enabled = ddi_prop_get_int(
4787eced415Sxw 	    DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg, 1);
4797eced415Sxw 
480*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_urange_a", index);
481*da14cebeSEric Cheng 	device_config->fifo.queue[index].tti[index].urange_a = ddi_prop_get_int(
4827eced415Sxw 	    DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg,
4837eced415Sxw 	    XGE_HAL_DEFAULT_TX_URANGE_A);
4847eced415Sxw 
485*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_ufc_a", index);
486*da14cebeSEric Cheng 	device_config->fifo.queue[index].tti[index].ufc_a = ddi_prop_get_int(
4877eced415Sxw 	    DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg,
4887eced415Sxw 	    XGE_HAL_DEFAULT_TX_UFC_A);
4897eced415Sxw 
490*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_urange_b", index);
491*da14cebeSEric Cheng 	device_config->fifo.queue[index].tti[index].urange_b = ddi_prop_get_int(
4927eced415Sxw 	    DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg,
4937eced415Sxw 	    XGE_HAL_DEFAULT_TX_URANGE_B);
4947eced415Sxw 
495*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_ufc_b", index);
496*da14cebeSEric Cheng 	device_config->fifo.queue[index].tti[index].ufc_b = ddi_prop_get_int(
4977eced415Sxw 	    DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg,
4987eced415Sxw 	    XGE_HAL_DEFAULT_TX_UFC_B);
4997eced415Sxw 
500*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_urange_c", index);
501*da14cebeSEric Cheng 	device_config->fifo.queue[index].tti[index].urange_c = ddi_prop_get_int(
5027eced415Sxw 	    DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg,
5037eced415Sxw 	    XGE_HAL_DEFAULT_TX_URANGE_C);
5047eced415Sxw 
505*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_ufc_c", index);
506*da14cebeSEric Cheng 	device_config->fifo.queue[index].tti[index].ufc_c = ddi_prop_get_int(
5077eced415Sxw 	    DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg,
5087eced415Sxw 	    XGE_HAL_DEFAULT_TX_UFC_C);
5097eced415Sxw 
510*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_ufc_d", index);
511*da14cebeSEric Cheng 	device_config->fifo.queue[index].tti[index].ufc_d = ddi_prop_get_int(
5127eced415Sxw 	    DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg,
5137eced415Sxw 	    XGE_HAL_DEFAULT_TX_UFC_D);
5147eced415Sxw 
515*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_timer_ac_en", index);
516*da14cebeSEric Cheng 	device_config->fifo.queue[index].tti[index].timer_ac_en =
517*da14cebeSEric Cheng 	    ddi_prop_get_int(DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg,
5187eced415Sxw 	    XGE_HAL_DEFAULT_TX_TIMER_AC_EN);
5197eced415Sxw 
520*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_timer_val", index);
521*da14cebeSEric Cheng 	device_config->fifo.queue[index].tti[index].timer_val_us =
522*da14cebeSEric Cheng 	    ddi_prop_get_int(DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg,
5237eced415Sxw 	    XGE_HAL_DEFAULT_TX_TIMER_VAL);
5247eced415Sxw 
525*da14cebeSEric Cheng 	(void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_timer_ci_en", index);
526*da14cebeSEric Cheng 	device_config->fifo.queue[index].tti[index].timer_ci_en =
527*da14cebeSEric Cheng 	    ddi_prop_get_int(DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg,
5287eced415Sxw 	    XGE_HAL_DEFAULT_TX_TIMER_CI_EN);
5297eced415Sxw }
5307eced415Sxw 
531a23fd118Syl /*
532a23fd118Syl  * xge_configuration_init
533a23fd118Syl  * @device_config: pointer to xge_hal_device_config_t
534a23fd118Syl  *
535a23fd118Syl  * This function will lookup properties from .conf file to init
536a23fd118Syl  * the configuration data structure. If a property is not in .conf
537a23fd118Syl  * file, the default value should be set.
538a23fd118Syl  */
539a23fd118Syl static void
xge_configuration_init(dev_info_t * dev_info,xge_hal_device_config_t * device_config,xgell_config_t * xgell_config)540a23fd118Syl xge_configuration_init(dev_info_t *dev_info,
541*da14cebeSEric Cheng     xge_hal_device_config_t *device_config, xgell_config_t *xgell_config)
542a23fd118Syl {
5437eced415Sxw 	int i, rings_configured = 0, fifos_configured = 0;
5447eced415Sxw 
545*da14cebeSEric Cheng 	/*
546*da14cebeSEric Cheng 	 * Initialize link layer configuration first
547*da14cebeSEric Cheng 	 */
548*da14cebeSEric Cheng 	xgell_config->rx_dma_lowat = ddi_prop_get_int(DDI_DEV_T_ANY, dev_info,
549*da14cebeSEric Cheng 	    DDI_PROP_DONTPASS, "rx_dma_lowat", XGELL_RX_DMA_LOWAT);
550*da14cebeSEric Cheng 	xgell_config->rx_pkt_burst = ddi_prop_get_int(DDI_DEV_T_ANY,
551