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 (__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 249 /* 250 * We prefer HAL could provide all default values to these tunables, 251 * so this level could care little the configurations need by HAL. 252 * Leave a const here is definitely not good idea. 253 */ 254 device_config->mtu = ddi_prop_get_int(DDI_DEV_T_ANY, 255 dev_info, DDI_PROP_DONTPASS, "default_mtu", 256 XGE_HAL_DEFAULT_INITIAL_MTU); 257 device_config->isr_polling_cnt = ddi_prop_get_int(DDI_DEV_T_ANY, 258 dev_info, DDI_PROP_DONTPASS, "isr_polling_cnt", 259 XGE_HAL_DEFAULT_ISR_POLLING_CNT); 260 device_config->latency_timer = ddi_prop_get_int(DDI_DEV_T_ANY, 261 dev_info, DDI_PROP_DONTPASS, "latency_timer", 262 XGE_HAL_DEFAULT_LATENCY_TIMER); 263 device_config->max_splits_trans = ddi_prop_get_int(DDI_DEV_T_ANY, 264 dev_info, DDI_PROP_DONTPASS, "max_splits_trans", 265 XGE_HAL_DEFAULT_SPLIT_TRANSACTION); 266 device_config->mmrb_count = ddi_prop_get_int(DDI_DEV_T_ANY, 267 dev_info, DDI_PROP_DONTPASS, "mmrb_count", 268 XGE_HAL_DEFAULT_MMRB_COUNT); 269 device_config->shared_splits = ddi_prop_get_int(DDI_DEV_T_ANY, 270 dev_info, DDI_PROP_DONTPASS, "shared_splits", 271 XGE_HAL_DEFAULT_SHARED_SPLITS); 272 device_config->stats_refresh_time_sec = ddi_prop_get_int(DDI_DEV_T_ANY, 273 dev_info, DDI_PROP_DONTPASS, "stats_refresh_time", 274 XGE_HAL_DEFAULT_STATS_REFRESH_TIME); 275 device_config->device_poll_millis = ddi_prop_get_int(DDI_DEV_T_ANY, 276 dev_info, DDI_PROP_DONTPASS, "device_poll_millis", 277 XGE_HAL_DEFAULT_DEVICE_POLL_MILLIS); 278 /* 279 * Query PCI bus freqency from parent nexus driver. 280 * Note this property is only provided on SPARC platforms. 281 */ 282 device_config->pci_freq_mherz = ddi_prop_get_int(DDI_DEV_T_ANY, 283 dev_info, 0, "clock-frequency", 284 XGE_HAL_PCI_FREQ_MHERZ_DEFAULT * 1000000) / 1000000; 285 286 /* 287 * Initialize ring properties 288 */ 289 device_config->ring.memblock_size = ddi_prop_get_int(DDI_DEV_T_ANY, 290 dev_info, DDI_PROP_DONTPASS, "ring_memblock_size", 291 XGE_HAL_DEFAULT_RING_MEMBLOCK_SIZE); 292 device_config->ring.strip_vlan_tag = XGE_HAL_RING_DONOT_STRIP_VLAN_TAG; 293 294 #if defined(__sparc) 295 device_config->ring.queue[XGELL_RING_MAIN_QID].no_snoop_bits = 1; 296 #endif 297 device_config->ring.queue[XGELL_RING_MAIN_QID].max = 298 ddi_prop_get_int(DDI_DEV_T_ANY, 299 dev_info, DDI_PROP_DONTPASS, "ring_main_max", 300 XGE_HAL_DEFAULT_USE_HARDCODE); 301 device_config->ring.queue[XGELL_RING_MAIN_QID].initial = 302 ddi_prop_get_int(DDI_DEV_T_ANY, 303 dev_info, DDI_PROP_DONTPASS, "ring_main_initial", 304 XGE_HAL_DEFAULT_USE_HARDCODE); 305 if (device_config->ring.queue[XGELL_RING_MAIN_QID].initial == 306 XGE_HAL_DEFAULT_USE_HARDCODE) { 307 if (device_config->mtu > XGE_HAL_DEFAULT_MTU) { 308 device_config->ring.queue[XGELL_RING_MAIN_QID].initial = 309 device_config->ring.queue[XGELL_RING_MAIN_QID].max = 310 XGE_HAL_DEFAULT_RING_QUEUE_BLOCKS_J; 311 } else { 312 device_config->ring.queue[XGELL_RING_MAIN_QID].initial = 313 device_config->ring.queue[XGELL_RING_MAIN_QID].max = 314 XGE_HAL_DEFAULT_RING_QUEUE_BLOCKS_N; 315 } 316 } 317 device_config->ring.queue[XGELL_RING_MAIN_QID].buffer_mode = 318 ddi_prop_get_int(DDI_DEV_T_ANY, 319 dev_info, DDI_PROP_DONTPASS, "ring_main_buffer_mode", 320 XGE_HAL_RING_QUEUE_BUFFER_MODE_DEFAULT); 321 device_config->ring.queue[XGELL_RING_MAIN_QID].dram_size_mb = 322 ddi_prop_get_int(DDI_DEV_T_ANY, 323 dev_info, DDI_PROP_DONTPASS, "ring_main_dram_size_mb", 324 XGE_HAL_DEFAULT_USE_HARDCODE); 325 device_config->ring.queue[XGELL_RING_MAIN_QID].backoff_interval_us = 326 ddi_prop_get_int(DDI_DEV_T_ANY, 327 dev_info, DDI_PROP_DONTPASS, "ring_main_backoff_interval_us", 328 XGE_HAL_DEFAULT_BACKOFF_INTERVAL_US); 329 device_config->ring.queue[XGELL_RING_MAIN_QID].max_frm_len = 330 ddi_prop_get_int(DDI_DEV_T_ANY, 331 dev_info, DDI_PROP_DONTPASS, "ring_main_max_frm_len", 332 XGE_HAL_RING_USE_MTU); 333 device_config->ring.queue[XGELL_RING_MAIN_QID].priority = 334 ddi_prop_get_int(DDI_DEV_T_ANY, 335 dev_info, DDI_PROP_DONTPASS, "ring_main_priority", 336 XGE_HAL_DEFAULT_RING_PRIORITY); 337 device_config->ring.queue[XGELL_RING_MAIN_QID].configured = 338 ddi_prop_get_int(DDI_DEV_T_ANY, 339 dev_info, DDI_PROP_DONTPASS, "ring_main_configured", 340 1); /* HAL never provide a good named macro */ 341 device_config->ring.queue[XGELL_RING_MAIN_QID].rti.urange_a = 342 ddi_prop_get_int(DDI_DEV_T_ANY, 343 dev_info, DDI_PROP_DONTPASS, "ring_main_urange_a", 344 XGE_HAL_DEFAULT_RX_URANGE_A); 345 device_config->ring.queue[XGELL_RING_MAIN_QID].rti.ufc_a = 346 ddi_prop_get_int(DDI_DEV_T_ANY, 347 dev_info, DDI_PROP_DONTPASS, "ring_main_ufc_a", 348 XGE_HAL_DEFAULT_RX_UFC_A); 349 device_config->ring.queue[XGELL_RING_MAIN_QID].rti.urange_b = 350 ddi_prop_get_int(DDI_DEV_T_ANY, 351 dev_info, DDI_PROP_DONTPASS, "ring_main_urange_b", 352 XGE_HAL_DEFAULT_RX_URANGE_B); 353 device_config->ring.queue[XGELL_RING_MAIN_QID].rti.ufc_b = 354 ddi_prop_get_int(DDI_DEV_T_ANY, 355 dev_info, DDI_PROP_DONTPASS, "ring_main_ufc_b", 356 XGE_HAL_DEFAULT_RX_UFC_B); 357 device_config->ring.queue[XGELL_RING_MAIN_QID].rti.urange_c = 358 ddi_prop_get_int(DDI_DEV_T_ANY, 359 dev_info, DDI_PROP_DONTPASS, "ring_main_urange_c", 360 XGE_HAL_DEFAULT_RX_URANGE_C); 361 device_config->ring.queue[XGELL_RING_MAIN_QID].rti.ufc_c = 362 ddi_prop_get_int(DDI_DEV_T_ANY, 363 dev_info, DDI_PROP_DONTPASS, "ring_main_ufc_c", 364 XGE_HAL_DEFAULT_RX_UFC_C); 365 device_config->ring.queue[XGELL_RING_MAIN_QID].rti.ufc_d = 366 ddi_prop_get_int(DDI_DEV_T_ANY, 367 dev_info, DDI_PROP_DONTPASS, "ring_main_ufc_d", 368 XGE_HAL_DEFAULT_RX_UFC_D); 369 device_config->ring.queue[XGELL_RING_MAIN_QID].rti.timer_val_us = 370 ddi_prop_get_int(DDI_DEV_T_ANY, 371 dev_info, DDI_PROP_DONTPASS, "ring_main_timer_val", 372 XGE_HAL_DEFAULT_RX_TIMER_VAL); 373 device_config->ring.queue[XGELL_RING_MAIN_QID].rti.timer_ac_en = 374 ddi_prop_get_int(DDI_DEV_T_ANY, 375 dev_info, DDI_PROP_DONTPASS, "ring_main_timer_ac_en", 376 XGE_HAL_DEFAULT_RX_TIMER_AC_EN); 377 device_config->ring.queue[XGELL_RING_MAIN_QID].indicate_max_pkts = 378 ddi_prop_get_int(DDI_DEV_T_ANY, 379 dev_info, DDI_PROP_DONTPASS, "ring_main_indicate_max_pkts", 380 XGE_HAL_DEFAULT_INDICATE_MAX_PKTS); 381 382 /* adaptive rx coalesing */ 383 device_config->sched_timer_us = ddi_prop_get_int(DDI_DEV_T_ANY, 384 dev_info, DDI_PROP_DONTPASS, "ring_main_ufc_a_timer", 385 0); 386 device_config->rxufca_intr_thres = ddi_prop_get_int(DDI_DEV_T_ANY, 387 dev_info, DDI_PROP_DONTPASS, "rxufca_intr_thres", 388 35); 389 device_config->rxufca_lo_lim = ddi_prop_get_int(DDI_DEV_T_ANY, 390 dev_info, DDI_PROP_DONTPASS, "rxufca_lo_lim", 391 1); 392 device_config->rxufca_hi_lim = ddi_prop_get_int(DDI_DEV_T_ANY, 393 dev_info, DDI_PROP_DONTPASS, "rxufca_hi_lim", 394 16); 395 device_config->rxufca_lbolt_period = ddi_prop_get_int(DDI_DEV_T_ANY, 396 dev_info, DDI_PROP_DONTPASS, "rxufca_lbolt_period", 397 1); 398 399 /* 400 * Initialize mac properties 401 */ 402 device_config->mac.tmac_util_period = ddi_prop_get_int(DDI_DEV_T_ANY, 403 dev_info, DDI_PROP_DONTPASS, "mac_tmac_util_period", 404 XGE_HAL_DEFAULT_TMAC_UTIL_PERIOD); 405 device_config->mac.rmac_util_period = ddi_prop_get_int(DDI_DEV_T_ANY, 406 dev_info, DDI_PROP_DONTPASS, "mac_rmac_util_period", 407 XGE_HAL_DEFAULT_RMAC_UTIL_PERIOD); 408 device_config->mac.rmac_bcast_en = ddi_prop_get_int(DDI_DEV_T_ANY, 409 dev_info, DDI_PROP_DONTPASS, "mac_rmac_bcast_en", 410 1); /* HAL never provide a good named macro */ 411 device_config->mac.rmac_pause_time = ddi_prop_get_int(DDI_DEV_T_ANY, 412 dev_info, DDI_PROP_DONTPASS, "mac_rmac_pause_time", 413 XGE_HAL_DEFAULT_RMAC_HIGH_PTIME); 414 device_config->mac.mc_pause_threshold_q0q3 = 415 ddi_prop_get_int(DDI_DEV_T_ANY, 416 dev_info, DDI_PROP_DONTPASS, "mac_mc_pause_threshold_q0q3", 417 XGE_HAL_DEFAULT_MC_PAUSE_THRESHOLD_Q0Q3); 418 device_config->mac.mc_pause_threshold_q4q7 = 419 ddi_prop_get_int(DDI_DEV_T_ANY, 420 dev_info, DDI_PROP_DONTPASS, "mac_mc_pause_threshold_q4q7", 421 XGE_HAL_DEFAULT_MC_PAUSE_THRESHOLD_Q4Q7); 422 423 /* 424 * Initialize fifo properties 425 */ 426 device_config->fifo.max_frags = ddi_prop_get_int(DDI_DEV_T_ANY, 427 dev_info, DDI_PROP_DONTPASS, "fifo_max_frags", 428 XGE_HAL_DEFAULT_FIFO_FRAGS); 429 if (device_config->fifo.max_frags == XGE_HAL_DEFAULT_USE_HARDCODE) 430 device_config->fifo.max_frags = XGE_HAL_DEFAULT_FIFO_FRAGS; 431 device_config->fifo.reserve_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, 432 dev_info, DDI_PROP_DONTPASS, "fifo_reserve_threshold", 433 XGE_HAL_DEFAULT_FIFO_RESERVE_THRESHOLD); 434 device_config->fifo.memblock_size = ddi_prop_get_int(DDI_DEV_T_ANY, 435 dev_info, DDI_PROP_DONTPASS, "fifo_memblock_size", 436 XGE_HAL_DEFAULT_FIFO_MEMBLOCK_SIZE); 437 #ifdef XGE_HAL_ALIGN_XMIT 438 device_config->fifo.alignment_size = 439 XGE_HAL_DEFAULT_FIFO_ALIGNMENT_SIZE; 440 device_config->fifo.max_aligned_frags = 441 XGE_HAL_DEFAULT_FIFO_MAX_ALIGNED_FRAGS; 442 #endif 443 #if defined(__sparc) 444 device_config->fifo.queue[0].no_snoop_bits = 1; 445 #endif 446 device_config->fifo.queue[0].max = ddi_prop_get_int(DDI_DEV_T_ANY, 447 dev_info, DDI_PROP_DONTPASS, "fifo0_max", 448 XGE_HAL_DEFAULT_USE_HARDCODE); 449 device_config->fifo.queue[0].initial = ddi_prop_get_int(DDI_DEV_T_ANY, 450 dev_info, DDI_PROP_DONTPASS, "fifo0_initial", 451 XGE_HAL_DEFAULT_USE_HARDCODE); 452 if (device_config->fifo.queue[0].initial == 453 XGE_HAL_DEFAULT_USE_HARDCODE) { 454 if (device_config->mtu > XGE_HAL_DEFAULT_MTU) { 455 device_config->fifo.queue[0].initial = 456 device_config->fifo.queue[0].max = 457 XGE_HAL_DEFAULT_FIFO_QUEUE_LENGTH_J; 458 } else { 459 device_config->fifo.queue[0].initial = 460 device_config->fifo.queue[0].max = 461 XGE_HAL_DEFAULT_FIFO_QUEUE_LENGTH_N; 462 } 463 } 464 device_config->fifo.queue[0].intr = ddi_prop_get_int(DDI_DEV_T_ANY, 465 dev_info, DDI_PROP_DONTPASS, "fifo0_intr", 466 XGE_HAL_DEFAULT_FIFO_QUEUE_INTR); 467 device_config->fifo.queue[0].configured = 468 ddi_prop_get_int(DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, 469 "fifo0_configured", 1); 470 471 /* 472 * Initialize tti properties 473 */ 474 device_config->tti.enabled = ddi_prop_get_int(DDI_DEV_T_ANY, 475 dev_info, DDI_PROP_DONTPASS, "tti_enabled", 476 XGE_HAL_TTI_ENABLE); 477 device_config->tti.urange_a = ddi_prop_get_int(DDI_DEV_T_ANY, 478 dev_info, DDI_PROP_DONTPASS, "tti_urange_a", 479 XGE_HAL_DEFAULT_TX_URANGE_A); 480 device_config->tti.ufc_a = ddi_prop_get_int(DDI_DEV_T_ANY, 481 dev_info, DDI_PROP_DONTPASS, "tti_ufc_a", 482 XGE_HAL_DEFAULT_TX_UFC_A); 483 device_config->tti.urange_b = ddi_prop_get_int(DDI_DEV_T_ANY, 484 dev_info, DDI_PROP_DONTPASS, "tti_urange_b", 485 XGE_HAL_DEFAULT_TX_URANGE_B); 486 device_config->tti.ufc_b = ddi_prop_get_int(DDI_DEV_T_ANY, 487 dev_info, DDI_PROP_DONTPASS, "tti_ufc_b", 488 XGE_HAL_DEFAULT_TX_UFC_B); 489 device_config->tti.urange_c = ddi_prop_get_int(DDI_DEV_T_ANY, 490 dev_info, DDI_PROP_DONTPASS, "tti_urange_c", 491 XGE_HAL_DEFAULT_TX_URANGE_C); 492 device_config->tti.ufc_c = ddi_prop_get_int(DDI_DEV_T_ANY, 493 dev_info, DDI_PROP_DONTPASS, "tti_ufc_c", 494 XGE_HAL_DEFAULT_TX_UFC_C); 495 device_config->tti.ufc_d = ddi_prop_get_int(DDI_DEV_T_ANY, 496 dev_info, DDI_PROP_DONTPASS, "tti_ufc_d", 497 XGE_HAL_DEFAULT_TX_UFC_D); 498 device_config->tti.timer_val_us = ddi_prop_get_int(DDI_DEV_T_ANY, 499 dev_info, DDI_PROP_DONTPASS, "tti_timer_ac_en", 500 XGE_HAL_DEFAULT_TX_TIMER_AC_EN); 501 device_config->tti.timer_val_us = ddi_prop_get_int(DDI_DEV_T_ANY, 502 dev_info, DDI_PROP_DONTPASS, "tti_timer_val", 503 XGE_HAL_DEFAULT_TX_TIMER_VAL); 504 device_config->tti.timer_ci_en = ddi_prop_get_int(DDI_DEV_T_ANY, 505 dev_info, DDI_PROP_DONTPASS, "tti_timer_ci_en", 506 XGE_HAL_DEFAULT_TX_TIMER_CI_EN); 507 508 /* 509 * Initialize errors dumping 510 */ 511 device_config->dump_on_serr = ddi_prop_get_int(DDI_DEV_T_ANY, 512 dev_info, DDI_PROP_DONTPASS, "dump_on_serr", 513 0); 514 device_config->dump_on_serr = ddi_prop_get_int(DDI_DEV_T_ANY, 515 dev_info, DDI_PROP_DONTPASS, "dump_on_eccerr", 516 0); 517 device_config->dump_on_serr = ddi_prop_get_int(DDI_DEV_T_ANY, 518 dev_info, DDI_PROP_DONTPASS, "dump_on_parityerr", 519 0); 520 521 /* 522 * Initialize link layer configuration 523 */ 524 ll_config->rx_buffer_total = ddi_prop_get_int(DDI_DEV_T_ANY, 525 dev_info, DDI_PROP_DONTPASS, "rx_buffer_total", 526 XGELL_RX_BUFFER_TOTAL); 527 ll_config->rx_buffer_post_hiwat = ddi_prop_get_int(DDI_DEV_T_ANY, 528 dev_info, DDI_PROP_DONTPASS, "rx_buffer_post_hiwat", 529 XGELL_RX_BUFFER_POST_HIWAT); 530 ll_config->rx_buffer_recycle_hiwat = ddi_prop_get_int(DDI_DEV_T_ANY, 531 dev_info, DDI_PROP_DONTPASS, "rx_buffer_recycle_hiwat", 532 XGELL_RX_BUFFER_RECYCLE_HIWAT); 533 } 534 535 /* 536 * xge_attach 537 * @dev_info: pointer to dev_info_t structure 538 * @cmd: attach command to process 539 * 540 * This is a solaris standard attach function. This 541 * function initializes the Xframe identified 542 * by the dev_info_t structure and setup the driver 543 * data structures corresponding to the Xframe Card. 544 * This function also registers the XFRAME device 545 * instance with the MAC Layer. 546 * If this function returns success then the OS 547 * will attach the HBA controller to this 548 * driver. 549 */ 550 static int 551 xge_attach(dev_info_t *dev_info, ddi_attach_cmd_t cmd) 552 { 553 xgelldev_t *ll; 554 xge_hal_device_config_t device_config; 555 xge_hal_device_t *hldev; 556 xge_hal_device_attr_t attr; 557 xge_hal_status_e status; 558 xgell_config_t ll_config; 559 int ret; 560 561 xge_debug_osdep(XGE_TRACE, "XGE_ATTACH cmd %d", cmd); 562 563 switch (cmd) { 564 case DDI_ATTACH: 565 break; 566 567 case DDI_RESUME: 568 case DDI_PM_RESUME: 569 xge_debug_osdep(XGE_ERR, "%s", "resume unsupported yet"); 570 ret = DDI_FAILURE; 571 goto _exit0; 572 573 default: 574 xge_debug_osdep(XGE_ERR, "cmd 0x%x unrecognized", cmd); 575 ret = DDI_FAILURE; 576 goto _exit0; 577 } 578 579 xge_os_memzero(&device_config, sizeof (xge_hal_device_config_t)); 580 581 /* Init device_config by lookup up properties from .conf file */ 582 xge_configuration_init(dev_info, &device_config, &ll_config); 583 584 /* map BAR0 */ 585 ret = ddi_regs_map_setup(dev_info, 1, (caddr_t *)&attr.bar0, 586 (offset_t)0, (offset_t)0, &xge_dev_attr, &attr.regh0); 587 if (ret != DDI_SUCCESS) { 588 xge_debug_osdep(XGE_ERR, "unable to map bar0: [%d]", ret); 589 goto _exit0; 590 } 591 592 /* map BAR1 */ 593 ret = ddi_regs_map_setup(dev_info, 2, (caddr_t *)&attr.bar1, 594 (offset_t)0, (offset_t)0, &xge_dev_attr, &attr.regh1); 595 if (ret != DDI_SUCCESS) { 596 xge_debug_osdep(XGE_ERR, "unable to map bar1: [%d]", ret); 597 goto _exit1; 598 } 599 600 /* preallocate memory for new HAL device and private LL part */ 601 hldev = kmem_zalloc(sizeof (xge_hal_device_t), KM_SLEEP); 602 if (hldev == NULL) { 603 xge_debug_osdep(XGE_ERR, "%s", "can not allocate memory"); 604 ret = DDI_ENOMEM; 605 goto _exit2; 606 } 607 608 /* get the interrupt block cookie associated with the interrupt */ 609 ret = ddi_get_iblock_cookie(dev_info, 0, &attr.irqh); 610 if (ret != DDI_SUCCESS) { 611 xge_debug_osdep(XGE_ERR, "%s", "can not get interrupt cookie"); 612 goto _exit2a; 613 } 614 615 /* Get the PCI Configuartion space handle */ 616 ret = pci_config_setup(dev_info, &attr.cfgh); 617 if (ret != DDI_SUCCESS) { 618 xge_debug_osdep(XGE_ERR, "%s", "can not setup config space"); 619 goto _exit2a; 620 } 621 622 attr.pdev = dev_info; 623 624 ret = xgell_device_alloc(hldev, dev_info, &ll); 625 if (ret != DDI_SUCCESS) { 626 xge_debug_osdep(XGE_ERR, 627 "%s", 628 "unable to allocate new LL device"); 629 goto _exit3; 630 } 631 632 /* attach an interrupt handler for handling Xge device interrupts */ 633 ret = ddi_add_intr(dev_info, 0, &attr.irqh, NULL, xge_isr, 634 (caddr_t)hldev); 635 if (ret != DDI_SUCCESS) { 636 xge_debug_osdep(XGE_ERR, "%s", "unable to register ISR"); 637 goto _exit3a; 638 } 639 640 /* initialize HW */ 641 status = xge_hal_device_initialize(hldev, &attr, &device_config); 642 if (status != XGE_HAL_OK) { 643 switch (status) { 644 case XGE_HAL_ERR_DRIVER_NOT_INITIALIZED: 645 xge_debug_osdep(XGE_ERR, "%s", 646 "driver is not initialized"); 647 ret = DDI_FAILURE; 648 goto _exit3b; 649 case XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT: 650 xge_debug_osdep(XGE_ERR, "%s", 651 "device is not quiescent"); 652 ret = DDI_EBUSY; 653 goto _exit3b; 654 case XGE_HAL_ERR_OUT_OF_MEMORY: 655 xge_debug_osdep(XGE_ERR, "%s", 656 "unable to allocate memory"); 657 ret = DDI_ENOMEM; 658 goto _exit3b; 659 default: 660 xge_debug_osdep(XGE_ERR, 661 "can't initialize the device: %d", status); 662 ret = DDI_FAILURE; 663 goto _exit3b; 664 } 665 } 666 667 /* allocate and register Link Layer */ 668 ret = xgell_device_register(ll, &ll_config); 669 if (ret != DDI_SUCCESS) { 670 goto _exit4; 671 } 672 673 /* store ll as a HAL private part */ 674 xge_hal_device_private_set(hldev, ll); 675 676 return (DDI_SUCCESS); 677 678 _exit4: 679 xge_hal_device_terminate(hldev); 680 _exit3b: 681 ddi_remove_intr(attr.pdev, 0, hldev->irqh); 682 _exit3a: 683 xgell_device_free(ll); 684 _exit3: 685 pci_config_teardown(&attr.cfgh); 686 _exit2a: 687 kmem_free(hldev, sizeof (xge_hal_device_t)); 688 _exit2: 689 ddi_regs_map_free(&attr.regh1); 690 _exit1: 691 ddi_regs_map_free(&attr.regh0); 692 _exit0: 693 return (ret); 694 } 695 696 /* 697 * xge_detach 698 * @dev_info: pointer to dev_info_t structure 699 * @cmd: attach command to process 700 * 701 * This function is called by OS when the system is about 702 * to shutdown or when the super user tries to unload 703 * the driver. This function frees all the memory allocated 704 * during xge_attch() and also unregisters the Xframe 705 * device instance from the GLD framework. 706 */ 707 static int 708 xge_detach(dev_info_t *dev_info, ddi_detach_cmd_t cmd) 709 { 710 xge_hal_device_t *hldev; 711 xge_hal_device_attr_t *attr; 712 xgelldev_t *lldev; 713 714 xge_debug_osdep(XGE_TRACE, "XGE_DETACH cmd %d", cmd); 715 716 hldev = (xge_hal_device_t *)ddi_get_driver_private(dev_info); 717 attr = xge_hal_device_attr(hldev); 718 lldev = xge_hal_device_private(hldev); 719 720 switch (cmd) { 721 case DDI_DETACH: 722 break; 723 724 case DDI_PM_SUSPEND: 725 xge_debug_osdep(XGE_ERR, "%s", "suspend unsupported yet"); 726 return (DDI_FAILURE); 727 728 default: 729 xge_debug_osdep(XGE_ERR, "cmd 0x%x unrecognized", cmd); 730 return (DDI_FAILURE); 731 } 732 733 if (lldev->is_initialized) { 734 xge_debug_osdep(XGE_ERR, "%s", 735 "can not detach: device is not unplumbed"); 736 return (DDI_FAILURE); 737 } 738 739 xge_hal_device_terminating(hldev); 740 if (xgell_device_unregister(lldev) != DDI_SUCCESS) { 741 return (DDI_FAILURE); 742 } 743 xge_hal_device_terminate(hldev); 744 745 ddi_remove_intr(attr->pdev, 0, attr->irqh); 746 xgell_device_free(lldev); 747 pci_config_teardown(&attr->cfgh); 748 ddi_regs_map_free(&attr->regh1); 749 ddi_regs_map_free(&attr->regh0); 750 kmem_free(hldev, sizeof (xge_hal_device_t)); 751 752 return (DDI_SUCCESS); 753 } 754