1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Copyright (c) 2002-2005 Neterion, Inc. 31 * All right Reserved. 32 * 33 * FileName : xge.c 34 * 35 * Description: Xge main Solaris specific initialization & routines 36 * for upper layer driver 37 * 38 */ 39 #include "xgell.h" 40 41 static int xge_attach(dev_info_t *dev_info, ddi_attach_cmd_t cmd); 42 static int xge_detach(dev_info_t *dev_info, ddi_detach_cmd_t cmd); 43 44 DDI_DEFINE_STREAM_OPS(xge_ops, nulldev, nulldev, xge_attach, xge_detach, 45 nodev, NULL, D_MP, NULL); 46 47 /* Standard Module linkage initialization for a Streams driver */ 48 extern struct mod_ops mod_driverops; 49 50 static struct modldrv modldrv = { 51 &mod_driverops, /* Type of module. This one is a driver */ 52 XGELL_DESC, /* short description */ 53 &xge_ops /* driver specific ops */ 54 }; 55 56 static struct modlinkage modlinkage = { 57 MODREV_1, {(void *)&modldrv, NULL} 58 }; 59 60 /* Xge device attributes */ 61 ddi_device_acc_attr_t xge_dev_attr = { 62 DDI_DEVICE_ATTR_V0, 63 DDI_NEVERSWAP_ACC, 64 DDI_STRICTORDER_ACC 65 }; 66 ddi_device_acc_attr_t *p_xge_dev_attr = &xge_dev_attr; 67 68 /* 69 * xge_event 70 * 71 * This function called by HAL to notify upper layer that some any 72 * event been produced. 73 */ 74 void 75 xge_event(xge_queue_item_t *item) 76 { 77 xgelldev_t *lldev = item->context; 78 79 switch (item->event_type) { 80 case XGELL_EVENT_RESCHED_NEEDED: 81 if (lldev->is_initialized) { 82 if (xge_hal_channel_dtr_count(lldev->fifo_channel) 83 >= XGELL_TX_LEVEL_HIGH) { 84 mac_tx_update(lldev->mh); 85 xge_debug_osdep(XGE_TRACE, 86 "mac_tx_update happened!"); 87 } 88 } 89 break; 90 default: 91 break; 92 } 93 } 94 95 /* 96 * xgell_callback_crit_err 97 * 98 * This function called by HAL on Serious Error event. XGE_HAL_EVENT_SERR. 99 * Upper layer must analyze it based on %type. 100 */ 101 static void 102 xge_callback_crit_err(void *userdata, xge_hal_event_e type, u64 serr_data) 103 { 104 (void) xgell_onerr_reset(userdata); 105 } 106 107 /* 108 * xge_queue_produce context 109 */ 110 static void 111 xge_callback_event_queued(xge_hal_device_h devh, int event_type) 112 { 113 if (event_type == XGELL_EVENT_RESCHED_NEEDED) { 114 (void) taskq_dispatch(system_taskq, xge_device_poll_now, devh, 115 TQ_NOSLEEP); 116 } 117 } 118 119 /* 120 * xge_driver_init_hal 121 * 122 * To initialize HAL portion of driver. 123 */ 124 static xge_hal_status_e 125 xge_driver_init_hal(void) 126 { 127 static xge_hal_driver_config_t driver_config; 128 xge_hal_uld_cbs_t uld_callbacks; 129 130 driver_config.queue_size_initial = 1; 131 driver_config.queue_size_max = 4; 132 133 uld_callbacks.link_up = xgell_callback_link_up; 134 uld_callbacks.link_down = xgell_callback_link_down; 135 uld_callbacks.crit_err = xge_callback_crit_err; 136 uld_callbacks.event = xge_event; 137 uld_callbacks.event_queued = xge_callback_event_queued; 138 uld_callbacks.before_device_poll = NULL; 139 uld_callbacks.after_device_poll = NULL; 140 uld_callbacks.sched_timer = NULL; 141 142 return (xge_hal_driver_initialize(&driver_config, &uld_callbacks)); 143 144 } 145 146 /* 147 * _init 148 * 149 * Solaris standard _init function for a device driver 150 */ 151 int 152 _init(void) 153 { 154 int ret = 0; 155 xge_hal_status_e status; 156 157 status = xge_driver_init_hal(); 158 if (status != XGE_HAL_OK) { 159 xge_debug_osdep(XGE_ERR, "can't initialize the driver (%d)", 160 status); 161 return (EINVAL); 162 } 163 164 xge_hal_driver_debug_module_mask_set(0xffffffff); 165 xge_hal_driver_debug_level_set(XGE_TRACE); 166 167 mac_init_ops(&xge_ops, "xge"); 168 if ((ret = mod_install(&modlinkage)) != 0) { 169 xge_hal_driver_terminate(); 170 mac_fini_ops(&xge_ops); 171 xge_debug_osdep(XGE_ERR, "%s", 172 "Unable to install the driver"); 173 return (ret); 174 } 175 176 return (0); 177 } 178 179 /* 180 * _fini 181 * 182 * Solaris standard _fini function for device driver 183 */ 184 int 185 _fini(void) 186 { 187 int ret; 188 189 ret = mod_remove(&modlinkage); 190 if (ret == 0) { 191 xge_hal_driver_terminate(); 192 mac_fini_ops(&xge_ops); 193 } 194 195 return (ret); 196 } 197 198 /* 199 * _info 200 * 201 * Solaris standard _info function for device driver 202 */ 203 int 204 _info(struct modinfo *pModinfo) 205 { 206 return (mod_info(&modlinkage, pModinfo)); 207 } 208 209 /* 210 * xge_isr 211 * @arg: pointer to device private strucutre(hldev) 212 * 213 * This is the ISR scheduled by the OS to indicate to the 214 * driver that the receive/transmit operation is completed. 215 */ 216 static uint_t 217 xge_isr(caddr_t arg) 218 { 219 xge_hal_status_e status; 220 xge_hal_device_t *hldev = (xge_hal_device_t *)arg; 221 xgelldev_t *lldev = xge_hal_device_private(hldev); 222 223 if (!lldev->is_initialized) { 224 return (DDI_INTR_CLAIMED); 225 } 226 227 status = xge_hal_device_handle_irq(hldev); 228 229 return ((status == XGE_HAL_ERR_WRONG_IRQ) ? 230 DDI_INTR_UNCLAIMED : DDI_INTR_CLAIMED); 231 } 232 233 /* 234 * xge_configuration_init 235 * @device_config: pointer to xge_hal_device_config_t 236 * 237 * This function will lookup properties from .conf file to init 238 * the configuration data structure. If a property is not in .conf 239 * file, the default value should be set. 240 */ 241 static void 242 xge_configuration_init(dev_info_t *dev_info, 243 xge_hal_device_config_t *device_config, xgell_config_t *ll_config) 244 { 245 /* 246 * Initialize common properties 247 */ 248 device_config->mtu = ddi_prop_get_int(DDI_DEV_T_ANY, 249 dev_info, DDI_PROP_DONTPASS, "default_mtu", 250 XGE_HAL_DEFAULT_INITIAL_MTU); 251 device_config->isr_polling_cnt = ddi_prop_get_int(DDI_DEV_T_ANY, 252 dev_info, DDI_PROP_DONTPASS, "isr_polling_cnt", 253 XGE_HAL_DEFAULT_ISR_POLLING_CNT); 254 device_config->latency_timer = ddi_prop_get_int(DDI_DEV_T_ANY, 255 dev_info, DDI_PROP_DONTPASS, "latency_timer", 256 XGE_HAL_DEFAULT_LATENCY_TIMER); 257 device_config->max_splits_trans = ddi_prop_get_int(DDI_DEV_T_ANY, 258 dev_info, DDI_PROP_DONTPASS, "max_splits_trans", 259 XGE_HAL_DEFAULT_SPLIT_TRANSACTION); 260 device_config->mmrb_count = ddi_prop_get_int(DDI_DEV_T_ANY, 261 dev_info, DDI_PROP_DONTPASS, "mmrb_count", 262 XGE_HAL_DEFAULT_MMRB_COUNT); 263 device_config->shared_splits = ddi_prop_get_int(DDI_DEV_T_ANY, 264 dev_info, DDI_PROP_DONTPASS, "shared_splits", 265 XGE_HAL_DEFAULT_SHARED_SPLITS); 266 device_config->stats_refresh_time_sec = ddi_prop_get_int(DDI_DEV_T_ANY, 267 dev_info, DDI_PROP_DONTPASS, "stats_refresh_time", 268 XGE_HAL_DEFAULT_STATS_REFRESH_TIME); 269 device_config->device_poll_millis = ddi_prop_get_int(DDI_DEV_T_ANY, 270 dev_info, DDI_PROP_DONTPASS, "device_poll_millis", 271 XGE_HAL_DEFAULT_DEVICE_POLL_MILLIS); 272 device_config->pci_freq_mherz = ddi_prop_get_int(DDI_DEV_T_ANY, 273 dev_info, DDI_PROP_DONTPASS, "pci_freq_mherz", 274 XGE_HAL_DEFAULT_USE_HARDCODE); 275 276 /* 277 * Initialize ring properties 278 */ 279 device_config->ring.memblock_size = ddi_prop_get_int(DDI_DEV_T_ANY, 280 dev_info, DDI_PROP_DONTPASS, "ring_memblock_size", 281 XGE_HAL_DEFAULT_RING_MEMBLOCK_SIZE); 282 device_config->ring.strip_vlan_tag = XGE_HAL_RING_DONOT_STRIP_VLAN_TAG; 283 284 #if defined(__sparc) 285 device_config->ring.queue[XGELL_RING_MAIN_QID].no_snoop_bits = 1; 286 #endif 287 device_config->ring.queue[XGELL_RING_MAIN_QID].max = 288 ddi_prop_get_int(DDI_DEV_T_ANY, 289 dev_info, DDI_PROP_DONTPASS, "ring_main_max", 290 XGE_HAL_DEFAULT_USE_HARDCODE); 291 device_config->ring.queue[XGELL_RING_MAIN_QID].initial = 292 ddi_prop_get_int(DDI_DEV_T_ANY, 293 dev_info, DDI_PROP_DONTPASS, "ring_main_initial", 294 XGE_HAL_DEFAULT_USE_HARDCODE); 295 if (device_config->ring.queue[XGELL_RING_MAIN_QID].initial == 296 XGE_HAL_DEFAULT_USE_HARDCODE) { 297 if (device_config->mtu > XGE_HAL_DEFAULT_MTU) { 298 device_config->ring.queue[XGELL_RING_MAIN_QID].initial = 299 device_config->ring.queue[XGELL_RING_MAIN_QID].max = 300 XGE_HAL_DEFAULT_RING_QUEUE_BLOCKS_J; 301 } else { 302 device_config->ring.queue[XGELL_RING_MAIN_QID].initial = 303 device_config->ring.queue[XGELL_RING_MAIN_QID].max = 304 XGE_HAL_DEFAULT_RING_QUEUE_BLOCKS_N; 305 } 306 } 307 device_config->ring.queue[XGELL_RING_MAIN_QID].buffer_mode = 308 ddi_prop_get_int(DDI_DEV_T_ANY, 309 dev_info, DDI_PROP_DONTPASS, "ring_main_buffer_mode", 310 XGE_HAL_RING_QUEUE_BUFFER_MODE_DEFAULT); 311 device_config->ring.queue[XGELL_RING_MAIN_QID].dram_size_mb = 312 ddi_prop_get_int(DDI_DEV_T_ANY, 313 dev_info, DDI_PROP_DONTPASS, "ring_main_dram_size_mb", 314 XGE_HAL_DEFAULT_USE_HARDCODE); 315 device_config->ring.queue[XGELL_RING_MAIN_QID].backoff_interval_us = 316 ddi_prop_get_int(DDI_DEV_T_ANY, 317 dev_info, DDI_PROP_DONTPASS, "ring_main_backoff_interval_us", 318 XGE_HAL_DEFAULT_BACKOFF_INTERVAL_US); 319 device_config->ring.queue[XGELL_RING_MAIN_QID].max_frm_len = 320 ddi_prop_get_int(DDI_DEV_T_ANY, 321 dev_info, DDI_PROP_DONTPASS, "ring_main_max_frm_len", 322 XGE_HAL_RING_USE_MTU); 323 device_config->ring.queue[XGELL_RING_MAIN_QID].priority = 324 ddi_prop_get_int(DDI_DEV_T_ANY, 325 dev_info, DDI_PROP_DONTPASS, "ring_main_priority", 326 XGE_HAL_DEFAULT_RING_PRIORITY); 327 device_config->ring.queue[XGELL_RING_MAIN_QID].configured = 328 ddi_prop_get_int(DDI_DEV_T_ANY, 329 dev_info, DDI_PROP_DONTPASS, "ring_main_configured", 330 1); 331 device_config->ring.queue[XGELL_RING_MAIN_QID].rti.urange_a = 332 ddi_prop_get_int(DDI_DEV_T_ANY, 333 dev_info, DDI_PROP_DONTPASS, "ring_main_urange_a", 334 XGE_HAL_DEFAULT_RX_URANGE_A); 335 device_config->ring.queue[XGELL_RING_MAIN_QID].rti.ufc_a = 336 ddi_prop_get_int(DDI_DEV_T_ANY, 337 dev_info, DDI_PROP_DONTPASS, "ring_main_ufc_a", 338 XGE_HAL_DEFAULT_RX_UFC_A); 339 device_config->ring.queue[XGELL_RING_MAIN_QID].rti.urange_b = 340 ddi_prop_get_int(DDI_DEV_T_ANY, 341 dev_info, DDI_PROP_DONTPASS, "ring_main_urange_b", 342 XGE_HAL_DEFAULT_RX_URANGE_B); 343 device_config->ring.queue[XGELL_RING_MAIN_QID].rti.ufc_b = 344 ddi_prop_get_int(DDI_DEV_T_ANY, 345 dev_info, DDI_PROP_DONTPASS, "ring_main_ufc_b", 346 device_config->mtu > XGE_HAL_DEFAULT_MTU ? 347 XGE_HAL_DEFAULT_RX_UFC_B_J : 348 XGE_HAL_DEFAULT_RX_UFC_B_N); 349 device_config->ring.queue[XGELL_RING_MAIN_QID].rti.urange_c = 350 ddi_prop_get_int(DDI_DEV_T_ANY, 351 dev_info, DDI_PROP_DONTPASS, "ring_main_urange_c", 352 XGE_HAL_DEFAULT_RX_URANGE_C); 353 device_config->ring.queue[XGELL_RING_MAIN_QID].rti.ufc_c = 354 ddi_prop_get_int(DDI_DEV_T_ANY, 355 dev_info, DDI_PROP_DONTPASS, "ring_main_ufc_c", 356 device_config->mtu > XGE_HAL_DEFAULT_MTU ? 357 XGE_HAL_DEFAULT_RX_UFC_C_J : 358 XGE_HAL_DEFAULT_RX_UFC_C_N); 359 device_config->ring.queue[XGELL_RING_MAIN_QID].rti.ufc_d = 360 ddi_prop_get_int(DDI_DEV_T_ANY, 361 dev_info, DDI_PROP_DONTPASS, "ring_main_ufc_d", 362 XGE_HAL_DEFAULT_RX_UFC_D); 363 device_config->ring.queue[XGELL_RING_MAIN_QID].rti.timer_val_us = 364 ddi_prop_get_int(DDI_DEV_T_ANY, 365 dev_info, DDI_PROP_DONTPASS, "ring_main_timer_val", 366 XGE_HAL_DEFAULT_RX_TIMER_VAL); 367 device_config->ring.queue[XGELL_RING_MAIN_QID].rti.timer_ac_en = 368 ddi_prop_get_int(DDI_DEV_T_ANY, 369 dev_info, DDI_PROP_DONTPASS, "ring_main_timer_ac_en", 370 XGE_HAL_DEFAULT_RX_TIMER_AC_EN); 371 device_config->ring.queue[XGELL_RING_MAIN_QID].indicate_max_pkts = 372 ddi_prop_get_int(DDI_DEV_T_ANY, 373 dev_info, DDI_PROP_DONTPASS, "ring_main_indicate_max_pkts", 374 (device_config->bimodal_interrupts ? 375 XGE_HAL_DEFAULT_INDICATE_MAX_PKTS_B : 376 XGE_HAL_DEFAULT_INDICATE_MAX_PKTS_N)); 377 378 /* 379 * Initialize mac properties 380 */ 381 device_config->mac.tmac_util_period = ddi_prop_get_int(DDI_DEV_T_ANY, 382 dev_info, DDI_PROP_DONTPASS, "mac_tmac_util_period", 383 XGE_HAL_DEFAULT_TMAC_UTIL_PERIOD); 384 device_config->mac.rmac_util_period = ddi_prop_get_int(DDI_DEV_T_ANY, 385 dev_info, DDI_PROP_DONTPASS, "mac_rmac_util_period", 386 XGE_HAL_DEFAULT_RMAC_UTIL_PERIOD); 387 device_config->mac.rmac_bcast_en = ddi_prop_get_int(DDI_DEV_T_ANY, 388 dev_info, DDI_PROP_DONTPASS, "mac_rmac_bcast_en", 389 1); /* HAL never provide a good named macro */ 390 device_config->mac.rmac_pause_gen_en = ddi_prop_get_int(DDI_DEV_T_ANY, 391 dev_info, DDI_PROP_DONTPASS, "rmac_pause_gen_en", 392 XGE_HAL_DEFAULT_RMAC_PAUSE_GEN_DIS); 393 device_config->mac.rmac_pause_rcv_en = ddi_prop_get_int(DDI_DEV_T_ANY, 394 dev_info, DDI_PROP_DONTPASS, "rmac_pause_rcv_en", 395 XGE_HAL_DEFAULT_RMAC_PAUSE_RCV_DIS); 396 device_config->mac.rmac_pause_time = ddi_prop_get_int(DDI_DEV_T_ANY, 397 dev_info, DDI_PROP_DONTPASS, "mac_rmac_pause_time", 398 XGE_HAL_DEFAULT_RMAC_HIGH_PTIME); 399 device_config->mac.mc_pause_threshold_q0q3 = 400 ddi_prop_get_int(DDI_DEV_T_ANY, 401 dev_info, DDI_PROP_DONTPASS, "mac_mc_pause_threshold_q0q3", 402 XGE_HAL_DEFAULT_MC_PAUSE_THRESHOLD_Q0Q3); 403 device_config->mac.mc_pause_threshold_q4q7 = 404 ddi_prop_get_int(DDI_DEV_T_ANY, 405 dev_info, DDI_PROP_DONTPASS, "mac_mc_pause_threshold_q4q7", 406 XGE_HAL_DEFAULT_MC_PAUSE_THRESHOLD_Q4Q7); 407 408 /* 409 * Initialize fifo properties 410 */ 411 device_config->fifo.max_frags = ddi_prop_get_int(DDI_DEV_T_ANY, 412 dev_info, DDI_PROP_DONTPASS, "fifo_max_frags", 413 XGE_HAL_DEFAULT_FIFO_FRAGS); 414 if (device_config->fifo.max_frags == XGE_HAL_DEFAULT_USE_HARDCODE) 415 device_config->fifo.max_frags = XGE_HAL_DEFAULT_FIFO_FRAGS; 416 device_config->fifo.reserve_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, 417 dev_info, DDI_PROP_DONTPASS, "fifo_reserve_threshold", 418 XGE_HAL_DEFAULT_FIFO_RESERVE_THRESHOLD); 419 device_config->fifo.memblock_size = ddi_prop_get_int(DDI_DEV_T_ANY, 420 dev_info, DDI_PROP_DONTPASS, "fifo_memblock_size", 421 XGE_HAL_DEFAULT_FIFO_MEMBLOCK_SIZE); 422 #ifdef XGE_HAL_ALIGN_XMIT 423 device_config->fifo.alignment_size = ddi_prop_get_int(DDI_DEV_T_ANY, 424 dev_info, DDI_PROP_DONTPASS, "fifo_copied_frag_size", 425 XGE_HAL_DEFAULT_FIFO_ALIGNMENT_SIZE); 426 device_config->fifo.max_aligned_frags = ddi_prop_get_int(DDI_DEV_T_ANY, 427 dev_info, DDI_PROP_DONTPASS, "fifo_copied_max_frags", 428 XGE_HAL_DEFAULT_FIFO_MAX_ALIGNED_FRAGS); 429 #endif 430 #if defined(__sparc) 431 device_config->fifo.queue[0].no_snoop_bits = 1; 432 #endif 433 device_config->fifo.queue[0].max = ddi_prop_get_int(DDI_DEV_T_ANY, 434 dev_info, DDI_PROP_DONTPASS, "fifo0_max", 435 XGE_HAL_DEFAULT_USE_HARDCODE); 436 device_config->fifo.queue[0].initial = ddi_prop_get_int(DDI_DEV_T_ANY, 437 dev_info, DDI_PROP_DONTPASS, "fifo0_initial", 438 XGE_HAL_DEFAULT_USE_HARDCODE); 439 if (device_config->fifo.queue[0].initial == 440 XGE_HAL_DEFAULT_USE_HARDCODE) { 441 if (device_config->mtu > XGE_HAL_DEFAULT_MTU) { 442 device_config->fifo.queue[0].initial = 443 device_config->fifo.queue[0].max = 444 XGE_HAL_DEFAULT_FIFO_QUEUE_LENGTH_J; 445 } else { 446 device_config->fifo.queue[0].initial = 447 device_config->fifo.queue[0].max = 448 XGE_HAL_DEFAULT_FIFO_QUEUE_LENGTH_N; 449 } 450 } 451 device_config->fifo.queue[0].intr = ddi_prop_get_int(DDI_DEV_T_ANY, 452 dev_info, DDI_PROP_DONTPASS, "fifo0_intr", 453 XGE_HAL_DEFAULT_FIFO_QUEUE_INTR); 454 device_config->fifo.queue[0].configured = 455 ddi_prop_get_int(DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, 456 "fifo0_configured", 1); 457 458 /* 459 * Bimodal Interrupts - TTI 56 configuration 460 */ 461 device_config->bimodal_interrupts = ddi_prop_get_int( 462 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, "bimodal_interrupts", 463 XGE_HAL_DEFAULT_BIMODAL_INTERRUPTS); 464 device_config->bimodal_timer_lo_us = ddi_prop_get_int( 465 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, "bimodal_timer_lo_us", 466 XGE_HAL_DEFAULT_BIMODAL_TIMER_LO_US); 467 device_config->bimodal_timer_hi_us = ddi_prop_get_int( 468 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, "bimodal_timer_hi_us", 469 XGE_HAL_DEFAULT_BIMODAL_TIMER_HI_US); 470 471 /* 472 * TTI 0 configuration 473 */ 474 device_config->fifo.queue[0].tti[0].enabled = ddi_prop_get_int( 475 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, "tti_enable", 1); 476 device_config->fifo.queue[0].tti[0].urange_a = ddi_prop_get_int( 477 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, "tti_urange_a", 478 XGE_HAL_DEFAULT_TX_URANGE_A); 479 device_config->fifo.queue[0].tti[0].ufc_a = ddi_prop_get_int( 480 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, "tti_ufc_a", 481 XGE_HAL_DEFAULT_TX_UFC_A); 482 device_config->fifo.queue[0].tti[0].urange_b = ddi_prop_get_int( 483 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, "tti_urange_b", 484 XGE_HAL_DEFAULT_TX_URANGE_B); 485 device_config->fifo.queue[0].tti[0].ufc_b = ddi_prop_get_int( 486 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, "tti_ufc_b", 487 XGE_HAL_DEFAULT_TX_UFC_B); 488 device_config->fifo.queue[0].tti[0].urange_c = ddi_prop_get_int( 489 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, "tti_urange_c", 490 XGE_HAL_DEFAULT_TX_URANGE_C); 491 device_config->fifo.queue[0].tti[0].ufc_c = ddi_prop_get_int( 492 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, "tti_ufc_c", 493 XGE_HAL_DEFAULT_TX_UFC_C); 494 device_config->fifo.queue[0].tti[0].ufc_d = ddi_prop_get_int( 495 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, "tti_ufc_d", 496 XGE_HAL_DEFAULT_TX_UFC_D); 497 device_config->fifo.queue[0].tti[0].timer_ac_en = ddi_prop_get_int( 498 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, "tti_timer_ac_en", 499 XGE_HAL_DEFAULT_TX_TIMER_AC_EN); 500 device_config->fifo.queue[0].tti[0].timer_val_us = ddi_prop_get_int( 501 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, "tti_timer_val", 502 XGE_HAL_DEFAULT_TX_TIMER_VAL); 503 device_config->fifo.queue[0].tti[0].timer_ci_en = ddi_prop_get_int( 504 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, "tti_timer_ci_en", 505 XGE_HAL_DEFAULT_TX_TIMER_CI_EN); 506 507 /* 508 * Initialize errors dumping 509 */ 510 device_config->dump_on_serr = ddi_prop_get_int(DDI_DEV_T_ANY, 511 dev_info, DDI_PROP_DONTPASS, "dump_on_serr", 512 0); 513 device_config->dump_on_serr = ddi_prop_get_int(DDI_DEV_T_ANY, 514 dev_info, DDI_PROP_DONTPASS, "dump_on_eccerr", 515 0); 516 device_config->dump_on_serr = ddi_prop_get_int(DDI_DEV_T_ANY, 517 dev_info, DDI_PROP_DONTPASS, "dump_on_parityerr", 518 0); 519 520 /* 521 * LRO tunables 522 */ 523 device_config->lro_sg_size = ddi_prop_get_int(DDI_DEV_T_ANY, 524 dev_info, DDI_PROP_DONTPASS, "lro_sg_size", 525 XGE_HAL_DEFAULT_LRO_SG_SIZE); 526 device_config->lro_frm_len = ddi_prop_get_int(DDI_DEV_T_ANY, 527 dev_info, DDI_PROP_DONTPASS, "lro_frm_len", 528 XGE_HAL_DEFAULT_LRO_FRM_LEN); 529 530 /* 531 * Initialize link layer configuration 532 */ 533 ll_config->rx_buffer_total = ddi_prop_get_int(DDI_DEV_T_ANY, 534 dev_info, DDI_PROP_DONTPASS, "rx_buffer_total", 535 device_config->ring.queue[XGELL_RING_MAIN_QID].initial * 536 XGELL_RX_BUFFER_TOTAL); 537 ll_config->rx_buffer_post_hiwat = ddi_prop_get_int(DDI_DEV_T_ANY, 538 dev_info, DDI_PROP_DONTPASS, "rx_buffer_post_hiwat", 539 device_config->ring.queue[XGELL_RING_MAIN_QID].initial * 540 XGELL_RX_BUFFER_POST_HIWAT); 541 ll_config->rx_pkt_burst = ddi_prop_get_int(DDI_DEV_T_ANY, 542 dev_info, DDI_PROP_DONTPASS, "rx_pkt_burst", 543 XGELL_RX_PKT_BURST); 544 ll_config->rx_dma_lowat = ddi_prop_get_int(DDI_DEV_T_ANY, dev_info, 545 DDI_PROP_DONTPASS, "rx_dma_lowat", XGELL_RX_DMA_LOWAT); 546 ll_config->tx_dma_lowat = ddi_prop_get_int(DDI_DEV_T_ANY, dev_info, 547 DDI_PROP_DONTPASS, "tx_dma_lowat", XGELL_TX_DMA_LOWAT); 548 ll_config->msi_enable = ddi_prop_get_int(DDI_DEV_T_ANY, dev_info, 549 DDI_PROP_DONTPASS, "msi_enable", XGELL_CONF_ENABLE_BY_DEFAULT); 550 ll_config->lso_enable = ddi_prop_get_int(DDI_DEV_T_ANY, dev_info, 551 DDI_PROP_DONTPASS, "lso_enable", XGELL_CONF_ENABLE_BY_DEFAULT); 552 } 553 554 /* 555 * xge_attach 556 * @dev_info: pointer to dev_info_t structure 557 * @cmd: attach command to process 558 * 559 * This is a solaris standard attach function. This 560 * function initializes the Xframe identified 561 * by the dev_info_t structure and setup the driver 562 * data structures corresponding to the Xframe Card. 563 * This function also registers the XFRAME device 564 * instance with the MAC Layer. 565 * If this function returns success then the OS 566 * will attach the HBA controller to this 567 * driver. 568 */ 569 static int 570 xge_attach(dev_info_t *dev_info, ddi_attach_cmd_t cmd) 571 { 572 xgelldev_t *ll; 573 xge_hal_device_config_t device_config; 574 xge_hal_device_t *hldev; 575 xge_hal_device_attr_t attr; 576 xge_hal_status_e status; 577 xgell_config_t ll_config; 578 int ret; 579 580 xge_debug_osdep(XGE_TRACE, "XGE_ATTACH cmd %d", cmd); 581 582 switch (cmd) { 583 case DDI_ATTACH: 584 break; 585 586 case DDI_RESUME: 587 case DDI_PM_RESUME: 588 xge_debug_osdep(XGE_ERR, "%s", "resume unsupported yet"); 589 ret = DDI_FAILURE; 590 goto _exit0; 591 592 default: 593 xge_debug_osdep(XGE_ERR, "cmd 0x%x unrecognized", cmd); 594 ret = DDI_FAILURE; 595 goto _exit0; 596 } 597 598 xge_os_memzero(&device_config, sizeof (xge_hal_device_config_t)); 599 600 /* Init device_config by lookup up properties from .conf file */ 601 xge_configuration_init(dev_info, &device_config, &ll_config); 602 603 /* map BAR0 */ 604 ret = ddi_regs_map_setup(dev_info, 1, (caddr_t *)&attr.bar0, 605 (offset_t)0, (offset_t)0, &xge_dev_attr, &attr.regh0); 606 if (ret != DDI_SUCCESS) { 607 xge_debug_osdep(XGE_ERR, "unable to map bar0: [%d]", ret); 608 goto _exit0; 609 } 610 611 /* map BAR1 */ 612 ret = ddi_regs_map_setup(dev_info, 2, (caddr_t *)&attr.bar1, 613 (offset_t)0, (offset_t)0, &xge_dev_attr, &attr.regh1); 614 if (ret != DDI_SUCCESS) { 615 xge_debug_osdep(XGE_ERR, "unable to map bar1: [%d]", ret); 616 goto _exit1; 617 } 618 619 /* preallocate memory for new HAL device and private LL part */ 620 hldev = kmem_zalloc(sizeof (xge_hal_device_t), KM_SLEEP); 621 if (hldev == NULL) { 622 xge_debug_osdep(XGE_ERR, "%s", "can not allocate memory"); 623 ret = DDI_ENOMEM; 624 goto _exit2; 625 } 626 627 /* get the interrupt block cookie associated with the interrupt */ 628 ret = ddi_get_iblock_cookie(dev_info, 0, &attr.irqh); 629 if (ret != DDI_SUCCESS) { 630 xge_debug_osdep(XGE_ERR, "%s", "can not get interrupt cookie"); 631 goto _exit2a; 632 } 633 634 /* Get the PCI Configuartion space handle */ 635 ret = pci_config_setup(dev_info, &attr.cfgh); 636 if (ret != DDI_SUCCESS) { 637 xge_debug_osdep(XGE_ERR, "%s", "can not setup config space"); 638 goto _exit2a; 639 } 640 641 attr.pdev = dev_info; 642 643 ret = xgell_device_alloc(hldev, dev_info, &ll); 644 if (ret != DDI_SUCCESS) { 645 xge_debug_osdep(XGE_ERR, 646 "%s", 647 "unable to allocate new LL device"); 648 goto _exit3; 649 } 650 651 /* attach an interrupt handler for handling Xge device interrupts */ 652 ret = ddi_add_intr(dev_info, 0, &attr.irqh, NULL, xge_isr, 653 (caddr_t)hldev); 654 if (ret != DDI_SUCCESS) { 655 xge_debug_osdep(XGE_ERR, "%s", "unable to register ISR"); 656 goto _exit3a; 657 } 658 659 /* initialize HW */ 660 status = xge_hal_device_initialize(hldev, &attr, &device_config); 661 if (status != XGE_HAL_OK) { 662 switch (status) { 663 case XGE_HAL_ERR_DRIVER_NOT_INITIALIZED: 664 xge_debug_osdep(XGE_ERR, "%s", 665 "driver is not initialized"); 666 ret = DDI_FAILURE; 667 goto _exit3b; 668 case XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT: 669 xge_debug_osdep(XGE_ERR, "%s", 670 "device is not quiescent"); 671 ret = DDI_EBUSY; 672 goto _exit3b; 673 case XGE_HAL_ERR_OUT_OF_MEMORY: 674 xge_debug_osdep(XGE_ERR, "%s", 675 "unable to allocate memory"); 676 ret = DDI_ENOMEM; 677 goto _exit3b; 678 default: 679 xge_debug_osdep(XGE_ERR, 680 "can't initialize the device: %d", status); 681 ret = DDI_FAILURE; 682 goto _exit3b; 683 } 684 } 685 686 /* allocate and register Link Layer */ 687 ret = xgell_device_register(ll, &ll_config); 688 if (ret != DDI_SUCCESS) { 689 goto _exit4; 690 } 691 692 /* store ll as a HAL private part */ 693 xge_hal_device_private_set(hldev, ll); 694 695 return (DDI_SUCCESS); 696 697 _exit4: 698 xge_hal_device_terminate(hldev); 699 _exit3b: 700 ddi_remove_intr(attr.pdev, 0, hldev->irqh); 701 _exit3a: 702 xgell_device_free(ll); 703 _exit3: 704 pci_config_teardown(&attr.cfgh); 705 _exit2a: 706 kmem_free(hldev, sizeof (xge_hal_device_t)); 707 _exit2: 708 ddi_regs_map_free(&attr.regh1); 709 _exit1: 710 ddi_regs_map_free(&attr.regh0); 711 _exit0: 712 return (ret); 713 } 714 715 /* 716 * xge_detach 717 * @dev_info: pointer to dev_info_t structure 718 * @cmd: attach command to process 719 * 720 * This function is called by OS when the system is about 721 * to shutdown or when the super user tries to unload 722 * the driver. This function frees all the memory allocated 723 * during xge_attch() and also unregisters the Xframe 724 * device instance from the GLD framework. 725 */ 726 static int 727 xge_detach(dev_info_t *dev_info, ddi_detach_cmd_t cmd) 728 { 729 xge_hal_device_t *hldev; 730 xge_hal_device_attr_t *attr; 731 xgelldev_t *lldev; 732 733 xge_debug_osdep(XGE_TRACE, "XGE_DETACH cmd %d", cmd); 734 735 hldev = (xge_hal_device_t *)ddi_get_driver_private(dev_info); 736 attr = xge_hal_device_attr(hldev); 737 lldev = xge_hal_device_private(hldev); 738 739 switch (cmd) { 740 case DDI_DETACH: 741 break; 742 743 case DDI_PM_SUSPEND: 744 xge_debug_osdep(XGE_ERR, "%s", "suspend unsupported yet"); 745 return (DDI_FAILURE); 746 747 default: 748 xge_debug_osdep(XGE_ERR, "cmd 0x%x unrecognized", cmd); 749 return (DDI_FAILURE); 750 } 751 752 if (lldev->is_initialized) { 753 xge_debug_osdep(XGE_ERR, "%s", 754 "can not detach: device is not unplumbed"); 755 return (DDI_FAILURE); 756 } 757 758 xge_hal_device_terminating(hldev); 759 if (xgell_device_unregister(lldev) != DDI_SUCCESS) { 760 return (DDI_FAILURE); 761 } 762 xge_hal_device_terminate(hldev); 763 764 ddi_remove_intr(attr->pdev, 0, attr->irqh); 765 xgell_device_free(lldev); 766 pci_config_teardown(&attr->cfgh); 767 ddi_regs_map_free(&attr->regh1); 768 ddi_regs_map_free(&attr->regh0); 769 kmem_free(hldev, sizeof (xge_hal_device_t)); 770 771 return (DDI_SUCCESS); 772 } 773