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 2008 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 #include "nge.h" 30 31 /* 32 * Describes the chip's DMA engine 33 */ 34 35 static ddi_dma_attr_t hot_dma_attr = { 36 DMA_ATTR_V0, /* dma_attr version */ 37 0x0000000000000000ull, /* dma_attr_addr_lo */ 38 0x000000FFFFFFFFFFull, /* dma_attr_addr_hi */ 39 0x000000007FFFFFFFull, /* dma_attr_count_max */ 40 0x0000000000000010ull, /* dma_attr_align */ 41 0x00000FFF, /* dma_attr_burstsizes */ 42 0x00000001, /* dma_attr_minxfer */ 43 0x000000000000FFFFull, /* dma_attr_maxxfer */ 44 0x000000FFFFFFFFFFull, /* dma_attr_seg */ 45 1, /* dma_attr_sgllen */ 46 0x00000001, /* dma_attr_granular */ 47 0 48 }; 49 50 static ddi_dma_attr_t hot_tx_dma_attr = { 51 DMA_ATTR_V0, /* dma_attr version */ 52 0x0000000000000000ull, /* dma_attr_addr_lo */ 53 0x000000FFFFFFFFFFull, /* dma_attr_addr_hi */ 54 0x0000000000003FFFull, /* dma_attr_count_max */ 55 0x0000000000000010ull, /* dma_attr_align */ 56 0x00000FFF, /* dma_attr_burstsizes */ 57 0x00000001, /* dma_attr_minxfer */ 58 0x0000000000003FFFull, /* dma_attr_maxxfer */ 59 0x000000FFFFFFFFFFull, /* dma_attr_seg */ 60 NGE_MAX_COOKIES, /* dma_attr_sgllen */ 61 1, /* dma_attr_granular */ 62 0 63 }; 64 65 static ddi_dma_attr_t sum_dma_attr = { 66 DMA_ATTR_V0, /* dma_attr version */ 67 0x0000000000000000ull, /* dma_attr_addr_lo */ 68 0x00000000FFFFFFFFull, /* dma_attr_addr_hi */ 69 0x000000007FFFFFFFull, /* dma_attr_count_max */ 70 0x0000000000000010ull, /* dma_attr_align */ 71 0x00000FFF, /* dma_attr_burstsizes */ 72 0x00000001, /* dma_attr_minxfer */ 73 0x000000000000FFFFull, /* dma_attr_maxxfer */ 74 0x00000000FFFFFFFFull, /* dma_attr_seg */ 75 1, /* dma_attr_sgllen */ 76 0x00000001, /* dma_attr_granular */ 77 0 78 }; 79 80 static ddi_dma_attr_t sum_tx_dma_attr = { 81 DMA_ATTR_V0, /* dma_attr version */ 82 0x0000000000000000ull, /* dma_attr_addr_lo */ 83 0x00000000FFFFFFFFull, /* dma_attr_addr_hi */ 84 0x0000000000003FFFull, /* dma_attr_count_max */ 85 0x0000000000000010ull, /* dma_attr_align */ 86 0x00000FFF, /* dma_attr_burstsizes */ 87 0x00000001, /* dma_attr_minxfer */ 88 0x0000000000003FFFull, /* dma_attr_maxxfer */ 89 0x00000000FFFFFFFFull, /* dma_attr_seg */ 90 NGE_MAX_COOKIES, /* dma_attr_sgllen */ 91 1, /* dma_attr_granular */ 92 0 93 }; 94 95 /* 96 * DMA access attributes for data. 97 */ 98 ddi_device_acc_attr_t nge_data_accattr = { 99 DDI_DEVICE_ATTR_V0, 100 DDI_STRUCTURE_LE_ACC, 101 DDI_STRICTORDER_ACC, 102 DDI_DEFAULT_ACC 103 }; 104 105 /* 106 * DMA access attributes for descriptors. 107 */ 108 static ddi_device_acc_attr_t nge_desc_accattr = { 109 DDI_DEVICE_ATTR_V0, 110 DDI_STRUCTURE_LE_ACC, 111 DDI_STRICTORDER_ACC, 112 DDI_DEFAULT_ACC 113 }; 114 115 /* 116 * PIO access attributes for registers 117 */ 118 static ddi_device_acc_attr_t nge_reg_accattr = { 119 DDI_DEVICE_ATTR_V0, 120 DDI_STRUCTURE_LE_ACC, 121 DDI_STRICTORDER_ACC, 122 DDI_DEFAULT_ACC 123 }; 124 125 /* 126 * NIC DESC MODE 2 127 */ 128 129 static const nge_desc_attr_t nge_sum_desc = { 130 131 sizeof (sum_rx_bd), 132 sizeof (sum_tx_bd), 133 &sum_dma_attr, 134 &sum_tx_dma_attr, 135 nge_sum_rxd_fill, 136 nge_sum_rxd_check, 137 nge_sum_txd_fill, 138 nge_sum_txd_check, 139 }; 140 141 /* 142 * NIC DESC MODE 3 143 */ 144 145 static const nge_desc_attr_t nge_hot_desc = { 146 147 sizeof (hot_rx_bd), 148 sizeof (hot_tx_bd), 149 &hot_dma_attr, 150 &hot_tx_dma_attr, 151 nge_hot_rxd_fill, 152 nge_hot_rxd_check, 153 nge_hot_txd_fill, 154 nge_hot_txd_check, 155 }; 156 157 static char nge_ident[] = "nVidia 1Gb Ethernet %I%"; 158 static char clsize_propname[] = "cache-line-size"; 159 static char latency_propname[] = "latency-timer"; 160 static char debug_propname[] = "nge-debug-flags"; 161 static char intr_moderation[] = "intr-moderation"; 162 static char rx_data_hw[] = "rx-data-hw"; 163 static char rx_prd_lw[] = "rx-prd-lw"; 164 static char rx_prd_hw[] = "rx-prd-hw"; 165 static char sw_intr_intv[] = "sw-intr-intvl"; 166 static char nge_desc_mode[] = "desc-mode"; 167 static char default_mtu[] = "default_mtu"; 168 static char low_memory_mode[] = "minimal-memory-usage"; 169 extern kmutex_t nge_log_mutex[1]; 170 171 static int nge_m_start(void *); 172 static void nge_m_stop(void *); 173 static int nge_m_promisc(void *, boolean_t); 174 static int nge_m_multicst(void *, boolean_t, const uint8_t *); 175 static int nge_m_unicst(void *, const uint8_t *); 176 static void nge_m_ioctl(void *, queue_t *, mblk_t *); 177 static boolean_t nge_m_getcapab(void *, mac_capab_t, void *); 178 static int nge_m_setprop(void *, const char *, mac_prop_id_t, 179 uint_t, const void *); 180 static int nge_m_getprop(void *, const char *, mac_prop_id_t, 181 uint_t, void *); 182 static int nge_set_priv_prop(nge_t *, const char *, uint_t, 183 const void *); 184 static int nge_get_priv_prop(nge_t *, const char *, uint_t, 185 void *); 186 187 #define NGE_M_CALLBACK_FLAGS\ 188 (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP) 189 190 static mac_callbacks_t nge_m_callbacks = { 191 NGE_M_CALLBACK_FLAGS, 192 nge_m_stat, 193 nge_m_start, 194 nge_m_stop, 195 nge_m_promisc, 196 nge_m_multicst, 197 nge_m_unicst, 198 nge_m_tx, 199 NULL, 200 nge_m_ioctl, 201 nge_m_getcapab, 202 NULL, 203 NULL, 204 nge_m_setprop, 205 nge_m_getprop 206 }; 207 208 static int nge_add_intrs(nge_t *, int); 209 static void nge_rem_intrs(nge_t *); 210 static int nge_register_intrs_and_init_locks(nge_t *); 211 212 /* 213 * NGE MSI tunable: 214 */ 215 boolean_t nge_enable_msi = B_FALSE; 216 217 static enum ioc_reply 218 nge_set_loop_mode(nge_t *ngep, uint32_t mode) 219 { 220 /* 221 * If the mode isn't being changed, there's nothing to do ... 222 */ 223 if (mode == ngep->param_loop_mode) 224 return (IOC_ACK); 225 226 /* 227 * Validate the requested mode and prepare a suitable message 228 * to explain the link down/up cycle that the change will 229 * probably induce ... 230 */ 231 switch (mode) { 232 default: 233 return (IOC_INVAL); 234 235 case NGE_LOOP_NONE: 236 case NGE_LOOP_EXTERNAL_100: 237 case NGE_LOOP_EXTERNAL_10: 238 case NGE_LOOP_INTERNAL_PHY: 239 break; 240 } 241 242 /* 243 * All OK; tell the caller to reprogram 244 * the PHY and/or MAC for the new mode ... 245 */ 246 ngep->param_loop_mode = mode; 247 return (IOC_RESTART_ACK); 248 } 249 250 #undef NGE_DBG 251 #define NGE_DBG NGE_DBG_INIT 252 253 /* 254 * Utility routine to carve a slice off a chunk of allocated memory, 255 * updating the chunk descriptor accordingly. The size of the slice 256 * is given by the product of the <qty> and <size> parameters. 257 */ 258 void 259 nge_slice_chunk(dma_area_t *slice, dma_area_t *chunk, 260 uint32_t qty, uint32_t size) 261 { 262 size_t totsize; 263 264 totsize = qty*size; 265 ASSERT(size > 0); 266 ASSERT(totsize <= chunk->alength); 267 268 *slice = *chunk; 269 slice->nslots = qty; 270 slice->size = size; 271 slice->alength = totsize; 272 273 chunk->mem_va = (caddr_t)chunk->mem_va + totsize; 274 chunk->alength -= totsize; 275 chunk->offset += totsize; 276 chunk->cookie.dmac_laddress += totsize; 277 chunk->cookie.dmac_size -= totsize; 278 } 279 280 /* 281 * Allocate an area of memory and a DMA handle for accessing it 282 */ 283 int 284 nge_alloc_dma_mem(nge_t *ngep, size_t memsize, ddi_device_acc_attr_t *attr_p, 285 uint_t dma_flags, dma_area_t *dma_p) 286 { 287 int err; 288 caddr_t va; 289 290 NGE_TRACE(("nge_alloc_dma_mem($%p, %ld, $%p, 0x%x, $%p)", 291 (void *)ngep, memsize, attr_p, dma_flags, dma_p)); 292 /* 293 * Allocate handle 294 */ 295 err = ddi_dma_alloc_handle(ngep->devinfo, ngep->desc_attr.dma_attr, 296 DDI_DMA_DONTWAIT, NULL, &dma_p->dma_hdl); 297 if (err != DDI_SUCCESS) 298 goto fail; 299 300 /* 301 * Allocate memory 302 */ 303 err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, attr_p, 304 dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING), 305 DDI_DMA_DONTWAIT, NULL, &va, &dma_p->alength, &dma_p->acc_hdl); 306 if (err != DDI_SUCCESS) 307 goto fail; 308 309 /* 310 * Bind the two together 311 */ 312 dma_p->mem_va = va; 313 err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL, 314 va, dma_p->alength, dma_flags, DDI_DMA_DONTWAIT, NULL, 315 &dma_p->cookie, &dma_p->ncookies); 316 317 if (err != DDI_DMA_MAPPED || dma_p->ncookies != 1) 318 goto fail; 319 320 dma_p->nslots = ~0U; 321 dma_p->size = ~0U; 322 dma_p->offset = 0; 323 324 return (DDI_SUCCESS); 325 326 fail: 327 nge_free_dma_mem(dma_p); 328 NGE_DEBUG(("nge_alloc_dma_mem: fail to alloc dma memory!")); 329 330 return (DDI_FAILURE); 331 } 332 333 /* 334 * Free one allocated area of DMAable memory 335 */ 336 void 337 nge_free_dma_mem(dma_area_t *dma_p) 338 { 339 if (dma_p->dma_hdl != NULL) { 340 if (dma_p->ncookies) { 341 (void) ddi_dma_unbind_handle(dma_p->dma_hdl); 342 dma_p->ncookies = 0; 343 } 344 } 345 if (dma_p->acc_hdl != NULL) { 346 ddi_dma_mem_free(&dma_p->acc_hdl); 347 dma_p->acc_hdl = NULL; 348 } 349 if (dma_p->dma_hdl != NULL) { 350 ddi_dma_free_handle(&dma_p->dma_hdl); 351 dma_p->dma_hdl = NULL; 352 } 353 } 354 355 #define ALLOC_TX_BUF 0x1 356 #define ALLOC_TX_DESC 0x2 357 #define ALLOC_RX_DESC 0x4 358 359 int 360 nge_alloc_bufs(nge_t *ngep) 361 { 362 int err; 363 int split; 364 int progress; 365 size_t txbuffsize; 366 size_t rxdescsize; 367 size_t txdescsize; 368 369 txbuffsize = ngep->tx_desc * ngep->buf_size; 370 rxdescsize = ngep->rx_desc; 371 txdescsize = ngep->tx_desc; 372 rxdescsize *= ngep->desc_attr.rxd_size; 373 txdescsize *= ngep->desc_attr.txd_size; 374 progress = 0; 375 376 NGE_TRACE(("nge_alloc_bufs($%p)", (void *)ngep)); 377 /* 378 * Allocate memory & handles for TX buffers 379 */ 380 ASSERT((txbuffsize % ngep->nge_split) == 0); 381 for (split = 0; split < ngep->nge_split; ++split) { 382 err = nge_alloc_dma_mem(ngep, txbuffsize/ngep->nge_split, 383 &nge_data_accattr, DDI_DMA_WRITE | NGE_DMA_MODE, 384 &ngep->send->buf[split]); 385 if (err != DDI_SUCCESS) 386 goto fail; 387 } 388 389 progress |= ALLOC_TX_BUF; 390 391 /* 392 * Allocate memory & handles for receive return rings and 393 * buffer (producer) descriptor rings 394 */ 395 err = nge_alloc_dma_mem(ngep, rxdescsize, &nge_desc_accattr, 396 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, &ngep->recv->desc); 397 if (err != DDI_SUCCESS) 398 goto fail; 399 progress |= ALLOC_RX_DESC; 400 401 /* 402 * Allocate memory & handles for TX descriptor rings, 403 */ 404 err = nge_alloc_dma_mem(ngep, txdescsize, &nge_desc_accattr, 405 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, &ngep->send->desc); 406 if (err != DDI_SUCCESS) 407 goto fail; 408 return (DDI_SUCCESS); 409 410 fail: 411 if (progress & ALLOC_RX_DESC) 412 nge_free_dma_mem(&ngep->recv->desc); 413 if (progress & ALLOC_TX_BUF) { 414 for (split = 0; split < ngep->nge_split; ++split) 415 nge_free_dma_mem(&ngep->send->buf[split]); 416 } 417 418 return (DDI_FAILURE); 419 } 420 421 /* 422 * This routine frees the transmit and receive buffers and descriptors. 423 * Make sure the chip is stopped before calling it! 424 */ 425 void 426 nge_free_bufs(nge_t *ngep) 427 { 428 int split; 429 430 NGE_TRACE(("nge_free_bufs($%p)", (void *)ngep)); 431 432 nge_free_dma_mem(&ngep->recv->desc); 433 nge_free_dma_mem(&ngep->send->desc); 434 435 for (split = 0; split < ngep->nge_split; ++split) 436 nge_free_dma_mem(&ngep->send->buf[split]); 437 } 438 439 /* 440 * Clean up initialisation done above before the memory is freed 441 */ 442 static void 443 nge_fini_send_ring(nge_t *ngep) 444 { 445 uint32_t slot; 446 size_t dmah_num; 447 send_ring_t *srp; 448 sw_tx_sbd_t *ssbdp; 449 450 srp = ngep->send; 451 ssbdp = srp->sw_sbds; 452 453 NGE_TRACE(("nge_fini_send_ring($%p)", (void *)ngep)); 454 455 dmah_num = sizeof (srp->dmahndl) / sizeof (srp->dmahndl[0]); 456 457 for (slot = 0; slot < dmah_num; ++slot) { 458 if (srp->dmahndl[slot].hndl) { 459 (void) ddi_dma_unbind_handle(srp->dmahndl[slot].hndl); 460 ddi_dma_free_handle(&srp->dmahndl[slot].hndl); 461 srp->dmahndl[slot].hndl = NULL; 462 srp->dmahndl[slot].next = NULL; 463 } 464 } 465 466 srp->dmah_free.head = NULL; 467 srp->dmah_free.tail = NULL; 468 469 kmem_free(ssbdp, srp->desc.nslots*sizeof (*ssbdp)); 470 471 } 472 473 /* 474 * Initialise the specified Send Ring, using the information in the 475 * <dma_area> descriptors that it contains to set up all the other 476 * fields. This routine should be called only once for each ring. 477 */ 478 static int 479 nge_init_send_ring(nge_t *ngep) 480 { 481 size_t dmah_num; 482 uint32_t nslots; 483 uint32_t err; 484 uint32_t slot; 485 uint32_t split; 486 send_ring_t *srp; 487 sw_tx_sbd_t *ssbdp; 488 dma_area_t desc; 489 dma_area_t pbuf; 490 491 srp = ngep->send; 492 srp->desc.nslots = ngep->tx_desc; 493 nslots = srp->desc.nslots; 494 495 NGE_TRACE(("nge_init_send_ring($%p)", (void *)ngep)); 496 /* 497 * Other one-off initialisation of per-ring data 498 */ 499 srp->ngep = ngep; 500 501 /* 502 * Allocate the array of s/w Send Buffer Descriptors 503 */ 504 ssbdp = kmem_zalloc(nslots*sizeof (*ssbdp), KM_SLEEP); 505 srp->sw_sbds = ssbdp; 506 507 /* 508 * Now initialise each array element once and for all 509 */ 510 desc = srp->desc; 511 for (split = 0; split < ngep->nge_split; ++split) { 512 pbuf = srp->buf[split]; 513 for (slot = 0; slot < nslots/ngep->nge_split; ++ssbdp, ++slot) { 514 nge_slice_chunk(&ssbdp->desc, &desc, 1, 515 ngep->desc_attr.txd_size); 516 nge_slice_chunk(&ssbdp->pbuf, &pbuf, 1, 517 ngep->buf_size); 518 } 519 ASSERT(pbuf.alength == 0); 520 } 521 ASSERT(desc.alength == 0); 522 523 dmah_num = sizeof (srp->dmahndl) / sizeof (srp->dmahndl[0]); 524 525 /* preallocate dma handles for tx buffer */ 526 for (slot = 0; slot < dmah_num; ++slot) { 527 528 err = ddi_dma_alloc_handle(ngep->devinfo, 529 ngep->desc_attr.tx_dma_attr, DDI_DMA_DONTWAIT, 530 NULL, &srp->dmahndl[slot].hndl); 531 532 if (err != DDI_SUCCESS) { 533 nge_fini_send_ring(ngep); 534 nge_error(ngep, 535 "nge_init_send_ring: alloc dma handle fails"); 536 return (DDI_FAILURE); 537 } 538 srp->dmahndl[slot].next = srp->dmahndl + slot + 1; 539 } 540 541 srp->dmah_free.head = srp->dmahndl; 542 srp->dmah_free.tail = srp->dmahndl + dmah_num - 1; 543 srp->dmah_free.tail->next = NULL; 544 545 return (DDI_SUCCESS); 546 } 547 548 /* 549 * Intialize the tx recycle pointer and tx sending pointer of tx ring 550 * and set the type of tx's data descriptor by default. 551 */ 552 static void 553 nge_reinit_send_ring(nge_t *ngep) 554 { 555 size_t dmah_num; 556 uint32_t slot; 557 send_ring_t *srp; 558 sw_tx_sbd_t *ssbdp; 559 560 srp = ngep->send; 561 562 /* 563 * Reinitialise control variables ... 564 */ 565 566 srp->tx_hwmark = NGE_DESC_MIN; 567 srp->tx_lwmark = NGE_DESC_MIN; 568 569 srp->tx_next = 0; 570 srp->tx_free = srp->desc.nslots; 571 srp->tc_next = 0; 572 573 dmah_num = sizeof (srp->dmahndl) / sizeof (srp->dmahndl[0]); 574 575 for (slot = 0; slot - dmah_num != 0; ++slot) 576 srp->dmahndl[slot].next = srp->dmahndl + slot + 1; 577 578 srp->dmah_free.head = srp->dmahndl; 579 srp->dmah_free.tail = srp->dmahndl + dmah_num - 1; 580 srp->dmah_free.tail->next = NULL; 581 582 /* 583 * Zero and sync all the h/w Send Buffer Descriptors 584 */ 585 for (slot = 0; slot < srp->desc.nslots; ++slot) { 586 ssbdp = &srp->sw_sbds[slot]; 587 ssbdp->flags = HOST_OWN; 588 } 589 590 DMA_ZERO(srp->desc); 591 DMA_SYNC(srp->desc, DDI_DMA_SYNC_FORDEV); 592 } 593 594 /* 595 * Initialize the slot number of rx's ring 596 */ 597 static void 598 nge_init_recv_ring(nge_t *ngep) 599 { 600 recv_ring_t *rrp; 601 602 rrp = ngep->recv; 603 rrp->desc.nslots = ngep->rx_desc; 604 rrp->ngep = ngep; 605 } 606 607 /* 608 * Intialize the rx recycle pointer and rx sending pointer of rx ring 609 */ 610 static void 611 nge_reinit_recv_ring(nge_t *ngep) 612 { 613 recv_ring_t *rrp; 614 615 rrp = ngep->recv; 616 617 /* 618 * Reinitialise control variables ... 619 */ 620 rrp->prod_index = 0; 621 /* 622 * Zero and sync all the h/w Send Buffer Descriptors 623 */ 624 DMA_ZERO(rrp->desc); 625 DMA_SYNC(rrp->desc, DDI_DMA_SYNC_FORDEV); 626 } 627 628 /* 629 * Clean up initialisation done above before the memory is freed 630 */ 631 static void 632 nge_fini_buff_ring(nge_t *ngep) 633 { 634 uint32_t i; 635 buff_ring_t *brp; 636 dma_area_t *bufp; 637 sw_rx_sbd_t *bsbdp; 638 639 brp = ngep->buff; 640 bsbdp = brp->sw_rbds; 641 642 NGE_DEBUG(("nge_fini_buff_ring($%p)", (void *)ngep)); 643 644 mutex_enter(brp->recycle_lock); 645 brp->buf_sign++; 646 mutex_exit(brp->recycle_lock); 647 for (i = 0; i < ngep->rx_desc; i++, ++bsbdp) { 648 if (bsbdp->bufp) { 649 if (bsbdp->bufp->mp) 650 freemsg(bsbdp->bufp->mp); 651 nge_free_dma_mem(bsbdp->bufp); 652 kmem_free(bsbdp->bufp, sizeof (dma_area_t)); 653 bsbdp->bufp = NULL; 654 } 655 } 656 while (brp->free_list != NULL) { 657 bufp = brp->free_list; 658 brp->free_list = bufp->next; 659 bufp->next = NULL; 660 if (bufp->mp) 661 freemsg(bufp->mp); 662 nge_free_dma_mem(bufp); 663 kmem_free(bufp, sizeof (dma_area_t)); 664 } 665 while (brp->recycle_list != NULL) { 666 bufp = brp->recycle_list; 667 brp->recycle_list = bufp->next; 668 bufp->next = NULL; 669 if (bufp->mp) 670 freemsg(bufp->mp); 671 nge_free_dma_mem(bufp); 672 kmem_free(bufp, sizeof (dma_area_t)); 673 } 674 675 676 kmem_free(brp->sw_rbds, (ngep->rx_desc * sizeof (*bsbdp))); 677 brp->sw_rbds = NULL; 678 } 679 680 /* 681 * Intialize the Rx's data ring and free ring 682 */ 683 static int 684 nge_init_buff_ring(nge_t *ngep) 685 { 686 uint32_t err; 687 uint32_t slot; 688 uint32_t nslots_buff; 689 uint32_t nslots_recv; 690 buff_ring_t *brp; 691 recv_ring_t *rrp; 692 dma_area_t desc; 693 dma_area_t *bufp; 694 sw_rx_sbd_t *bsbdp; 695 696 rrp = ngep->recv; 697 brp = ngep->buff; 698 brp->nslots = ngep->rx_buf; 699 brp->rx_bcopy = B_FALSE; 700 nslots_recv = rrp->desc.nslots; 701 nslots_buff = brp->nslots; 702 brp->ngep = ngep; 703 704 NGE_TRACE(("nge_init_buff_ring($%p)", (void *)ngep)); 705 706 /* 707 * Allocate the array of s/w Recv Buffer Descriptors 708 */ 709 bsbdp = kmem_zalloc(nslots_recv *sizeof (*bsbdp), KM_SLEEP); 710 brp->sw_rbds = bsbdp; 711 brp->free_list = NULL; 712 brp->recycle_list = NULL; 713 for (slot = 0; slot < nslots_buff; ++slot) { 714 bufp = kmem_zalloc(sizeof (dma_area_t), KM_SLEEP); 715 err = nge_alloc_dma_mem(ngep, (ngep->buf_size 716 + NGE_HEADROOM), 717 &nge_data_accattr, DDI_DMA_READ | NGE_DMA_MODE, bufp); 718 if (err != DDI_SUCCESS) { 719 kmem_free(bufp, sizeof (dma_area_t)); 720 return (DDI_FAILURE); 721 } 722 723 bufp->alength -= NGE_HEADROOM; 724 bufp->offset += NGE_HEADROOM; 725 bufp->private = (caddr_t)ngep; 726 bufp->rx_recycle.free_func = nge_recv_recycle; 727 bufp->rx_recycle.free_arg = (caddr_t)bufp; 728 bufp->signature = brp->buf_sign; 729 bufp->rx_delivered = B_FALSE; 730 bufp->mp = desballoc(DMA_VPTR(*bufp), 731 ngep->buf_size + NGE_HEADROOM, 732 0, &bufp->rx_recycle); 733 734 if (bufp->mp == NULL) { 735 return (DDI_FAILURE); 736 } 737 bufp->next = brp->free_list; 738 brp->free_list = bufp; 739 } 740 741 /* 742 * Now initialise each array element once and for all 743 */ 744 desc = rrp->desc; 745 for (slot = 0; slot < nslots_recv; ++slot, ++bsbdp) { 746 nge_slice_chunk(&bsbdp->desc, &desc, 1, 747 ngep->desc_attr.rxd_size); 748 bufp = brp->free_list; 749 brp->free_list = bufp->next; 750 bsbdp->bufp = bufp; 751 bsbdp->flags = CONTROLER_OWN; 752 bufp->next = NULL; 753 } 754 755 ASSERT(desc.alength == 0); 756 return (DDI_SUCCESS); 757 } 758 759 /* 760 * Fill the host address of data in rx' descriptor 761 * and initialize free pointers of rx free ring 762 */ 763 static int 764 nge_reinit_buff_ring(nge_t *ngep) 765 { 766 uint32_t slot; 767 uint32_t nslots_recv; 768 buff_ring_t *brp; 769 recv_ring_t *rrp; 770 sw_rx_sbd_t *bsbdp; 771 void *hw_bd_p; 772 773 brp = ngep->buff; 774 rrp = ngep->recv; 775 bsbdp = brp->sw_rbds; 776 nslots_recv = rrp->desc.nslots; 777 for (slot = 0; slot < nslots_recv; ++bsbdp, ++slot) { 778 hw_bd_p = DMA_VPTR(bsbdp->desc); 779 /* 780 * There is a scenario: When the traffic of small tcp 781 * packet is heavy, suspending the tcp traffic will 782 * cause the preallocated buffers for rx not to be 783 * released in time by tcp taffic and cause rx's buffer 784 * pointers not to be refilled in time. 785 * 786 * At this point, if we reinitialize the driver, the bufp 787 * pointer for rx's traffic will be NULL. 788 * So the result of the reinitializion fails. 789 */ 790 if (bsbdp->bufp == NULL) 791 return (DDI_FAILURE); 792 793 ngep->desc_attr.rxd_fill(hw_bd_p, &bsbdp->bufp->cookie, 794 bsbdp->bufp->alength); 795 } 796 return (DDI_SUCCESS); 797 } 798 799 static void 800 nge_init_ring_param_lock(nge_t *ngep) 801 { 802 buff_ring_t *brp; 803 send_ring_t *srp; 804 805 srp = ngep->send; 806 brp = ngep->buff; 807 808 /* Init the locks for send ring */ 809 mutex_init(srp->tx_lock, NULL, MUTEX_DRIVER, 810 DDI_INTR_PRI(ngep->intr_pri)); 811 mutex_init(srp->tc_lock, NULL, MUTEX_DRIVER, 812 DDI_INTR_PRI(ngep->intr_pri)); 813 mutex_init(&srp->dmah_lock, NULL, MUTEX_DRIVER, 814 DDI_INTR_PRI(ngep->intr_pri)); 815 816 /* Init parameters of buffer ring */ 817 brp->free_list = NULL; 818 brp->recycle_list = NULL; 819 brp->rx_hold = 0; 820 brp->buf_sign = 0; 821 822 /* Init recycle list lock */ 823 mutex_init(brp->recycle_lock, NULL, MUTEX_DRIVER, 824 DDI_INTR_PRI(ngep->intr_pri)); 825 } 826 827 int 828 nge_init_rings(nge_t *ngep) 829 { 830 uint32_t err; 831 832 err = nge_init_send_ring(ngep); 833 if (err != DDI_SUCCESS) { 834 return (err); 835 } 836 nge_init_recv_ring(ngep); 837 838 err = nge_init_buff_ring(ngep); 839 if (err != DDI_SUCCESS) { 840 nge_fini_send_ring(ngep); 841 return (DDI_FAILURE); 842 } 843 844 return (err); 845 } 846 847 static int 848 nge_reinit_ring(nge_t *ngep) 849 { 850 int err; 851 852 nge_reinit_recv_ring(ngep); 853 nge_reinit_send_ring(ngep); 854 err = nge_reinit_buff_ring(ngep); 855 return (err); 856 } 857 858 859 void 860 nge_fini_rings(nge_t *ngep) 861 { 862 /* 863 * For receive ring, nothing need to be finished. 864 * So only finish buffer ring and send ring here. 865 */ 866 nge_fini_buff_ring(ngep); 867 nge_fini_send_ring(ngep); 868 } 869 870 /* 871 * Loopback ioctl code 872 */ 873 874 static lb_property_t loopmodes[] = { 875 { normal, "normal", NGE_LOOP_NONE }, 876 { external, "100Mbps", NGE_LOOP_EXTERNAL_100 }, 877 { external, "10Mbps", NGE_LOOP_EXTERNAL_10 }, 878 { internal, "PHY", NGE_LOOP_INTERNAL_PHY }, 879 }; 880 881 enum ioc_reply 882 nge_loop_ioctl(nge_t *ngep, mblk_t *mp, struct iocblk *iocp) 883 { 884 int cmd; 885 uint32_t *lbmp; 886 lb_info_sz_t *lbsp; 887 lb_property_t *lbpp; 888 889 /* 890 * Validate format of ioctl 891 */ 892 if (mp->b_cont == NULL) 893 return (IOC_INVAL); 894 895 cmd = iocp->ioc_cmd; 896 897 switch (cmd) { 898 default: 899 return (IOC_INVAL); 900 901 case LB_GET_INFO_SIZE: 902 if (iocp->ioc_count != sizeof (lb_info_sz_t)) 903 return (IOC_INVAL); 904 lbsp = (lb_info_sz_t *)mp->b_cont->b_rptr; 905 *lbsp = sizeof (loopmodes); 906 return (IOC_REPLY); 907 908 case LB_GET_INFO: 909 if (iocp->ioc_count != sizeof (loopmodes)) 910 return (IOC_INVAL); 911 lbpp = (lb_property_t *)mp->b_cont->b_rptr; 912 bcopy(loopmodes, lbpp, sizeof (loopmodes)); 913 return (IOC_REPLY); 914 915 case LB_GET_MODE: 916 if (iocp->ioc_count != sizeof (uint32_t)) 917 return (IOC_INVAL); 918 lbmp = (uint32_t *)mp->b_cont->b_rptr; 919 *lbmp = ngep->param_loop_mode; 920 return (IOC_REPLY); 921 922 case LB_SET_MODE: 923 if (iocp->ioc_count != sizeof (uint32_t)) 924 return (IOC_INVAL); 925 lbmp = (uint32_t *)mp->b_cont->b_rptr; 926 return (nge_set_loop_mode(ngep, *lbmp)); 927 } 928 } 929 930 #undef NGE_DBG 931 #define NGE_DBG NGE_DBG_NEMO 932 933 934 static void 935 nge_check_desc_prop(nge_t *ngep) 936 { 937 if (ngep->desc_mode != DESC_HOT && ngep->desc_mode != DESC_OFFLOAD) 938 ngep->desc_mode = DESC_HOT; 939 940 if (ngep->desc_mode == DESC_OFFLOAD) { 941 942 ngep->desc_attr = nge_sum_desc; 943 944 } else if (ngep->desc_mode == DESC_HOT) { 945 946 ngep->desc_attr = nge_hot_desc; 947 } 948 } 949 950 /* 951 * nge_get_props -- get the parameters to tune the driver 952 */ 953 static void 954 nge_get_props(nge_t *ngep) 955 { 956 chip_info_t *infop; 957 dev_info_t *devinfo; 958 nge_dev_spec_param_t *dev_param_p; 959 960 devinfo = ngep->devinfo; 961 infop = (chip_info_t *)&ngep->chipinfo; 962 dev_param_p = &ngep->dev_spec_param; 963 964 infop->clsize = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 965 DDI_PROP_DONTPASS, clsize_propname, 32); 966 967 infop->latency = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 968 DDI_PROP_DONTPASS, latency_propname, 64); 969 ngep->intr_moderation = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 970 DDI_PROP_DONTPASS, intr_moderation, NGE_SET); 971 ngep->rx_datahwm = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 972 DDI_PROP_DONTPASS, rx_data_hw, 0x20); 973 ngep->rx_prdlwm = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 974 DDI_PROP_DONTPASS, rx_prd_lw, 0x4); 975 ngep->rx_prdhwm = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 976 DDI_PROP_DONTPASS, rx_prd_hw, 0xc); 977 978 ngep->sw_intr_intv = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 979 DDI_PROP_DONTPASS, sw_intr_intv, SWTR_ITC); 980 ngep->debug = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 981 DDI_PROP_DONTPASS, debug_propname, NGE_DBG_CHIP); 982 ngep->desc_mode = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 983 DDI_PROP_DONTPASS, nge_desc_mode, dev_param_p->desc_type); 984 ngep->lowmem_mode = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 985 DDI_PROP_DONTPASS, low_memory_mode, 0); 986 987 if (dev_param_p->jumbo) { 988 ngep->default_mtu = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 989 DDI_PROP_DONTPASS, default_mtu, ETHERMTU); 990 } else 991 ngep->default_mtu = ETHERMTU; 992 993 if (ngep->default_mtu > ETHERMTU && 994 ngep->default_mtu <= NGE_MTU_2500) { 995 ngep->buf_size = NGE_JB2500_BUFSZ; 996 ngep->tx_desc = NGE_SEND_JB2500_SLOTS_DESC; 997 ngep->rx_desc = NGE_RECV_JB2500_SLOTS_DESC; 998 ngep->rx_buf = NGE_RECV_JB2500_SLOTS_DESC * 2; 999 ngep->nge_split = NGE_SPLIT_256; 1000 } else if (ngep->default_mtu > NGE_MTU_2500 && 1001 ngep->default_mtu <= NGE_MTU_4500) { 1002 ngep->buf_size = NGE_JB4500_BUFSZ; 1003 ngep->tx_desc = NGE_SEND_JB4500_SLOTS_DESC; 1004 ngep->rx_desc = NGE_RECV_JB4500_SLOTS_DESC; 1005 ngep->rx_buf = NGE_RECV_JB4500_SLOTS_DESC * 2; 1006 ngep->nge_split = NGE_SPLIT_256; 1007 } else if (ngep->default_mtu > NGE_MTU_4500 && 1008 ngep->default_mtu <= NGE_MAX_MTU) { 1009 ngep->buf_size = NGE_JB9000_BUFSZ; 1010 ngep->tx_desc = NGE_SEND_JB9000_SLOTS_DESC; 1011 ngep->rx_desc = NGE_RECV_JB9000_SLOTS_DESC; 1012 ngep->rx_buf = NGE_RECV_JB9000_SLOTS_DESC * 2; 1013 ngep->nge_split = NGE_SPLIT_256; 1014 } else if (ngep->default_mtu > NGE_MAX_MTU) { 1015 ngep->default_mtu = NGE_MAX_MTU; 1016 ngep->buf_size = NGE_JB9000_BUFSZ; 1017 ngep->tx_desc = NGE_SEND_JB9000_SLOTS_DESC; 1018 ngep->rx_desc = NGE_RECV_JB9000_SLOTS_DESC; 1019 ngep->rx_buf = NGE_RECV_JB9000_SLOTS_DESC * 2; 1020 ngep->nge_split = NGE_SPLIT_256; 1021 } else if (ngep->lowmem_mode != 0) { 1022 ngep->default_mtu = ETHERMTU; 1023 ngep->buf_size = NGE_STD_BUFSZ; 1024 ngep->tx_desc = NGE_SEND_LOWMEM_SLOTS_DESC; 1025 ngep->rx_desc = NGE_RECV_LOWMEM_SLOTS_DESC; 1026 ngep->rx_buf = NGE_RECV_LOWMEM_SLOTS_DESC * 2; 1027 ngep->nge_split = NGE_SPLIT_32; 1028 } else { 1029 ngep->default_mtu = ETHERMTU; 1030 ngep->buf_size = NGE_STD_BUFSZ; 1031 ngep->tx_desc = dev_param_p->tx_desc_num; 1032 ngep->rx_desc = dev_param_p->rx_desc_num; 1033 ngep->rx_buf = dev_param_p->rx_desc_num * 2; 1034 ngep->nge_split = dev_param_p->nge_split; 1035 } 1036 1037 nge_check_desc_prop(ngep); 1038 } 1039 1040 1041 static int 1042 nge_reset(nge_t *ngep) 1043 { 1044 int err; 1045 nge_mul_addr1 maddr1; 1046 nge_sw_statistics_t *sw_stp; 1047 sw_stp = &ngep->statistics.sw_statistics; 1048 send_ring_t *srp = ngep->send; 1049 1050 ASSERT(mutex_owned(ngep->genlock)); 1051 mutex_enter(srp->tc_lock); 1052 mutex_enter(srp->tx_lock); 1053 1054 nge_tx_recycle_all(ngep); 1055 err = nge_reinit_ring(ngep); 1056 if (err == DDI_FAILURE) { 1057 mutex_exit(srp->tx_lock); 1058 mutex_exit(srp->tc_lock); 1059 return (err); 1060 } 1061 err = nge_chip_reset(ngep); 1062 /* 1063 * Clear the Multicast mac address table 1064 */ 1065 nge_reg_put32(ngep, NGE_MUL_ADDR0, 0); 1066 maddr1.addr_val = nge_reg_get32(ngep, NGE_MUL_ADDR1); 1067 maddr1.addr_bits.addr = 0; 1068 nge_reg_put32(ngep, NGE_MUL_ADDR1, maddr1.addr_val); 1069 1070 mutex_exit(srp->tx_lock); 1071 mutex_exit(srp->tc_lock); 1072 if (err == DDI_FAILURE) 1073 return (err); 1074 ngep->watchdog = 0; 1075 ngep->resched_needed = B_FALSE; 1076 ngep->promisc = B_FALSE; 1077 ngep->param_loop_mode = NGE_LOOP_NONE; 1078 ngep->factotum_flag = 0; 1079 ngep->resched_needed = 0; 1080 ngep->nge_mac_state = NGE_MAC_RESET; 1081 ngep->max_sdu = ngep->default_mtu + ETHER_HEAD_LEN + ETHERFCSL; 1082 ngep->max_sdu += VTAG_SIZE; 1083 ngep->rx_def = 0x16; 1084 1085 /* Clear the software statistics */ 1086 sw_stp->recv_count = 0; 1087 sw_stp->xmit_count = 0; 1088 sw_stp->rbytes = 0; 1089 sw_stp->obytes = 0; 1090 1091 return (DDI_SUCCESS); 1092 } 1093 1094 static void 1095 nge_m_stop(void *arg) 1096 { 1097 nge_t *ngep = arg; /* private device info */ 1098 1099 NGE_TRACE(("nge_m_stop($%p)", arg)); 1100 1101 /* 1102 * Just stop processing, then record new MAC state 1103 */ 1104 mutex_enter(ngep->genlock); 1105 /* If suspended, the adapter is already stopped, just return. */ 1106 if (ngep->suspended) { 1107 ASSERT(ngep->nge_mac_state == NGE_MAC_STOPPED); 1108 mutex_exit(ngep->genlock); 1109 return; 1110 } 1111 rw_enter(ngep->rwlock, RW_WRITER); 1112 1113 (void) nge_chip_stop(ngep, B_FALSE); 1114 ngep->nge_mac_state = NGE_MAC_STOPPED; 1115 1116 /* Recycle all the TX BD */ 1117 nge_tx_recycle_all(ngep); 1118 nge_fini_rings(ngep); 1119 nge_free_bufs(ngep); 1120 1121 NGE_DEBUG(("nge_m_stop($%p) done", arg)); 1122 1123 rw_exit(ngep->rwlock); 1124 mutex_exit(ngep->genlock); 1125 } 1126 1127 static int 1128 nge_m_start(void *arg) 1129 { 1130 int err; 1131 nge_t *ngep = arg; 1132 1133 NGE_TRACE(("nge_m_start($%p)", arg)); 1134 1135 /* 1136 * Start processing and record new MAC state 1137 */ 1138 mutex_enter(ngep->genlock); 1139 /* 1140 * If suspended, don't start, as the resume processing 1141 * will recall this function with the suspended flag off. 1142 */ 1143 if (ngep->suspended) { 1144 mutex_exit(ngep->genlock); 1145 return (EIO); 1146 } 1147 rw_enter(ngep->rwlock, RW_WRITER); 1148 err = nge_alloc_bufs(ngep); 1149 if (err != DDI_SUCCESS) { 1150 nge_problem(ngep, "nge_m_start: DMA buffer allocation failed"); 1151 goto finish; 1152 } 1153 err = nge_init_rings(ngep); 1154 if (err != DDI_SUCCESS) { 1155 nge_free_bufs(ngep); 1156 nge_problem(ngep, "nge_init_rings() failed,err=%x", err); 1157 goto finish; 1158 } 1159 err = nge_restart(ngep); 1160 1161 NGE_DEBUG(("nge_m_start($%p) done", arg)); 1162 finish: 1163 rw_exit(ngep->rwlock); 1164 mutex_exit(ngep->genlock); 1165 1166 return (err == DDI_SUCCESS ? 0 : EIO); 1167 } 1168 1169 static int 1170 nge_m_unicst(void *arg, const uint8_t *macaddr) 1171 { 1172 nge_t *ngep = arg; 1173 1174 NGE_TRACE(("nge_m_unicst($%p)", arg)); 1175 /* 1176 * Remember the new current address in the driver state 1177 * Sync the chip's idea of the address too ... 1178 */ 1179 mutex_enter(ngep->genlock); 1180 1181 ethaddr_copy(macaddr, ngep->cur_uni_addr.addr); 1182 ngep->cur_uni_addr.set = 1; 1183 1184 /* 1185 * If we are suspended, we want to quit now, and not update 1186 * the chip. Doing so might put it in a bad state, but the 1187 * resume will get the unicast address installed. 1188 */ 1189 if (ngep->suspended) { 1190 mutex_exit(ngep->genlock); 1191 return (DDI_SUCCESS); 1192 } 1193 nge_chip_sync(ngep); 1194 1195 NGE_DEBUG(("nge_m_unicst($%p) done", arg)); 1196 mutex_exit(ngep->genlock); 1197 1198 return (0); 1199 } 1200 1201 static int 1202 nge_m_promisc(void *arg, boolean_t on) 1203 { 1204 nge_t *ngep = arg; 1205 1206 NGE_TRACE(("nge_m_promisc($%p)", arg)); 1207 1208 /* 1209 * Store specified mode and pass to chip layer to update h/w 1210 */ 1211 mutex_enter(ngep->genlock); 1212 /* 1213 * If suspended, there is no need to do anything, even 1214 * recording the promiscuious mode is not neccessary, as 1215 * it won't be properly set on resume. Just return failing. 1216 */ 1217 if (ngep->suspended) { 1218 mutex_exit(ngep->genlock); 1219 return (DDI_FAILURE); 1220 } 1221 if (ngep->promisc == on) { 1222 mutex_exit(ngep->genlock); 1223 NGE_DEBUG(("nge_m_promisc($%p) done", arg)); 1224 return (0); 1225 } 1226 ngep->promisc = on; 1227 nge_chip_sync(ngep); 1228 NGE_DEBUG(("nge_m_promisc($%p) done", arg)); 1229 mutex_exit(ngep->genlock); 1230 1231 return (0); 1232 } 1233 1234 static void nge_mulparam(nge_t *ngep) 1235 { 1236 uint8_t number; 1237 ether_addr_t pand; 1238 ether_addr_t por; 1239 mul_item *plist; 1240 1241 for (number = 0; number < ETHERADDRL; number++) { 1242 pand[number] = 0x00; 1243 por[number] = 0x00; 1244 } 1245 for (plist = ngep->pcur_mulist; plist != NULL; plist = plist->next) { 1246 for (number = 0; number < ETHERADDRL; number++) { 1247 pand[number] &= plist->mul_addr[number]; 1248 por[number] |= plist->mul_addr[number]; 1249 } 1250 } 1251 for (number = 0; number < ETHERADDRL; number++) { 1252 ngep->cur_mul_addr.addr[number] 1253 = pand[number] & por[number]; 1254 ngep->cur_mul_mask.addr[number] 1255 = pand [number] | (~por[number]); 1256 } 1257 } 1258 static int 1259 nge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 1260 { 1261 boolean_t update; 1262 boolean_t b_eq; 1263 nge_t *ngep = arg; 1264 mul_item *plist; 1265 mul_item *plist_prev; 1266 mul_item *pitem; 1267 1268 NGE_TRACE(("nge_m_multicst($%p, %s, %s)", arg, 1269 (add) ? "add" : "remove", ether_sprintf((void *)mca))); 1270 1271 update = B_FALSE; 1272 plist = plist_prev = NULL; 1273 mutex_enter(ngep->genlock); 1274 if (add) { 1275 if (ngep->pcur_mulist != NULL) { 1276 for (plist = ngep->pcur_mulist; plist != NULL; 1277 plist = plist->next) { 1278 b_eq = ether_eq(plist->mul_addr, mca); 1279 if (b_eq) { 1280 plist->ref_cnt++; 1281 break; 1282 } 1283 plist_prev = plist; 1284 } 1285 } 1286 1287 if (plist == NULL) { 1288 pitem = kmem_zalloc(sizeof (mul_item), KM_SLEEP); 1289 ether_copy(mca, pitem->mul_addr); 1290 pitem ->ref_cnt++; 1291 pitem ->next = NULL; 1292 if (plist_prev == NULL) 1293 ngep->pcur_mulist = pitem; 1294 else 1295 plist_prev->next = pitem; 1296 update = B_TRUE; 1297 } 1298 } else { 1299 if (ngep->pcur_mulist != NULL) { 1300 for (plist = ngep->pcur_mulist; plist != NULL; 1301 plist = plist->next) { 1302 b_eq = ether_eq(plist->mul_addr, mca); 1303 if (b_eq) { 1304 update = B_TRUE; 1305 break; 1306 } 1307 plist_prev = plist; 1308 } 1309 1310 if (update) { 1311 if ((plist_prev == NULL) && 1312 (plist->next == NULL)) 1313 ngep->pcur_mulist = NULL; 1314 else if ((plist_prev == NULL) && 1315 (plist->next != NULL)) 1316 ngep->pcur_mulist = plist->next; 1317 else 1318 plist_prev->next = plist->next; 1319 kmem_free(plist, sizeof (mul_item)); 1320 } 1321 } 1322 } 1323 1324 if (update && !ngep->suspended) { 1325 nge_mulparam(ngep); 1326 nge_chip_sync(ngep); 1327 } 1328 NGE_DEBUG(("nge_m_multicst($%p) done", arg)); 1329 mutex_exit(ngep->genlock); 1330 1331 return (0); 1332 } 1333 1334 static void 1335 nge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 1336 { 1337 int err; 1338 int cmd; 1339 nge_t *ngep = arg; 1340 struct iocblk *iocp; 1341 enum ioc_reply status; 1342 boolean_t need_privilege; 1343 1344 /* 1345 * If suspended, we might actually be able to do some of 1346 * these ioctls, but it is harder to make sure they occur 1347 * without actually putting the hardware in an undesireable 1348 * state. So just NAK it. 1349 */ 1350 mutex_enter(ngep->genlock); 1351 if (ngep->suspended) { 1352 miocnak(wq, mp, 0, EINVAL); 1353 mutex_exit(ngep->genlock); 1354 return; 1355 } 1356 mutex_exit(ngep->genlock); 1357 1358 /* 1359 * Validate the command before bothering with the mutex ... 1360 */ 1361 iocp = (struct iocblk *)mp->b_rptr; 1362 iocp->ioc_error = 0; 1363 need_privilege = B_TRUE; 1364 cmd = iocp->ioc_cmd; 1365 1366 NGE_DEBUG(("nge_m_ioctl: cmd 0x%x", cmd)); 1367 switch (cmd) { 1368 default: 1369 NGE_LDB(NGE_DBG_BADIOC, 1370 ("nge_m_ioctl: unknown cmd 0x%x", cmd)); 1371 1372 miocnak(wq, mp, 0, EINVAL); 1373 return; 1374 1375 case NGE_MII_READ: 1376 case NGE_MII_WRITE: 1377 case NGE_SEE_READ: 1378 case NGE_SEE_WRITE: 1379 case NGE_DIAG: 1380 case NGE_PEEK: 1381 case NGE_POKE: 1382 case NGE_PHY_RESET: 1383 case NGE_SOFT_RESET: 1384 case NGE_HARD_RESET: 1385 break; 1386 1387 case LB_GET_INFO_SIZE: 1388 case LB_GET_INFO: 1389 case LB_GET_MODE: 1390 need_privilege = B_FALSE; 1391 break; 1392 case LB_SET_MODE: 1393 break; 1394 1395 case ND_GET: 1396 need_privilege = B_FALSE; 1397 break; 1398 case ND_SET: 1399 break; 1400 } 1401 1402 if (need_privilege) { 1403 /* 1404 * Check for specific net_config privilege. 1405 */ 1406 err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 1407 if (err != 0) { 1408 NGE_DEBUG(("nge_m_ioctl: rejected cmd 0x%x, err %d", 1409 cmd, err)); 1410 miocnak(wq, mp, 0, err); 1411 return; 1412 } 1413 } 1414 1415 mutex_enter(ngep->genlock); 1416 1417 switch (cmd) { 1418 default: 1419 _NOTE(NOTREACHED) 1420 status = IOC_INVAL; 1421 break; 1422 1423 case NGE_MII_READ: 1424 case NGE_MII_WRITE: 1425 case NGE_SEE_READ: 1426 case NGE_SEE_WRITE: 1427 case NGE_DIAG: 1428 case NGE_PEEK: 1429 case NGE_POKE: 1430 case NGE_PHY_RESET: 1431 case NGE_SOFT_RESET: 1432 case NGE_HARD_RESET: 1433 status = nge_chip_ioctl(ngep, mp, iocp); 1434 break; 1435 1436 case LB_GET_INFO_SIZE: 1437 case LB_GET_INFO: 1438 case LB_GET_MODE: 1439 case LB_SET_MODE: 1440 status = nge_loop_ioctl(ngep, mp, iocp); 1441 break; 1442 1443 case ND_GET: 1444 case ND_SET: 1445 status = nge_nd_ioctl(ngep, wq, mp, iocp); 1446 break; 1447 1448 } 1449 1450 /* 1451 * Do we need to reprogram the PHY and/or the MAC? 1452 * Do it now, while we still have the mutex. 1453 * 1454 * Note: update the PHY first, 'cos it controls the 1455 * speed/duplex parameters that the MAC code uses. 1456 */ 1457 1458 NGE_DEBUG(("nge_m_ioctl: cmd 0x%x status %d", cmd, status)); 1459 1460 switch (status) { 1461 case IOC_RESTART_REPLY: 1462 case IOC_RESTART_ACK: 1463 (*ngep->physops->phys_update)(ngep); 1464 nge_chip_sync(ngep); 1465 break; 1466 1467 default: 1468 break; 1469 } 1470 1471 mutex_exit(ngep->genlock); 1472 1473 /* 1474 * Finally, decide how to reply 1475 */ 1476 switch (status) { 1477 1478 default: 1479 case IOC_INVAL: 1480 miocnak(wq, mp, 0, iocp->ioc_error == 0 ? 1481 EINVAL : iocp->ioc_error); 1482 break; 1483 1484 case IOC_DONE: 1485 break; 1486 1487 case IOC_RESTART_ACK: 1488 case IOC_ACK: 1489 miocack(wq, mp, 0, 0); 1490 break; 1491 1492 case IOC_RESTART_REPLY: 1493 case IOC_REPLY: 1494 mp->b_datap->db_type = iocp->ioc_error == 0 ? 1495 M_IOCACK : M_IOCNAK; 1496 qreply(wq, mp); 1497 break; 1498 } 1499 } 1500 1501 static boolean_t 1502 nge_param_locked(mac_prop_id_t pr_num) 1503 { 1504 /* 1505 * All adv_* parameters are locked (read-only) while 1506 * the device is in any sort of loopback mode ... 1507 */ 1508 switch (pr_num) { 1509 case DLD_PROP_ADV_1000FDX_CAP: 1510 case DLD_PROP_EN_1000FDX_CAP: 1511 case DLD_PROP_ADV_1000HDX_CAP: 1512 case DLD_PROP_EN_1000HDX_CAP: 1513 case DLD_PROP_ADV_100FDX_CAP: 1514 case DLD_PROP_EN_100FDX_CAP: 1515 case DLD_PROP_ADV_100HDX_CAP: 1516 case DLD_PROP_EN_100HDX_CAP: 1517 case DLD_PROP_ADV_10FDX_CAP: 1518 case DLD_PROP_EN_10FDX_CAP: 1519 case DLD_PROP_ADV_10HDX_CAP: 1520 case DLD_PROP_EN_10HDX_CAP: 1521 case DLD_PROP_AUTONEG: 1522 case DLD_PROP_FLOWCTRL: 1523 return (B_TRUE); 1524 } 1525 return (B_FALSE); 1526 } 1527 1528 /* 1529 * callback functions for set/get of properties 1530 */ 1531 static int 1532 nge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 1533 uint_t pr_valsize, const void *pr_val) 1534 { 1535 nge_t *ngep = barg; 1536 int err = 0; 1537 uint64_t cur_mtu, new_mtu; 1538 link_flowctrl_t fl; 1539 1540 mutex_enter(ngep->genlock); 1541 if (ngep->param_loop_mode != NGE_LOOP_NONE && 1542 nge_param_locked(pr_num)) { 1543 /* 1544 * All adv_* parameters are locked (read-only) 1545 * while the device is in any sort of loopback mode. 1546 */ 1547 mutex_exit(ngep->genlock); 1548 return (EBUSY); 1549 } 1550 switch (pr_num) { 1551 case DLD_PROP_EN_1000FDX_CAP: 1552 ngep->param_en_1000fdx = *(uint8_t *)pr_val; 1553 ngep->param_adv_1000fdx = *(uint8_t *)pr_val; 1554 goto reprogram; 1555 case DLD_PROP_EN_1000HDX_CAP: 1556 ngep->param_en_1000hdx = *(uint8_t *)pr_val; 1557 ngep->param_adv_1000hdx = *(uint8_t *)pr_val; 1558 goto reprogram; 1559 case DLD_PROP_EN_100FDX_CAP: 1560 ngep->param_en_100fdx = *(uint8_t *)pr_val; 1561 ngep->param_adv_100fdx = *(uint8_t *)pr_val; 1562 goto reprogram; 1563 case DLD_PROP_EN_100HDX_CAP: 1564 ngep->param_en_100hdx = *(uint8_t *)pr_val; 1565 ngep->param_adv_100hdx = *(uint8_t *)pr_val; 1566 goto reprogram; 1567 case DLD_PROP_EN_10FDX_CAP: 1568 ngep->param_en_10fdx = *(uint8_t *)pr_val; 1569 ngep->param_adv_10fdx = *(uint8_t *)pr_val; 1570 goto reprogram; 1571 case DLD_PROP_EN_10HDX_CAP: 1572 ngep->param_en_10hdx = *(uint8_t *)pr_val; 1573 ngep->param_adv_10hdx = *(uint8_t *)pr_val; 1574 reprogram: 1575 (*ngep->physops->phys_update)(ngep); 1576 nge_chip_sync(ngep); 1577 break; 1578 1579 case DLD_PROP_ADV_1000FDX_CAP: 1580 case DLD_PROP_ADV_1000HDX_CAP: 1581 case DLD_PROP_ADV_100FDX_CAP: 1582 case DLD_PROP_ADV_100HDX_CAP: 1583 case DLD_PROP_ADV_10FDX_CAP: 1584 case DLD_PROP_ADV_10HDX_CAP: 1585 case DLD_PROP_STATUS: 1586 case DLD_PROP_SPEED: 1587 case DLD_PROP_DUPLEX: 1588 err = ENOTSUP; /* read-only prop. Can't set this */ 1589 break; 1590 case DLD_PROP_AUTONEG: 1591 ngep->param_adv_autoneg = *(uint8_t *)pr_val; 1592 (*ngep->physops->phys_update)(ngep); 1593 nge_chip_sync(ngep); 1594 break; 1595 case DLD_PROP_DEFMTU: 1596 cur_mtu = ngep->default_mtu; 1597 bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 1598 if (new_mtu == cur_mtu) { 1599 err = 0; 1600 break; 1601 } 1602 if (new_mtu < ETHERMTU || 1603 new_mtu > NGE_MAX_MTU) { 1604 err = EINVAL; 1605 break; 1606 } 1607 if ((new_mtu > ETHERMTU) && 1608 (!ngep->dev_spec_param.jumbo)) { 1609 err = EINVAL; 1610 break; 1611 } 1612 if (ngep->nge_mac_state == NGE_MAC_STARTED) { 1613 err = EBUSY; 1614 break; 1615 } 1616 1617 ngep->default_mtu = new_mtu; 1618 if (ngep->default_mtu > ETHERMTU && 1619 ngep->default_mtu <= NGE_MTU_2500) { 1620 ngep->buf_size = NGE_JB2500_BUFSZ; 1621 ngep->tx_desc = NGE_SEND_JB2500_SLOTS_DESC; 1622 ngep->rx_desc = NGE_RECV_JB2500_SLOTS_DESC; 1623 ngep->rx_buf = NGE_RECV_JB2500_SLOTS_DESC * 2; 1624 ngep->nge_split = NGE_SPLIT_256; 1625 } else if (ngep->default_mtu > NGE_MTU_2500 && 1626 ngep->default_mtu <= NGE_MTU_4500) { 1627 ngep->buf_size = NGE_JB4500_BUFSZ; 1628 ngep->tx_desc = NGE_SEND_JB4500_SLOTS_DESC; 1629 ngep->rx_desc = NGE_RECV_JB4500_SLOTS_DESC; 1630 ngep->rx_buf = NGE_RECV_JB4500_SLOTS_DESC * 2; 1631 ngep->nge_split = NGE_SPLIT_256; 1632 } else if (ngep->default_mtu > NGE_MTU_4500 && 1633 ngep->default_mtu <= NGE_MAX_MTU) { 1634 ngep->buf_size = NGE_JB9000_BUFSZ; 1635 ngep->tx_desc = NGE_SEND_JB9000_SLOTS_DESC; 1636 ngep->rx_desc = NGE_RECV_JB9000_SLOTS_DESC; 1637 ngep->rx_buf = NGE_RECV_JB9000_SLOTS_DESC * 2; 1638 ngep->nge_split = NGE_SPLIT_256; 1639 } else if (ngep->default_mtu > NGE_MAX_MTU) { 1640 ngep->default_mtu = NGE_MAX_MTU; 1641 ngep->buf_size = NGE_JB9000_BUFSZ; 1642 ngep->tx_desc = NGE_SEND_JB9000_SLOTS_DESC; 1643 ngep->rx_desc = NGE_RECV_JB9000_SLOTS_DESC; 1644 ngep->rx_buf = NGE_RECV_JB9000_SLOTS_DESC * 2; 1645 ngep->nge_split = NGE_SPLIT_256; 1646 } else if (ngep->lowmem_mode != 0) { 1647 ngep->default_mtu = ETHERMTU; 1648 ngep->buf_size = NGE_STD_BUFSZ; 1649 ngep->tx_desc = NGE_SEND_LOWMEM_SLOTS_DESC; 1650 ngep->rx_desc = NGE_RECV_LOWMEM_SLOTS_DESC; 1651 ngep->rx_buf = NGE_RECV_LOWMEM_SLOTS_DESC * 2; 1652 ngep->nge_split = NGE_SPLIT_32; 1653 } else { 1654 ngep->default_mtu = ETHERMTU; 1655 ngep->buf_size = NGE_STD_BUFSZ; 1656 ngep->tx_desc = 1657 ngep->dev_spec_param.tx_desc_num; 1658 ngep->rx_desc = 1659 ngep->dev_spec_param.rx_desc_num; 1660 ngep->rx_buf = 1661 ngep->dev_spec_param.rx_desc_num * 2; 1662 ngep->nge_split = 1663 ngep->dev_spec_param.nge_split; 1664 } 1665 1666 err = mac_maxsdu_update(ngep->mh, ngep->default_mtu); 1667 1668 break; 1669 case DLD_PROP_FLOWCTRL: 1670 bcopy(pr_val, &fl, sizeof (fl)); 1671 switch (fl) { 1672 default: 1673 err = ENOTSUP; 1674 break; 1675 case LINK_FLOWCTRL_NONE: 1676 ngep->param_adv_pause = 0; 1677 ngep->param_adv_asym_pause = 0; 1678 1679 ngep->param_link_rx_pause = B_FALSE; 1680 ngep->param_link_tx_pause = B_FALSE; 1681 break; 1682 case LINK_FLOWCTRL_RX: 1683 if (!((ngep->param_lp_pause == 0) && 1684 (ngep->param_lp_asym_pause == 1))) { 1685 err = EINVAL; 1686 break; 1687 } 1688 ngep->param_adv_pause = 1; 1689 ngep->param_adv_asym_pause = 1; 1690 1691 ngep->param_link_rx_pause = B_TRUE; 1692 ngep->param_link_tx_pause = B_FALSE; 1693 break; 1694 case LINK_FLOWCTRL_TX: 1695 if (!((ngep->param_lp_pause == 1) && 1696 (ngep->param_lp_asym_pause == 1))) { 1697 err = EINVAL; 1698 break; 1699 } 1700 ngep->param_adv_pause = 0; 1701 ngep->param_adv_asym_pause = 1; 1702 1703 ngep->param_link_rx_pause = B_FALSE; 1704 ngep->param_link_tx_pause = B_TRUE; 1705 break; 1706 case LINK_FLOWCTRL_BI: 1707 if (ngep->param_lp_pause != 1) { 1708 err = EINVAL; 1709 break; 1710 } 1711 ngep->param_adv_pause = 1; 1712 1713 ngep->param_link_rx_pause = B_TRUE; 1714 ngep->param_link_tx_pause = B_TRUE; 1715 break; 1716 } 1717 1718 if (err == 0) { 1719 (*ngep->physops->phys_update)(ngep); 1720 nge_chip_sync(ngep); 1721 } 1722 1723 break; 1724 case DLD_PROP_PRIVATE: 1725 err = nge_set_priv_prop(ngep, pr_name, pr_valsize, 1726 pr_val); 1727 if (err == 0) { 1728 (*ngep->physops->phys_update)(ngep); 1729 nge_chip_sync(ngep); 1730 } 1731 break; 1732 default: 1733 err = ENOTSUP; 1734 } 1735 mutex_exit(ngep->genlock); 1736 return (err); 1737 } 1738 1739 static int 1740 nge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 1741 uint_t pr_valsize, void *pr_val) 1742 { 1743 nge_t *ngep = barg; 1744 int err = EINVAL; 1745 link_flowctrl_t fl; 1746 uint64_t tmp = 0; 1747 1748 bzero(pr_val, pr_valsize); 1749 switch (pr_num) { 1750 case DLD_PROP_DUPLEX: 1751 if (pr_valsize >= sizeof (uint8_t)) { 1752 *(uint8_t *)pr_val = ngep->param_link_duplex; 1753 err = 0; 1754 } 1755 break; 1756 case DLD_PROP_SPEED: 1757 if (pr_valsize >= sizeof (uint64_t)) { 1758 tmp = ngep->param_link_speed * 1000000ull; 1759 bcopy(&tmp, pr_val, sizeof (tmp)); 1760 err = 0; 1761 } 1762 break; 1763 case DLD_PROP_STATUS: 1764 if (pr_valsize >= sizeof (uint8_t)) { 1765 *(uint8_t *)pr_val = ngep->param_link_up; 1766 err = 0; 1767 } 1768 break; 1769 case DLD_PROP_AUTONEG: 1770 if (pr_valsize >= sizeof (uint8_t)) { 1771 *(uint8_t *)pr_val = ngep->param_adv_autoneg; 1772 err = 0; 1773 } 1774 break; 1775 case DLD_PROP_DEFMTU: { 1776 if (pr_valsize >= sizeof (uint64_t)) { 1777 tmp = ngep->default_mtu; 1778 bcopy(&tmp, pr_val, sizeof (tmp)); 1779 err = 0; 1780 } 1781 break; 1782 } 1783 case DLD_PROP_FLOWCTRL: 1784 if (pr_valsize >= sizeof (link_flowctrl_t)) { 1785 if (ngep->param_link_rx_pause && 1786 !ngep->param_link_tx_pause) 1787 fl = LINK_FLOWCTRL_RX; 1788 1789 if (!ngep->param_link_rx_pause && 1790 !ngep->param_link_tx_pause) 1791 fl = LINK_FLOWCTRL_NONE; 1792 1793 if (!ngep->param_link_rx_pause && 1794 ngep->param_link_tx_pause) 1795 fl = LINK_FLOWCTRL_TX; 1796 1797 if (ngep->param_link_rx_pause && 1798 ngep->param_link_tx_pause) 1799 fl = LINK_FLOWCTRL_BI; 1800 bcopy(&fl, pr_val, sizeof (fl)); 1801 err = 0; 1802 } 1803 break; 1804 case DLD_PROP_ADV_1000FDX_CAP: 1805 if (pr_valsize >= sizeof (uint8_t)) { 1806 *(uint8_t *)pr_val = ngep->param_adv_1000fdx; 1807 err = 0; 1808 } 1809 break; 1810 case DLD_PROP_EN_1000FDX_CAP: 1811 if (pr_valsize >= sizeof (uint8_t)) { 1812 *(uint8_t *)pr_val = ngep->param_en_1000fdx; 1813 err = 0; 1814 } 1815 break; 1816 case DLD_PROP_ADV_1000HDX_CAP: 1817 if (pr_valsize >= sizeof (uint8_t)) { 1818 *(uint8_t *)pr_val = ngep->param_adv_1000hdx; 1819 err = 0; 1820 } 1821 break; 1822 case DLD_PROP_EN_1000HDX_CAP: 1823 if (pr_valsize >= sizeof (uint8_t)) { 1824 *(uint8_t *)pr_val = ngep->param_en_1000hdx; 1825 err = 0; 1826 } 1827 break; 1828 case DLD_PROP_ADV_100FDX_CAP: 1829 if (pr_valsize >= sizeof (uint8_t)) { 1830 *(uint8_t *)pr_val = ngep->param_adv_100fdx; 1831 err = 0; 1832 } 1833 break; 1834 case DLD_PROP_EN_100FDX_CAP: 1835 if (pr_valsize >= sizeof (uint8_t)) { 1836 *(uint8_t *)pr_val = ngep->param_en_100fdx; 1837 err = 0; 1838 } 1839 break; 1840 case DLD_PROP_ADV_100HDX_CAP: 1841 if (pr_valsize >= sizeof (uint8_t)) { 1842 *(uint8_t *)pr_val = ngep->param_adv_100hdx; 1843 err = 0; 1844 } 1845 break; 1846 case DLD_PROP_EN_100HDX_CAP: 1847 if (pr_valsize >= sizeof (uint8_t)) { 1848 *(uint8_t *)pr_val = ngep->param_en_100hdx; 1849 err = 0; 1850 } 1851 break; 1852 case DLD_PROP_ADV_10FDX_CAP: 1853 if (pr_valsize >= sizeof (uint8_t)) { 1854 *(uint8_t *)pr_val = ngep->param_adv_10fdx; 1855 err = 0; 1856 } 1857 break; 1858 case DLD_PROP_EN_10FDX_CAP: 1859 if (pr_valsize >= sizeof (uint8_t)) { 1860 *(uint8_t *)pr_val = ngep->param_en_10fdx; 1861 err = 0; 1862 } 1863 break; 1864 case DLD_PROP_ADV_10HDX_CAP: 1865 if (pr_valsize >= sizeof (uint8_t)) { 1866 *(uint8_t *)pr_val = ngep->param_adv_10hdx; 1867 err = 0; 1868 } 1869 break; 1870 case DLD_PROP_EN_10HDX_CAP: 1871 if (pr_valsize >= sizeof (uint8_t)) { 1872 *(uint8_t *)pr_val = ngep->param_en_10hdx; 1873 err = 0; 1874 } 1875 break; 1876 case DLD_PROP_PRIVATE: 1877 err = nge_get_priv_prop(ngep, pr_name, pr_valsize, 1878 pr_val); 1879 break; 1880 default: 1881 err = ENOTSUP; 1882 } 1883 return (err); 1884 } 1885 1886 /* ARGSUSED */ 1887 static int 1888 nge_set_priv_prop(nge_t *ngep, const char *pr_name, uint_t pr_valsize, 1889 const void *pr_val) 1890 { 1891 int err = 0; 1892 long result; 1893 1894 if (strcmp(pr_name, "_tx_bcopy_threshold") == 0) { 1895 if (pr_val == NULL) { 1896 err = EINVAL; 1897 return (err); 1898 } 1899 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1900 if (result < 0 || result > NGE_MAX_SDU) { 1901 err = EINVAL; 1902 } else { 1903 ngep->param_txbcopy_threshold = (uint32_t)result; 1904 goto reprogram; 1905 } 1906 return (err); 1907 } 1908 if (strcmp(pr_name, "_rx_bcopy_threshold") == 0) { 1909 if (pr_val == NULL) { 1910 err = EINVAL; 1911 return (err); 1912 } 1913 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1914 if (result < 0 || result > NGE_MAX_SDU) { 1915 err = EINVAL; 1916 } else { 1917 ngep->param_rxbcopy_threshold = (uint32_t)result; 1918 goto reprogram; 1919 } 1920 return (err); 1921 } 1922 if (strcmp(pr_name, "_recv_max_packet") == 0) { 1923 if (pr_val == NULL) { 1924 err = EINVAL; 1925 return (err); 1926 } 1927 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1928 if (result < 0 || result > NGE_RECV_SLOTS_DESC_1024) { 1929 err = EINVAL; 1930 } else { 1931 ngep->param_recv_max_packet = (uint32_t)result; 1932 goto reprogram; 1933 } 1934 return (err); 1935 } 1936 if (strcmp(pr_name, "_poll_quiet_time") == 0) { 1937 if (pr_val == NULL) { 1938 err = EINVAL; 1939 return (err); 1940 } 1941 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1942 if (result < 0 || result > 10000) { 1943 err = EINVAL; 1944 } else { 1945 ngep->param_poll_quiet_time = (uint32_t)result; 1946 goto reprogram; 1947 } 1948 return (err); 1949 } 1950 if (strcmp(pr_name, "_poll_busy_time") == 0) { 1951 if (pr_val == NULL) { 1952 err = EINVAL; 1953 return (err); 1954 } 1955 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1956 if (result < 0 || result > 10000) { 1957 err = EINVAL; 1958 } else { 1959 ngep->param_poll_busy_time = (uint32_t)result; 1960 goto reprogram; 1961 } 1962 return (err); 1963 } 1964 if (strcmp(pr_name, "_rx_intr_hwater") == 0) { 1965 if (pr_val == NULL) { 1966 err = EINVAL; 1967 return (err); 1968 } 1969 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1970 if (result < 0 || result > PARAM_RECV_MAX_PACKET) { 1971 err = EINVAL; 1972 } else { 1973 ngep->param_rx_intr_hwater = (uint32_t)result; 1974 goto reprogram; 1975 } 1976 return (err); 1977 } 1978 if (strcmp(pr_name, "_rx_intr_lwater") == 0) { 1979 if (pr_val == NULL) { 1980 err = EINVAL; 1981 return (err); 1982 } 1983 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1984 if (result < 0 || result > PARAM_RECV_MAX_PACKET) { 1985 err = EINVAL; 1986 } else { 1987 ngep->param_rx_intr_lwater = (uint32_t)result; 1988 goto reprogram; 1989 } 1990 return (err); 1991 } 1992 if (strcmp(pr_name, "_tx_n_intr") == 0) { 1993 if (pr_val == NULL) { 1994 err = EINVAL; 1995 return (err); 1996 } 1997 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1998 if (result < 1 || result > 10000) { 1999 err = EINVAL; 2000 } else { 2001 ngep->param_tx_n_intr = (uint32_t)result; 2002 goto reprogram; 2003 } 2004 return (err); 2005 } 2006 2007 err = ENOTSUP; 2008 return (err); 2009 2010 reprogram: 2011 if (err == 0) { 2012 (*ngep->physops->phys_update)(ngep); 2013 nge_chip_sync(ngep); 2014 } 2015 2016 return (err); 2017 } 2018 2019 static int 2020 nge_get_priv_prop(nge_t *ngep, const char *pr_name, uint_t pr_valsize, 2021 void *pr_val) 2022 { 2023 char valstr[MAXNAMELEN]; 2024 int err = ENOTSUP; 2025 uint_t strsize; 2026 2027 if (strcmp(pr_name, "_tx_bcopy_threshold") == 0) { 2028 (void) sprintf(valstr, "%d", ngep->param_txbcopy_threshold); 2029 err = 0; 2030 goto done; 2031 } 2032 if (strcmp(pr_name, "_rx_bcopy_threshold") == 0) { 2033 (void) sprintf(valstr, "%d", ngep->param_rxbcopy_threshold); 2034 err = 0; 2035 goto done; 2036 } 2037 if (strcmp(pr_name, "_recv_max_packet") == 0) { 2038 (void) sprintf(valstr, "%d", ngep->param_recv_max_packet); 2039 err = 0; 2040 goto done; 2041 } 2042 if (strcmp(pr_name, "_poll_quiet_time") == 0) { 2043 (void) sprintf(valstr, "%d", ngep->param_poll_quiet_time); 2044 err = 0; 2045 goto done; 2046 } 2047 if (strcmp(pr_name, "_poll_busy_time") == 0) { 2048 (void) sprintf(valstr, "%d", ngep->param_poll_busy_time); 2049 err = 0; 2050 goto done; 2051 } 2052 if (strcmp(pr_name, "_rx_intr_hwater") == 0) { 2053 (void) sprintf(valstr, "%d", ngep->param_rx_intr_hwater); 2054 err = 0; 2055 goto done; 2056 } 2057 if (strcmp(pr_name, "_rx_intr_lwater") == 0) { 2058 (void) sprintf(valstr, "%d", ngep->param_rx_intr_lwater); 2059 err = 0; 2060 goto done; 2061 } 2062 if (strcmp(pr_name, "_tx_n_intr") == 0) { 2063 (void) sprintf(valstr, "%d", ngep->param_tx_n_intr); 2064 err = 0; 2065 goto done; 2066 } 2067 2068 done: 2069 if (err == 0) { 2070 strsize = (uint_t)strlen(valstr); 2071 if (pr_valsize < strsize) { 2072 err = ENOBUFS; 2073 } else { 2074 (void) strlcpy(pr_val, valstr, strsize); 2075 } 2076 } 2077 return (err); 2078 } 2079 2080 /* ARGSUSED */ 2081 static boolean_t 2082 nge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 2083 { 2084 nge_t *ngep = arg; 2085 nge_dev_spec_param_t *dev_param_p; 2086 2087 dev_param_p = &ngep->dev_spec_param; 2088 2089 switch (cap) { 2090 case MAC_CAPAB_HCKSUM: { 2091 uint32_t *hcksum_txflags = cap_data; 2092 2093 if (dev_param_p->tx_hw_checksum) { 2094 *hcksum_txflags = dev_param_p->tx_hw_checksum; 2095 } else 2096 return (B_FALSE); 2097 break; 2098 } 2099 case MAC_CAPAB_POLL: 2100 /* 2101 * There's nothing for us to fill in, simply returning 2102 * B_TRUE, stating that we support polling is sufficient. 2103 */ 2104 break; 2105 default: 2106 return (B_FALSE); 2107 } 2108 return (B_TRUE); 2109 } 2110 2111 #undef NGE_DBG 2112 #define NGE_DBG NGE_DBG_INIT /* debug flag for this code */ 2113 int 2114 nge_restart(nge_t *ngep) 2115 { 2116 int err = 0; 2117 err = nge_reset(ngep); 2118 if (!err) 2119 err = nge_chip_start(ngep); 2120 2121 if (err) { 2122 ngep->nge_mac_state = NGE_MAC_STOPPED; 2123 return (DDI_FAILURE); 2124 } else { 2125 ngep->nge_mac_state = NGE_MAC_STARTED; 2126 return (DDI_SUCCESS); 2127 } 2128 } 2129 2130 void 2131 nge_wake_factotum(nge_t *ngep) 2132 { 2133 mutex_enter(ngep->softlock); 2134 if (ngep->factotum_flag == 0) { 2135 ngep->factotum_flag = 1; 2136 (void) ddi_intr_trigger_softint(ngep->factotum_hdl, NULL); 2137 } 2138 mutex_exit(ngep->softlock); 2139 } 2140 2141 /* 2142 * High-level cyclic handler 2143 * 2144 * This routine schedules a (low-level) softint callback to the 2145 * factotum. 2146 */ 2147 2148 static void 2149 nge_chip_cyclic(void *arg) 2150 { 2151 nge_t *ngep; 2152 2153 ngep = (nge_t *)arg; 2154 2155 switch (ngep->nge_chip_state) { 2156 default: 2157 return; 2158 2159 case NGE_CHIP_RUNNING: 2160 break; 2161 2162 case NGE_CHIP_FAULT: 2163 case NGE_CHIP_ERROR: 2164 break; 2165 } 2166 2167 nge_wake_factotum(ngep); 2168 } 2169 2170 static void 2171 nge_unattach(nge_t *ngep) 2172 { 2173 send_ring_t *srp; 2174 buff_ring_t *brp; 2175 2176 srp = ngep->send; 2177 brp = ngep->buff; 2178 NGE_TRACE(("nge_unattach($%p)", (void *)ngep)); 2179 2180 /* 2181 * Flag that no more activity may be initiated 2182 */ 2183 ngep->progress &= ~PROGRESS_READY; 2184 ngep->nge_mac_state = NGE_MAC_UNATTACH; 2185 2186 /* 2187 * Quiesce the PHY and MAC (leave it reset but still powered). 2188 * Clean up and free all NGE data structures 2189 */ 2190 if (ngep->periodic_id != NULL) { 2191 ddi_periodic_delete(ngep->periodic_id); 2192 ngep->periodic_id = NULL; 2193 } 2194 2195 if (ngep->progress & PROGRESS_KSTATS) 2196 nge_fini_kstats(ngep); 2197 2198 if (ngep->progress & PROGRESS_NDD) 2199 nge_nd_cleanup(ngep); 2200 2201 if (ngep->progress & PROGRESS_HWINT) { 2202 mutex_enter(ngep->genlock); 2203 nge_restore_mac_addr(ngep); 2204 (void) nge_chip_stop(ngep, B_FALSE); 2205 mutex_exit(ngep->genlock); 2206 } 2207 2208 if (ngep->progress & PROGRESS_SWINT) 2209 nge_rem_intrs(ngep); 2210 2211 if (ngep->progress & PROGRESS_FACTOTUM) 2212 (void) ddi_intr_remove_softint(ngep->factotum_hdl); 2213 2214 if (ngep->progress & PROGRESS_RESCHED) 2215 (void) ddi_intr_remove_softint(ngep->resched_hdl); 2216 2217 if (ngep->progress & PROGRESS_INTR) { 2218 mutex_destroy(srp->tx_lock); 2219 mutex_destroy(srp->tc_lock); 2220 mutex_destroy(&srp->dmah_lock); 2221 mutex_destroy(brp->recycle_lock); 2222 2223 mutex_destroy(ngep->genlock); 2224 mutex_destroy(ngep->softlock); 2225 rw_destroy(ngep->rwlock); 2226 } 2227 2228 if (ngep->progress & PROGRESS_REGS) 2229 ddi_regs_map_free(&ngep->io_handle); 2230 2231 if (ngep->progress & PROGRESS_CFG) 2232 pci_config_teardown(&ngep->cfg_handle); 2233 2234 ddi_remove_minor_node(ngep->devinfo, NULL); 2235 2236 kmem_free(ngep, sizeof (*ngep)); 2237 } 2238 2239 static int 2240 nge_resume(dev_info_t *devinfo) 2241 { 2242 nge_t *ngep; 2243 chip_info_t *infop; 2244 int err; 2245 2246 ASSERT(devinfo != NULL); 2247 2248 ngep = ddi_get_driver_private(devinfo); 2249 err = 0; 2250 2251 /* 2252 * If there are state inconsistancies, this is bad. Returning 2253 * DDI_FAILURE here will eventually cause the machine to panic, 2254 * so it is best done here so that there is a possibility of 2255 * debugging the problem. 2256 */ 2257 if (ngep == NULL) 2258 cmn_err(CE_PANIC, 2259 "nge: ngep returned from ddi_get_driver_private was NULL"); 2260 infop = (chip_info_t *)&ngep->chipinfo; 2261 2262 if (ngep->devinfo != devinfo) 2263 cmn_err(CE_PANIC, 2264 "nge: passed devinfo not the same as saved devinfo"); 2265 2266 mutex_enter(ngep->genlock); 2267 rw_enter(ngep->rwlock, RW_WRITER); 2268 2269 /* 2270 * Fetch the config space. Even though we have most of it cached, 2271 * some values *might* change across a suspend/resume. 2272 */ 2273 nge_chip_cfg_init(ngep, infop, B_FALSE); 2274 2275 /* 2276 * Only in one case, this conditional branch can be executed: the port 2277 * hasn't been plumbed. 2278 */ 2279 if (ngep->suspended == B_FALSE) { 2280 rw_exit(ngep->rwlock); 2281 mutex_exit(ngep->genlock); 2282 return (DDI_SUCCESS); 2283 } 2284 2285 nge_tx_recycle_all(ngep); 2286 err = nge_reinit_ring(ngep); 2287 if (!err) { 2288 err = nge_chip_reset(ngep); 2289 if (!err) 2290 err = nge_chip_start(ngep); 2291 } 2292 2293 if (err) { 2294 /* 2295 * We note the failure, but return success, as the 2296 * system is still usable without this controller. 2297 */ 2298 cmn_err(CE_WARN, "nge: resume: failed to restart controller"); 2299 } else { 2300 ngep->nge_mac_state = NGE_MAC_STARTED; 2301 } 2302 ngep->suspended = B_FALSE; 2303 2304 rw_exit(ngep->rwlock); 2305 mutex_exit(ngep->genlock); 2306 2307 return (DDI_SUCCESS); 2308 } 2309 2310 /* 2311 * attach(9E) -- Attach a device to the system 2312 * 2313 * Called once for each board successfully probed. 2314 */ 2315 static int 2316 nge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 2317 { 2318 int err; 2319 int i; 2320 int instance; 2321 caddr_t regs; 2322 nge_t *ngep; 2323 chip_info_t *infop; 2324 mac_register_t *macp; 2325 2326 switch (cmd) { 2327 default: 2328 return (DDI_FAILURE); 2329 2330 case DDI_RESUME: 2331 return (nge_resume(devinfo)); 2332 2333 case DDI_ATTACH: 2334 break; 2335 } 2336 2337 ngep = kmem_zalloc(sizeof (*ngep), KM_SLEEP); 2338 instance = ddi_get_instance(devinfo); 2339 ddi_set_driver_private(devinfo, ngep); 2340 ngep->devinfo = devinfo; 2341 2342 (void) snprintf(ngep->ifname, sizeof (ngep->ifname), "%s%d", 2343 NGE_DRIVER_NAME, instance); 2344 err = pci_config_setup(devinfo, &ngep->cfg_handle); 2345 if (err != DDI_SUCCESS) { 2346 nge_problem(ngep, "nge_attach: pci_config_setup() failed"); 2347 goto attach_fail; 2348 } 2349 infop = (chip_info_t *)&ngep->chipinfo; 2350 nge_chip_cfg_init(ngep, infop, B_FALSE); 2351 nge_init_dev_spec_param(ngep); 2352 nge_get_props(ngep); 2353 ngep->progress |= PROGRESS_CFG; 2354 2355 err = ddi_regs_map_setup(devinfo, NGE_PCI_OPREGS_RNUMBER, 2356 ®s, 0, 0, &nge_reg_accattr, &ngep->io_handle); 2357 if (err != DDI_SUCCESS) { 2358 nge_problem(ngep, "nge_attach: ddi_regs_map_setup() failed"); 2359 goto attach_fail; 2360 } 2361 ngep->io_regs = regs; 2362 ngep->progress |= PROGRESS_REGS; 2363 2364 err = nge_register_intrs_and_init_locks(ngep); 2365 if (err != DDI_SUCCESS) { 2366 nge_problem(ngep, "nge_attach:" 2367 " register intrs and init locks failed"); 2368 goto attach_fail; 2369 } 2370 nge_init_ring_param_lock(ngep); 2371 ngep->progress |= PROGRESS_INTR; 2372 2373 mutex_enter(ngep->genlock); 2374 2375 /* 2376 * Initialise link state variables 2377 * Stop, reset & reinitialise the chip. 2378 * Initialise the (internal) PHY. 2379 */ 2380 nge_phys_init(ngep); 2381 err = nge_chip_reset(ngep); 2382 if (err != DDI_SUCCESS) { 2383 nge_problem(ngep, "nge_attach: nge_chip_reset() failed"); 2384 mutex_exit(ngep->genlock); 2385 goto attach_fail; 2386 } 2387 nge_chip_sync(ngep); 2388 2389 /* 2390 * Now that mutex locks are initialized, enable interrupts. 2391 */ 2392 if (ngep->intr_cap & DDI_INTR_FLAG_BLOCK) { 2393 /* Call ddi_intr_block_enable() for MSI interrupts */ 2394 (void) ddi_intr_block_enable(ngep->htable, 2395 ngep->intr_actual_cnt); 2396 } else { 2397 /* Call ddi_intr_enable for MSI or FIXED interrupts */ 2398 for (i = 0; i < ngep->intr_actual_cnt; i++) { 2399 (void) ddi_intr_enable(ngep->htable[i]); 2400 } 2401 } 2402 2403 ngep->link_state = LINK_STATE_UNKNOWN; 2404 ngep->progress |= PROGRESS_HWINT; 2405 2406 /* 2407 * Register NDD-tweakable parameters 2408 */ 2409 if (nge_nd_init(ngep)) { 2410 nge_problem(ngep, "nge_attach: nge_nd_init() failed"); 2411 mutex_exit(ngep->genlock); 2412 goto attach_fail; 2413 } 2414 ngep->progress |= PROGRESS_NDD; 2415 2416 /* 2417 * Create & initialise named kstats 2418 */ 2419 nge_init_kstats(ngep, instance); 2420 ngep->progress |= PROGRESS_KSTATS; 2421 2422 mutex_exit(ngep->genlock); 2423 2424 if ((macp = mac_alloc(MAC_VERSION)) == NULL) 2425 goto attach_fail; 2426 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 2427 macp->m_driver = ngep; 2428 macp->m_dip = devinfo; 2429 macp->m_src_addr = infop->vendor_addr.addr; 2430 macp->m_callbacks = &nge_m_callbacks; 2431 macp->m_min_sdu = 0; 2432 macp->m_max_sdu = ngep->default_mtu; 2433 macp->m_margin = VTAG_SIZE; 2434 /* 2435 * Finally, we're ready to register ourselves with the mac 2436 * interface; if this succeeds, we're all ready to start() 2437 */ 2438 err = mac_register(macp, &ngep->mh); 2439 mac_free(macp); 2440 if (err != 0) 2441 goto attach_fail; 2442 2443 /* 2444 * Register a periodical handler. 2445 * nge_chip_cyclic() is invoked in kernel context. 2446 */ 2447 ngep->periodic_id = ddi_periodic_add(nge_chip_cyclic, ngep, 2448 NGE_CYCLIC_PERIOD, DDI_IPL_0); 2449 2450 ngep->progress |= PROGRESS_READY; 2451 return (DDI_SUCCESS); 2452 2453 attach_fail: 2454 nge_unattach(ngep); 2455 return (DDI_FAILURE); 2456 } 2457 2458 static int 2459 nge_suspend(nge_t *ngep) 2460 { 2461 mutex_enter(ngep->genlock); 2462 rw_enter(ngep->rwlock, RW_WRITER); 2463 2464 /* if the port hasn't been plumbed, just return */ 2465 if (ngep->nge_mac_state != NGE_MAC_STARTED) { 2466 rw_exit(ngep->rwlock); 2467 mutex_exit(ngep->genlock); 2468 return (DDI_SUCCESS); 2469 } 2470 ngep->suspended = B_TRUE; 2471 (void) nge_chip_stop(ngep, B_FALSE); 2472 ngep->nge_mac_state = NGE_MAC_STOPPED; 2473 2474 rw_exit(ngep->rwlock); 2475 mutex_exit(ngep->genlock); 2476 return (DDI_SUCCESS); 2477 } 2478 2479 /* 2480 * detach(9E) -- Detach a device from the system 2481 */ 2482 static int 2483 nge_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 2484 { 2485 int i; 2486 nge_t *ngep; 2487 mul_item *p, *nextp; 2488 buff_ring_t *brp; 2489 2490 NGE_GTRACE(("nge_detach($%p, %d)", (void *)devinfo, cmd)); 2491 2492 ngep = ddi_get_driver_private(devinfo); 2493 brp = ngep->buff; 2494 2495 switch (cmd) { 2496 default: 2497 return (DDI_FAILURE); 2498 2499 case DDI_SUSPEND: 2500 /* 2501 * Stop the NIC 2502 * Note: This driver doesn't currently support WOL, but 2503 * should it in the future, it is important to 2504 * make sure the PHY remains powered so that the 2505 * wakeup packet can actually be recieved. 2506 */ 2507 return (nge_suspend(ngep)); 2508 2509 case DDI_DETACH: 2510 break; 2511 } 2512 2513 /* Try to wait all the buffer post to upper layer be released */ 2514 for (i = 0; i < 1000; i++) { 2515 if (brp->rx_hold == 0) 2516 break; 2517 drv_usecwait(1000); 2518 } 2519 2520 /* If there is any posted buffer, reject to detach */ 2521 if (brp->rx_hold != 0) 2522 return (DDI_FAILURE); 2523 2524 /* Recycle the multicast table */ 2525 for (p = ngep->pcur_mulist; p != NULL; p = nextp) { 2526 nextp = p->next; 2527 kmem_free(p, sizeof (mul_item)); 2528 } 2529 ngep->pcur_mulist = NULL; 2530 2531 /* 2532 * Unregister from the GLD subsystem. This can fail, in 2533 * particular if there are DLPI style-2 streams still open - 2534 * in which case we just return failure without shutting 2535 * down chip operations. 2536 */ 2537 if (mac_unregister(ngep->mh) != DDI_SUCCESS) 2538 return (DDI_FAILURE); 2539 2540 /* 2541 * All activity stopped, so we can clean up & exit 2542 */ 2543 nge_unattach(ngep); 2544 return (DDI_SUCCESS); 2545 } 2546 2547 2548 /* 2549 * ========== Module Loading Data & Entry Points ========== 2550 */ 2551 2552 DDI_DEFINE_STREAM_OPS(nge_dev_ops, nulldev, nulldev, nge_attach, nge_detach, 2553 nodev, NULL, D_MP, NULL); 2554 2555 2556 static struct modldrv nge_modldrv = { 2557 &mod_driverops, /* Type of module. This one is a driver */ 2558 nge_ident, /* short description */ 2559 &nge_dev_ops /* driver specific ops */ 2560 }; 2561 2562 static struct modlinkage modlinkage = { 2563 MODREV_1, (void *)&nge_modldrv, NULL 2564 }; 2565 2566 2567 int 2568 _info(struct modinfo *modinfop) 2569 { 2570 return (mod_info(&modlinkage, modinfop)); 2571 } 2572 2573 int 2574 _init(void) 2575 { 2576 int status; 2577 2578 mac_init_ops(&nge_dev_ops, "nge"); 2579 status = mod_install(&modlinkage); 2580 if (status != DDI_SUCCESS) 2581 mac_fini_ops(&nge_dev_ops); 2582 else 2583 mutex_init(nge_log_mutex, NULL, MUTEX_DRIVER, NULL); 2584 2585 return (status); 2586 } 2587 2588 int 2589 _fini(void) 2590 { 2591 int status; 2592 2593 status = mod_remove(&modlinkage); 2594 if (status == DDI_SUCCESS) { 2595 mac_fini_ops(&nge_dev_ops); 2596 mutex_destroy(nge_log_mutex); 2597 } 2598 2599 return (status); 2600 } 2601 2602 /* 2603 * ============ Init MSI/Fixed/SoftInterrupt routines ============== 2604 */ 2605 2606 /* 2607 * Register interrupts and initialize each mutex and condition variables 2608 */ 2609 2610 static int 2611 nge_register_intrs_and_init_locks(nge_t *ngep) 2612 { 2613 int err; 2614 int intr_types; 2615 uint_t soft_prip; 2616 nge_msi_mask msi_mask; 2617 nge_msi_map0_vec map0_vec; 2618 nge_msi_map1_vec map1_vec; 2619 2620 /* 2621 * Add the softint handlers: 2622 * 2623 * Both of these handlers are used to avoid restrictions on the 2624 * context and/or mutexes required for some operations. In 2625 * particular, the hardware interrupt handler and its subfunctions 2626 * can detect a number of conditions that we don't want to handle 2627 * in that context or with that set of mutexes held. So, these 2628 * softints are triggered instead: 2629 * 2630 * the <resched> softint is triggered if if we have previously 2631 * had to refuse to send a packet because of resource shortage 2632 * (we've run out of transmit buffers), but the send completion 2633 * interrupt handler has now detected that more buffers have 2634 * become available. Its only purpose is to call gld_sched() 2635 * to retry the pending transmits (we're not allowed to hold 2636 * driver-defined mutexes across gld_sched()). 2637 * 2638 * the <factotum> is triggered if the h/w interrupt handler 2639 * sees the <link state changed> or <error> bits in the status 2640 * block. It's also triggered periodically to poll the link 2641 * state, just in case we aren't getting link status change 2642 * interrupts ... 2643 */ 2644 err = ddi_intr_add_softint(ngep->devinfo, &ngep->resched_hdl, 2645 DDI_INTR_SOFTPRI_MIN, nge_reschedule, (caddr_t)ngep); 2646 if (err != DDI_SUCCESS) { 2647 nge_problem(ngep, 2648 "nge_attach: add nge_reschedule softintr failed"); 2649 2650 return (DDI_FAILURE); 2651 } 2652 ngep->progress |= PROGRESS_RESCHED; 2653 err = ddi_intr_add_softint(ngep->devinfo, &ngep->factotum_hdl, 2654 DDI_INTR_SOFTPRI_MIN, nge_chip_factotum, (caddr_t)ngep); 2655 if (err != DDI_SUCCESS) { 2656 nge_problem(ngep, 2657 "nge_attach: add nge_chip_factotum softintr failed!"); 2658 2659 return (DDI_FAILURE); 2660 } 2661 if (ddi_intr_get_softint_pri(ngep->factotum_hdl, &soft_prip) 2662 != DDI_SUCCESS) { 2663 nge_problem(ngep, "nge_attach: get softintr priority failed\n"); 2664 2665 return (DDI_FAILURE); 2666 } 2667 ngep->soft_pri = soft_prip; 2668 2669 ngep->progress |= PROGRESS_FACTOTUM; 2670 /* Get supported interrupt types */ 2671 if (ddi_intr_get_supported_types(ngep->devinfo, &intr_types) 2672 != DDI_SUCCESS) { 2673 nge_error(ngep, "ddi_intr_get_supported_types failed\n"); 2674 2675 return (DDI_FAILURE); 2676 } 2677 2678 NGE_DEBUG(("ddi_intr_get_supported_types() returned: %x", 2679 intr_types)); 2680 2681 if ((intr_types & DDI_INTR_TYPE_MSI) && nge_enable_msi) { 2682 2683 /* MSI Configurations for mcp55 chipset */ 2684 if (ngep->chipinfo.device == DEVICE_ID_MCP55_373 || 2685 ngep->chipinfo.device == DEVICE_ID_MCP55_372) { 2686 2687 2688 /* Enable the 8 vectors */ 2689 msi_mask.msi_mask_val = 2690 nge_reg_get32(ngep, NGE_MSI_MASK); 2691 msi_mask.msi_msk_bits.vec0 = NGE_SET; 2692 msi_mask.msi_msk_bits.vec1 = NGE_SET; 2693 msi_mask.msi_msk_bits.vec2 = NGE_SET; 2694 msi_mask.msi_msk_bits.vec3 = NGE_SET; 2695 msi_mask.msi_msk_bits.vec4 = NGE_SET; 2696 msi_mask.msi_msk_bits.vec5 = NGE_SET; 2697 msi_mask.msi_msk_bits.vec6 = NGE_SET; 2698 msi_mask.msi_msk_bits.vec7 = NGE_SET; 2699 nge_reg_put32(ngep, NGE_MSI_MASK, 2700 msi_mask.msi_mask_val); 2701 2702 /* 2703 * Remapping the MSI MAP0 and MAP1. MCP55 2704 * is default mapping all the interrupt to 0 vector. 2705 * Software needs to remapping this. 2706 * This mapping is same as CK804. 2707 */ 2708 map0_vec.msi_map0_val = 2709 nge_reg_get32(ngep, NGE_MSI_MAP0); 2710 map1_vec.msi_map1_val = 2711 nge_reg_get32(ngep, NGE_MSI_MAP1); 2712 map0_vec.vecs_bits.reint_vec = 0; 2713 map0_vec.vecs_bits.rcint_vec = 0; 2714 map0_vec.vecs_bits.miss_vec = 3; 2715 map0_vec.vecs_bits.teint_vec = 5; 2716 map0_vec.vecs_bits.tcint_vec = 5; 2717 map0_vec.vecs_bits.stint_vec = 2; 2718 map0_vec.vecs_bits.mint_vec = 6; 2719 map0_vec.vecs_bits.rfint_vec = 0; 2720 map1_vec.vecs_bits.tfint_vec = 5; 2721 map1_vec.vecs_bits.feint_vec = 6; 2722 map1_vec.vecs_bits.resv8_11 = 3; 2723 map1_vec.vecs_bits.resv12_15 = 1; 2724 map1_vec.vecs_bits.resv16_19 = 0; 2725 map1_vec.vecs_bits.resv20_23 = 7; 2726 map1_vec.vecs_bits.resv24_31 = 0xff; 2727 nge_reg_put32(ngep, NGE_MSI_MAP0, 2728 map0_vec.msi_map0_val); 2729 nge_reg_put32(ngep, NGE_MSI_MAP1, 2730 map1_vec.msi_map1_val); 2731 } 2732 if (nge_add_intrs(ngep, DDI_INTR_TYPE_MSI) != DDI_SUCCESS) { 2733 NGE_DEBUG(("MSI registration failed, " 2734 "trying FIXED interrupt type\n")); 2735 } else { 2736 nge_log(ngep, "Using MSI interrupt type\n"); 2737 2738 ngep->intr_type = DDI_INTR_TYPE_MSI; 2739 ngep->progress |= PROGRESS_SWINT; 2740 } 2741 } 2742 2743 if (!(ngep->progress & PROGRESS_SWINT) && 2744 (intr_types & DDI_INTR_TYPE_FIXED)) { 2745 if (nge_add_intrs(ngep, DDI_INTR_TYPE_FIXED) != DDI_SUCCESS) { 2746 nge_error(ngep, "FIXED interrupt " 2747 "registration failed\n"); 2748 2749 return (DDI_FAILURE); 2750 } 2751 2752 nge_log(ngep, "Using FIXED interrupt type\n"); 2753 2754 ngep->intr_type = DDI_INTR_TYPE_FIXED; 2755 ngep->progress |= PROGRESS_SWINT; 2756 } 2757 2758 2759 if (!(ngep->progress & PROGRESS_SWINT)) { 2760 nge_error(ngep, "No interrupts registered\n"); 2761 2762 return (DDI_FAILURE); 2763 } 2764 mutex_init(ngep->genlock, NULL, MUTEX_DRIVER, 2765 DDI_INTR_PRI(ngep->intr_pri)); 2766 mutex_init(ngep->softlock, NULL, MUTEX_DRIVER, 2767 DDI_INTR_PRI(ngep->soft_pri)); 2768 rw_init(ngep->rwlock, NULL, RW_DRIVER, 2769 DDI_INTR_PRI(ngep->intr_pri)); 2770 2771 return (DDI_SUCCESS); 2772 } 2773 2774 /* 2775 * nge_add_intrs: 2776 * 2777 * Register FIXED or MSI interrupts. 2778 */ 2779 static int 2780 nge_add_intrs(nge_t *ngep, int intr_type) 2781 { 2782 dev_info_t *dip = ngep->devinfo; 2783 int avail, actual, intr_size, count = 0; 2784 int i, flag, ret; 2785 2786 NGE_DEBUG(("nge_add_intrs: interrupt type 0x%x\n", intr_type)); 2787 2788 /* Get number of interrupts */ 2789 ret = ddi_intr_get_nintrs(dip, intr_type, &count); 2790 if ((ret != DDI_SUCCESS) || (count == 0)) { 2791 nge_error(ngep, "ddi_intr_get_nintrs() failure, ret: %d, " 2792 "count: %d", ret, count); 2793 2794 return (DDI_FAILURE); 2795 } 2796 2797 /* Get number of available interrupts */ 2798 ret = ddi_intr_get_navail(dip, intr_type, &avail); 2799 if ((ret != DDI_SUCCESS) || (avail == 0)) { 2800 nge_error(ngep, "ddi_intr_get_navail() failure, " 2801 "ret: %d, avail: %d\n", ret, avail); 2802 2803 return (DDI_FAILURE); 2804 } 2805 2806 if (avail < count) { 2807 NGE_DEBUG(("nitrs() returned %d, navail returned %d\n", 2808 count, avail)); 2809 } 2810 flag = DDI_INTR_ALLOC_NORMAL; 2811 2812 /* Allocate an array of interrupt handles */ 2813 intr_size = count * sizeof (ddi_intr_handle_t); 2814 ngep->htable = kmem_alloc(intr_size, KM_SLEEP); 2815 2816 /* Call ddi_intr_alloc() */ 2817 ret = ddi_intr_alloc(dip, ngep->htable, intr_type, 0, 2818 count, &actual, flag); 2819 2820 if ((ret != DDI_SUCCESS) || (actual == 0)) { 2821 nge_error(ngep, "ddi_intr_alloc() failed %d\n", ret); 2822 2823 kmem_free(ngep->htable, intr_size); 2824 return (DDI_FAILURE); 2825 } 2826 2827 if (actual < count) { 2828 NGE_DEBUG(("Requested: %d, Received: %d\n", 2829 count, actual)); 2830 } 2831 2832 ngep->intr_actual_cnt = actual; 2833 ngep->intr_req_cnt = count; 2834 2835 /* 2836 * Get priority for first msi, assume remaining are all the same 2837 */ 2838 if ((ret = ddi_intr_get_pri(ngep->htable[0], &ngep->intr_pri)) != 2839 DDI_SUCCESS) { 2840 nge_error(ngep, "ddi_intr_get_pri() failed %d\n", ret); 2841 2842 /* Free already allocated intr */ 2843 for (i = 0; i < actual; i++) { 2844 (void) ddi_intr_free(ngep->htable[i]); 2845 } 2846 2847 kmem_free(ngep->htable, intr_size); 2848 2849 return (DDI_FAILURE); 2850 } 2851 /* Test for high level mutex */ 2852 if (ngep->intr_pri >= ddi_intr_get_hilevel_pri()) { 2853 nge_error(ngep, "nge_add_intrs:" 2854 "Hi level interrupt not supported"); 2855 2856 for (i = 0; i < actual; i++) 2857 (void) ddi_intr_free(ngep->htable[i]); 2858 2859 kmem_free(ngep->htable, intr_size); 2860 2861 return (DDI_FAILURE); 2862 } 2863 2864 2865 /* Call ddi_intr_add_handler() */ 2866 for (i = 0; i < actual; i++) { 2867 if ((ret = ddi_intr_add_handler(ngep->htable[i], nge_chip_intr, 2868 (caddr_t)ngep, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) { 2869 nge_error(ngep, "ddi_intr_add_handler() " 2870 "failed %d\n", ret); 2871 2872 /* Free already allocated intr */ 2873 for (i = 0; i < actual; i++) { 2874 (void) ddi_intr_free(ngep->htable[i]); 2875 } 2876 2877 kmem_free(ngep->htable, intr_size); 2878 2879 return (DDI_FAILURE); 2880 } 2881 } 2882 2883 if ((ret = ddi_intr_get_cap(ngep->htable[0], &ngep->intr_cap)) 2884 != DDI_SUCCESS) { 2885 nge_error(ngep, "ddi_intr_get_cap() failed %d\n", ret); 2886 2887 for (i = 0; i < actual; i++) { 2888 (void) ddi_intr_remove_handler(ngep->htable[i]); 2889 (void) ddi_intr_free(ngep->htable[i]); 2890 } 2891 2892 kmem_free(ngep->htable, intr_size); 2893 2894 return (DDI_FAILURE); 2895 } 2896 2897 return (DDI_SUCCESS); 2898 } 2899 2900 /* 2901 * nge_rem_intrs: 2902 * 2903 * Unregister FIXED or MSI interrupts 2904 */ 2905 static void 2906 nge_rem_intrs(nge_t *ngep) 2907 { 2908 int i; 2909 2910 NGE_DEBUG(("nge_rem_intrs\n")); 2911 2912 /* Disable all interrupts */ 2913 if (ngep->intr_cap & DDI_INTR_FLAG_BLOCK) { 2914 /* Call ddi_intr_block_disable() */ 2915 (void) ddi_intr_block_disable(ngep->htable, 2916 ngep->intr_actual_cnt); 2917 } else { 2918 for (i = 0; i < ngep->intr_actual_cnt; i++) { 2919 (void) ddi_intr_disable(ngep->htable[i]); 2920 } 2921 } 2922 2923 /* Call ddi_intr_remove_handler() */ 2924 for (i = 0; i < ngep->intr_actual_cnt; i++) { 2925 (void) ddi_intr_remove_handler(ngep->htable[i]); 2926 (void) ddi_intr_free(ngep->htable[i]); 2927 } 2928 2929 kmem_free(ngep->htable, 2930 ngep->intr_req_cnt * sizeof (ddi_intr_handle_t)); 2931 } 2932