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 2007 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 rx_data_hw[] = "rx-data-hw"; 162 static char rx_prd_lw[] = "rx-prd-lw"; 163 static char rx_prd_hw[] = "rx-prd-hw"; 164 static char sw_intr_intv[] = "sw-intr-intvl"; 165 static char nge_desc_mode[] = "desc-mode"; 166 static char default_mtu[] = "default_mtu"; 167 static char low_memory_mode[] = "minimal-memory-usage"; 168 extern kmutex_t nge_log_mutex[1]; 169 170 static int nge_m_start(void *); 171 static void nge_m_stop(void *); 172 static int nge_m_promisc(void *, boolean_t); 173 static int nge_m_multicst(void *, boolean_t, const uint8_t *); 174 static int nge_m_unicst(void *, const uint8_t *); 175 static void nge_m_resources(void *); 176 static void nge_m_ioctl(void *, queue_t *, mblk_t *); 177 static boolean_t nge_m_getcapab(void *, mac_capab_t, void *); 178 179 #define NGE_M_CALLBACK_FLAGS (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB) 180 181 static mac_callbacks_t nge_m_callbacks = { 182 NGE_M_CALLBACK_FLAGS, 183 nge_m_stat, 184 nge_m_start, 185 nge_m_stop, 186 nge_m_promisc, 187 nge_m_multicst, 188 nge_m_unicst, 189 nge_m_tx, 190 nge_m_resources, 191 nge_m_ioctl, 192 nge_m_getcapab 193 }; 194 195 static int nge_add_intrs(nge_t *, int); 196 static void nge_rem_intrs(nge_t *); 197 static int nge_register_intrs_and_init_locks(nge_t *); 198 199 /* 200 * NGE MSI tunable: 201 */ 202 boolean_t nge_enable_msi = B_FALSE; 203 204 static enum ioc_reply 205 nge_set_loop_mode(nge_t *ngep, uint32_t mode) 206 { 207 /* 208 * If the mode isn't being changed, there's nothing to do ... 209 */ 210 if (mode == ngep->param_loop_mode) 211 return (IOC_ACK); 212 213 /* 214 * Validate the requested mode and prepare a suitable message 215 * to explain the link down/up cycle that the change will 216 * probably induce ... 217 */ 218 switch (mode) { 219 default: 220 return (IOC_INVAL); 221 222 case NGE_LOOP_NONE: 223 case NGE_LOOP_EXTERNAL_100: 224 case NGE_LOOP_EXTERNAL_10: 225 case NGE_LOOP_INTERNAL_PHY: 226 break; 227 } 228 229 /* 230 * All OK; tell the caller to reprogram 231 * the PHY and/or MAC for the new mode ... 232 */ 233 ngep->param_loop_mode = mode; 234 return (IOC_RESTART_ACK); 235 } 236 237 #undef NGE_DBG 238 #define NGE_DBG NGE_DBG_INIT 239 240 /* 241 * Utility routine to carve a slice off a chunk of allocated memory, 242 * updating the chunk descriptor accordingly. The size of the slice 243 * is given by the product of the <qty> and <size> parameters. 244 */ 245 void 246 nge_slice_chunk(dma_area_t *slice, dma_area_t *chunk, 247 uint32_t qty, uint32_t size) 248 { 249 size_t totsize; 250 251 totsize = qty*size; 252 ASSERT(size > 0); 253 ASSERT(totsize <= chunk->alength); 254 255 *slice = *chunk; 256 slice->nslots = qty; 257 slice->size = size; 258 slice->alength = totsize; 259 260 chunk->mem_va = (caddr_t)chunk->mem_va + totsize; 261 chunk->alength -= totsize; 262 chunk->offset += totsize; 263 chunk->cookie.dmac_laddress += totsize; 264 chunk->cookie.dmac_size -= totsize; 265 } 266 267 /* 268 * Allocate an area of memory and a DMA handle for accessing it 269 */ 270 int 271 nge_alloc_dma_mem(nge_t *ngep, size_t memsize, ddi_device_acc_attr_t *attr_p, 272 uint_t dma_flags, dma_area_t *dma_p) 273 { 274 int err; 275 caddr_t va; 276 277 NGE_TRACE(("nge_alloc_dma_mem($%p, %ld, $%p, 0x%x, $%p)", 278 (void *)ngep, memsize, attr_p, dma_flags, dma_p)); 279 /* 280 * Allocate handle 281 */ 282 err = ddi_dma_alloc_handle(ngep->devinfo, ngep->desc_attr.dma_attr, 283 DDI_DMA_DONTWAIT, NULL, &dma_p->dma_hdl); 284 if (err != DDI_SUCCESS) 285 goto fail; 286 287 /* 288 * Allocate memory 289 */ 290 err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, attr_p, 291 dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING), 292 DDI_DMA_DONTWAIT, NULL, &va, &dma_p->alength, &dma_p->acc_hdl); 293 if (err != DDI_SUCCESS) 294 goto fail; 295 296 /* 297 * Bind the two together 298 */ 299 dma_p->mem_va = va; 300 err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL, 301 va, dma_p->alength, dma_flags, DDI_DMA_DONTWAIT, NULL, 302 &dma_p->cookie, &dma_p->ncookies); 303 304 if (err != DDI_DMA_MAPPED || dma_p->ncookies != 1) 305 goto fail; 306 307 dma_p->nslots = ~0U; 308 dma_p->size = ~0U; 309 dma_p->offset = 0; 310 311 return (DDI_SUCCESS); 312 313 fail: 314 nge_free_dma_mem(dma_p); 315 NGE_DEBUG(("nge_alloc_dma_mem: fail to alloc dma memory!")); 316 317 return (DDI_FAILURE); 318 } 319 320 /* 321 * Free one allocated area of DMAable memory 322 */ 323 void 324 nge_free_dma_mem(dma_area_t *dma_p) 325 { 326 if (dma_p->dma_hdl != NULL) { 327 if (dma_p->ncookies) { 328 (void) ddi_dma_unbind_handle(dma_p->dma_hdl); 329 dma_p->ncookies = 0; 330 } 331 } 332 if (dma_p->acc_hdl != NULL) { 333 ddi_dma_mem_free(&dma_p->acc_hdl); 334 dma_p->acc_hdl = NULL; 335 } 336 if (dma_p->dma_hdl != NULL) { 337 ddi_dma_free_handle(&dma_p->dma_hdl); 338 dma_p->dma_hdl = NULL; 339 } 340 } 341 342 #define ALLOC_TX_BUF 0x1 343 #define ALLOC_TX_DESC 0x2 344 #define ALLOC_RX_DESC 0x4 345 346 int 347 nge_alloc_bufs(nge_t *ngep) 348 { 349 int err; 350 int split; 351 int progress; 352 size_t txbuffsize; 353 size_t rxdescsize; 354 size_t txdescsize; 355 356 txbuffsize = ngep->tx_desc * ngep->buf_size; 357 rxdescsize = ngep->rx_desc; 358 txdescsize = ngep->tx_desc; 359 rxdescsize *= ngep->desc_attr.rxd_size; 360 txdescsize *= ngep->desc_attr.txd_size; 361 progress = 0; 362 363 NGE_TRACE(("nge_alloc_bufs($%p)", (void *)ngep)); 364 /* 365 * Allocate memory & handles for TX buffers 366 */ 367 ASSERT((txbuffsize % ngep->nge_split) == 0); 368 for (split = 0; split < ngep->nge_split; ++split) { 369 err = nge_alloc_dma_mem(ngep, txbuffsize/ngep->nge_split, 370 &nge_data_accattr, DDI_DMA_WRITE | NGE_DMA_MODE, 371 &ngep->send->buf[split]); 372 if (err != DDI_SUCCESS) 373 goto fail; 374 } 375 376 progress |= ALLOC_TX_BUF; 377 378 /* 379 * Allocate memory & handles for receive return rings and 380 * buffer (producer) descriptor rings 381 */ 382 err = nge_alloc_dma_mem(ngep, rxdescsize, &nge_desc_accattr, 383 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, &ngep->recv->desc); 384 if (err != DDI_SUCCESS) 385 goto fail; 386 progress |= ALLOC_RX_DESC; 387 388 /* 389 * Allocate memory & handles for TX descriptor rings, 390 */ 391 err = nge_alloc_dma_mem(ngep, txdescsize, &nge_desc_accattr, 392 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, &ngep->send->desc); 393 if (err != DDI_SUCCESS) 394 goto fail; 395 return (DDI_SUCCESS); 396 397 fail: 398 if (progress & ALLOC_RX_DESC) 399 nge_free_dma_mem(&ngep->recv->desc); 400 if (progress & ALLOC_TX_BUF) { 401 for (split = 0; split < ngep->nge_split; ++split) 402 nge_free_dma_mem(&ngep->send->buf[split]); 403 } 404 405 return (DDI_FAILURE); 406 } 407 408 /* 409 * This routine frees the transmit and receive buffers and descriptors. 410 * Make sure the chip is stopped before calling it! 411 */ 412 void 413 nge_free_bufs(nge_t *ngep) 414 { 415 int split; 416 417 NGE_TRACE(("nge_free_bufs($%p)", (void *)ngep)); 418 419 nge_free_dma_mem(&ngep->recv->desc); 420 nge_free_dma_mem(&ngep->send->desc); 421 422 for (split = 0; split < ngep->nge_split; ++split) 423 nge_free_dma_mem(&ngep->send->buf[split]); 424 } 425 426 /* 427 * Clean up initialisation done above before the memory is freed 428 */ 429 static void 430 nge_fini_send_ring(nge_t *ngep) 431 { 432 uint32_t slot; 433 size_t dmah_num; 434 send_ring_t *srp; 435 sw_tx_sbd_t *ssbdp; 436 437 srp = ngep->send; 438 ssbdp = srp->sw_sbds; 439 440 NGE_TRACE(("nge_fini_send_ring($%p)", (void *)ngep)); 441 442 dmah_num = sizeof (srp->dmahndl) / sizeof (srp->dmahndl[0]); 443 444 for (slot = 0; slot < dmah_num; ++slot) { 445 if (srp->dmahndl[slot].hndl) { 446 (void) ddi_dma_unbind_handle(srp->dmahndl[slot].hndl); 447 ddi_dma_free_handle(&srp->dmahndl[slot].hndl); 448 srp->dmahndl[slot].hndl = NULL; 449 srp->dmahndl[slot].next = NULL; 450 } 451 } 452 453 srp->dmah_free.head = NULL; 454 srp->dmah_free.tail = NULL; 455 456 kmem_free(ssbdp, srp->desc.nslots*sizeof (*ssbdp)); 457 458 } 459 460 /* 461 * Initialise the specified Send Ring, using the information in the 462 * <dma_area> descriptors that it contains to set up all the other 463 * fields. This routine should be called only once for each ring. 464 */ 465 static int 466 nge_init_send_ring(nge_t *ngep) 467 { 468 size_t dmah_num; 469 uint32_t nslots; 470 uint32_t err; 471 uint32_t slot; 472 uint32_t split; 473 send_ring_t *srp; 474 sw_tx_sbd_t *ssbdp; 475 dma_area_t desc; 476 dma_area_t pbuf; 477 478 srp = ngep->send; 479 srp->desc.nslots = ngep->tx_desc; 480 nslots = srp->desc.nslots; 481 482 NGE_TRACE(("nge_init_send_ring($%p)", (void *)ngep)); 483 /* 484 * Other one-off initialisation of per-ring data 485 */ 486 srp->ngep = ngep; 487 488 /* 489 * Allocate the array of s/w Send Buffer Descriptors 490 */ 491 ssbdp = kmem_zalloc(nslots*sizeof (*ssbdp), KM_SLEEP); 492 srp->sw_sbds = ssbdp; 493 494 /* 495 * Now initialise each array element once and for all 496 */ 497 desc = srp->desc; 498 for (split = 0; split < ngep->nge_split; ++split) { 499 pbuf = srp->buf[split]; 500 for (slot = 0; slot < nslots/ngep->nge_split; ++ssbdp, ++slot) { 501 nge_slice_chunk(&ssbdp->desc, &desc, 1, 502 ngep->desc_attr.txd_size); 503 nge_slice_chunk(&ssbdp->pbuf, &pbuf, 1, 504 ngep->buf_size); 505 } 506 ASSERT(pbuf.alength == 0); 507 } 508 ASSERT(desc.alength == 0); 509 510 dmah_num = sizeof (srp->dmahndl) / sizeof (srp->dmahndl[0]); 511 512 /* preallocate dma handles for tx buffer */ 513 for (slot = 0; slot < dmah_num; ++slot) { 514 515 err = ddi_dma_alloc_handle(ngep->devinfo, 516 ngep->desc_attr.tx_dma_attr, DDI_DMA_DONTWAIT, 517 NULL, &srp->dmahndl[slot].hndl); 518 519 if (err != DDI_SUCCESS) { 520 nge_fini_send_ring(ngep); 521 nge_error(ngep, 522 "nge_init_send_ring: alloc dma handle fails"); 523 return (DDI_FAILURE); 524 } 525 srp->dmahndl[slot].next = srp->dmahndl + slot + 1; 526 } 527 528 srp->dmah_free.head = srp->dmahndl; 529 srp->dmah_free.tail = srp->dmahndl + dmah_num - 1; 530 srp->dmah_free.tail->next = NULL; 531 532 return (DDI_SUCCESS); 533 } 534 535 /* 536 * Intialize the tx recycle pointer and tx sending pointer of tx ring 537 * and set the type of tx's data descriptor by default. 538 */ 539 static void 540 nge_reinit_send_ring(nge_t *ngep) 541 { 542 size_t dmah_num; 543 uint32_t slot; 544 send_ring_t *srp; 545 sw_tx_sbd_t *ssbdp; 546 547 srp = ngep->send; 548 549 /* 550 * Reinitialise control variables ... 551 */ 552 553 srp->tx_hwmark = NGE_DESC_MIN; 554 srp->tx_lwmark = NGE_DESC_MIN; 555 556 srp->tx_next = 0; 557 srp->tx_free = srp->desc.nslots; 558 srp->tc_next = 0; 559 560 dmah_num = sizeof (srp->dmahndl) / sizeof (srp->dmahndl[0]); 561 562 for (slot = 0; slot - dmah_num != 0; ++slot) 563 srp->dmahndl[slot].next = srp->dmahndl + slot + 1; 564 565 srp->dmah_free.head = srp->dmahndl; 566 srp->dmah_free.tail = srp->dmahndl + dmah_num - 1; 567 srp->dmah_free.tail->next = NULL; 568 569 /* 570 * Zero and sync all the h/w Send Buffer Descriptors 571 */ 572 for (slot = 0; slot < srp->desc.nslots; ++slot) { 573 ssbdp = &srp->sw_sbds[slot]; 574 ssbdp->flags = HOST_OWN; 575 } 576 577 DMA_ZERO(srp->desc); 578 DMA_SYNC(srp->desc, DDI_DMA_SYNC_FORDEV); 579 } 580 581 /* 582 * Initialize the slot number of rx's ring 583 */ 584 static void 585 nge_init_recv_ring(nge_t *ngep) 586 { 587 recv_ring_t *rrp; 588 589 rrp = ngep->recv; 590 rrp->desc.nslots = ngep->rx_desc; 591 rrp->ngep = ngep; 592 } 593 594 /* 595 * Intialize the rx recycle pointer and rx sending pointer of rx ring 596 */ 597 static void 598 nge_reinit_recv_ring(nge_t *ngep) 599 { 600 recv_ring_t *rrp; 601 602 rrp = ngep->recv; 603 604 /* 605 * Reinitialise control variables ... 606 */ 607 rrp->prod_index = 0; 608 /* 609 * Zero and sync all the h/w Send Buffer Descriptors 610 */ 611 DMA_ZERO(rrp->desc); 612 DMA_SYNC(rrp->desc, DDI_DMA_SYNC_FORDEV); 613 } 614 615 /* 616 * Clean up initialisation done above before the memory is freed 617 */ 618 static void 619 nge_fini_buff_ring(nge_t *ngep) 620 { 621 uint32_t i; 622 buff_ring_t *brp; 623 dma_area_t *bufp; 624 sw_rx_sbd_t *bsbdp; 625 626 brp = ngep->buff; 627 bsbdp = brp->sw_rbds; 628 629 NGE_DEBUG(("nge_fini_buff_ring($%p)", (void *)ngep)); 630 631 mutex_enter(brp->recycle_lock); 632 brp->buf_sign++; 633 mutex_exit(brp->recycle_lock); 634 for (i = 0; i < ngep->rx_desc; i++, ++bsbdp) { 635 if (bsbdp->bufp) { 636 if (bsbdp->bufp->mp) 637 freemsg(bsbdp->bufp->mp); 638 nge_free_dma_mem(bsbdp->bufp); 639 kmem_free(bsbdp->bufp, sizeof (dma_area_t)); 640 bsbdp->bufp = NULL; 641 } 642 } 643 while (brp->free_list != NULL) { 644 bufp = brp->free_list; 645 brp->free_list = bufp->next; 646 bufp->next = NULL; 647 if (bufp->mp) 648 freemsg(bufp->mp); 649 nge_free_dma_mem(bufp); 650 kmem_free(bufp, sizeof (dma_area_t)); 651 } 652 while (brp->recycle_list != NULL) { 653 bufp = brp->recycle_list; 654 brp->recycle_list = bufp->next; 655 bufp->next = NULL; 656 if (bufp->mp) 657 freemsg(bufp->mp); 658 nge_free_dma_mem(bufp); 659 kmem_free(bufp, sizeof (dma_area_t)); 660 } 661 662 663 kmem_free(brp->sw_rbds, (ngep->rx_desc * sizeof (*bsbdp))); 664 brp->sw_rbds = NULL; 665 } 666 667 /* 668 * Intialize the Rx's data ring and free ring 669 */ 670 static int 671 nge_init_buff_ring(nge_t *ngep) 672 { 673 uint32_t err; 674 uint32_t slot; 675 uint32_t nslots_buff; 676 uint32_t nslots_recv; 677 buff_ring_t *brp; 678 recv_ring_t *rrp; 679 dma_area_t desc; 680 dma_area_t *bufp; 681 sw_rx_sbd_t *bsbdp; 682 683 rrp = ngep->recv; 684 brp = ngep->buff; 685 brp->nslots = ngep->rx_buf; 686 brp->rx_bcopy = B_FALSE; 687 nslots_recv = rrp->desc.nslots; 688 nslots_buff = brp->nslots; 689 brp->ngep = ngep; 690 691 NGE_TRACE(("nge_init_buff_ring($%p)", (void *)ngep)); 692 693 /* 694 * Allocate the array of s/w Recv Buffer Descriptors 695 */ 696 bsbdp = kmem_zalloc(nslots_recv *sizeof (*bsbdp), KM_SLEEP); 697 brp->sw_rbds = bsbdp; 698 brp->free_list = NULL; 699 brp->recycle_list = NULL; 700 for (slot = 0; slot < nslots_buff; ++slot) { 701 bufp = kmem_zalloc(sizeof (dma_area_t), KM_SLEEP); 702 err = nge_alloc_dma_mem(ngep, (ngep->buf_size 703 + NGE_HEADROOM), 704 &nge_data_accattr, DDI_DMA_READ | NGE_DMA_MODE, bufp); 705 if (err != DDI_SUCCESS) { 706 kmem_free(bufp, sizeof (dma_area_t)); 707 return (DDI_FAILURE); 708 } 709 710 bufp->alength -= NGE_HEADROOM; 711 bufp->offset += NGE_HEADROOM; 712 bufp->private = (caddr_t)ngep; 713 bufp->rx_recycle.free_func = nge_recv_recycle; 714 bufp->rx_recycle.free_arg = (caddr_t)bufp; 715 bufp->signature = brp->buf_sign; 716 bufp->rx_delivered = B_FALSE; 717 bufp->mp = desballoc(DMA_VPTR(*bufp), 718 ngep->buf_size + NGE_HEADROOM, 719 0, &bufp->rx_recycle); 720 721 if (bufp->mp == NULL) { 722 return (DDI_FAILURE); 723 } 724 bufp->next = brp->free_list; 725 brp->free_list = bufp; 726 } 727 728 /* 729 * Now initialise each array element once and for all 730 */ 731 desc = rrp->desc; 732 for (slot = 0; slot < nslots_recv; ++slot, ++bsbdp) { 733 nge_slice_chunk(&bsbdp->desc, &desc, 1, 734 ngep->desc_attr.rxd_size); 735 bufp = brp->free_list; 736 brp->free_list = bufp->next; 737 bsbdp->bufp = bufp; 738 bsbdp->flags = CONTROLER_OWN; 739 bufp->next = NULL; 740 } 741 742 ASSERT(desc.alength == 0); 743 return (DDI_SUCCESS); 744 } 745 746 /* 747 * Fill the host address of data in rx' descriptor 748 * and initialize free pointers of rx free ring 749 */ 750 static int 751 nge_reinit_buff_ring(nge_t *ngep) 752 { 753 uint32_t slot; 754 uint32_t nslots_recv; 755 buff_ring_t *brp; 756 recv_ring_t *rrp; 757 sw_rx_sbd_t *bsbdp; 758 void *hw_bd_p; 759 760 brp = ngep->buff; 761 rrp = ngep->recv; 762 bsbdp = brp->sw_rbds; 763 nslots_recv = rrp->desc.nslots; 764 for (slot = 0; slot < nslots_recv; ++bsbdp, ++slot) { 765 hw_bd_p = DMA_VPTR(bsbdp->desc); 766 /* 767 * There is a scenario: When the traffic of small tcp 768 * packet is heavy, suspending the tcp traffic will 769 * cause the preallocated buffers for rx not to be 770 * released in time by tcp taffic and cause rx's buffer 771 * pointers not to be refilled in time. 772 * 773 * At this point, if we reinitialize the driver, the bufp 774 * pointer for rx's traffic will be NULL. 775 * So the result of the reinitializion fails. 776 */ 777 if (bsbdp->bufp == NULL) 778 return (DDI_FAILURE); 779 780 ngep->desc_attr.rxd_fill(hw_bd_p, &bsbdp->bufp->cookie, 781 bsbdp->bufp->alength); 782 } 783 return (DDI_SUCCESS); 784 } 785 786 static void 787 nge_init_ring_param_lock(nge_t *ngep) 788 { 789 buff_ring_t *brp; 790 send_ring_t *srp; 791 792 srp = ngep->send; 793 brp = ngep->buff; 794 795 /* Init the locks for send ring */ 796 mutex_init(srp->tx_lock, NULL, MUTEX_DRIVER, 797 DDI_INTR_PRI(ngep->intr_pri)); 798 mutex_init(srp->tc_lock, NULL, MUTEX_DRIVER, 799 DDI_INTR_PRI(ngep->intr_pri)); 800 mutex_init(&srp->dmah_lock, NULL, MUTEX_DRIVER, 801 DDI_INTR_PRI(ngep->intr_pri)); 802 803 /* Init parameters of buffer ring */ 804 brp->free_list = NULL; 805 brp->recycle_list = NULL; 806 brp->rx_hold = 0; 807 brp->buf_sign = 0; 808 809 /* Init recycle list lock */ 810 mutex_init(brp->recycle_lock, NULL, MUTEX_DRIVER, 811 DDI_INTR_PRI(ngep->intr_pri)); 812 } 813 814 int 815 nge_init_rings(nge_t *ngep) 816 { 817 uint32_t err; 818 819 err = nge_init_send_ring(ngep); 820 if (err != DDI_SUCCESS) { 821 return (err); 822 } 823 nge_init_recv_ring(ngep); 824 825 err = nge_init_buff_ring(ngep); 826 if (err != DDI_SUCCESS) { 827 nge_fini_send_ring(ngep); 828 return (DDI_FAILURE); 829 } 830 831 return (err); 832 } 833 834 static int 835 nge_reinit_ring(nge_t *ngep) 836 { 837 int err; 838 839 nge_reinit_recv_ring(ngep); 840 nge_reinit_send_ring(ngep); 841 err = nge_reinit_buff_ring(ngep); 842 return (err); 843 } 844 845 846 void 847 nge_fini_rings(nge_t *ngep) 848 { 849 /* 850 * For receive ring, nothing need to be finished. 851 * So only finish buffer ring and send ring here. 852 */ 853 nge_fini_buff_ring(ngep); 854 nge_fini_send_ring(ngep); 855 } 856 857 /* 858 * Loopback ioctl code 859 */ 860 861 static lb_property_t loopmodes[] = { 862 { normal, "normal", NGE_LOOP_NONE }, 863 { external, "100Mbps", NGE_LOOP_EXTERNAL_100 }, 864 { external, "10Mbps", NGE_LOOP_EXTERNAL_10 }, 865 { internal, "PHY", NGE_LOOP_INTERNAL_PHY }, 866 }; 867 868 enum ioc_reply 869 nge_loop_ioctl(nge_t *ngep, mblk_t *mp, struct iocblk *iocp) 870 { 871 int cmd; 872 uint32_t *lbmp; 873 lb_info_sz_t *lbsp; 874 lb_property_t *lbpp; 875 876 /* 877 * Validate format of ioctl 878 */ 879 if (mp->b_cont == NULL) 880 return (IOC_INVAL); 881 882 cmd = iocp->ioc_cmd; 883 884 switch (cmd) { 885 default: 886 return (IOC_INVAL); 887 888 case LB_GET_INFO_SIZE: 889 if (iocp->ioc_count != sizeof (lb_info_sz_t)) 890 return (IOC_INVAL); 891 lbsp = (lb_info_sz_t *)mp->b_cont->b_rptr; 892 *lbsp = sizeof (loopmodes); 893 return (IOC_REPLY); 894 895 case LB_GET_INFO: 896 if (iocp->ioc_count != sizeof (loopmodes)) 897 return (IOC_INVAL); 898 lbpp = (lb_property_t *)mp->b_cont->b_rptr; 899 bcopy(loopmodes, lbpp, sizeof (loopmodes)); 900 return (IOC_REPLY); 901 902 case LB_GET_MODE: 903 if (iocp->ioc_count != sizeof (uint32_t)) 904 return (IOC_INVAL); 905 lbmp = (uint32_t *)mp->b_cont->b_rptr; 906 *lbmp = ngep->param_loop_mode; 907 return (IOC_REPLY); 908 909 case LB_SET_MODE: 910 if (iocp->ioc_count != sizeof (uint32_t)) 911 return (IOC_INVAL); 912 lbmp = (uint32_t *)mp->b_cont->b_rptr; 913 return (nge_set_loop_mode(ngep, *lbmp)); 914 } 915 } 916 917 #undef NGE_DBG 918 #define NGE_DBG NGE_DBG_NEMO 919 920 921 static void 922 nge_check_desc_prop(nge_t *ngep) 923 { 924 if (ngep->desc_mode != DESC_HOT && ngep->desc_mode != DESC_OFFLOAD) 925 ngep->desc_mode = DESC_HOT; 926 927 if (ngep->desc_mode == DESC_OFFLOAD) { 928 929 ngep->desc_attr = nge_sum_desc; 930 931 } else if (ngep->desc_mode == DESC_HOT) { 932 933 ngep->desc_attr = nge_hot_desc; 934 } 935 } 936 937 /* 938 * nge_get_props -- get the parameters to tune the driver 939 */ 940 static void 941 nge_get_props(nge_t *ngep) 942 { 943 chip_info_t *infop; 944 dev_info_t *devinfo; 945 nge_dev_spec_param_t *dev_param_p; 946 947 devinfo = ngep->devinfo; 948 infop = (chip_info_t *)&ngep->chipinfo; 949 dev_param_p = &ngep->dev_spec_param; 950 951 infop->clsize = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 952 DDI_PROP_DONTPASS, clsize_propname, 32); 953 954 infop->latency = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 955 DDI_PROP_DONTPASS, latency_propname, 64); 956 ngep->rx_datahwm = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 957 DDI_PROP_DONTPASS, rx_data_hw, 0x20); 958 ngep->rx_prdlwm = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 959 DDI_PROP_DONTPASS, rx_prd_lw, 0x4); 960 ngep->rx_prdhwm = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 961 DDI_PROP_DONTPASS, rx_prd_hw, 0xc); 962 963 ngep->sw_intr_intv = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 964 DDI_PROP_DONTPASS, sw_intr_intv, SWTR_ITC); 965 ngep->debug = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 966 DDI_PROP_DONTPASS, debug_propname, NGE_DBG_CHIP); 967 ngep->desc_mode = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 968 DDI_PROP_DONTPASS, nge_desc_mode, dev_param_p->desc_type); 969 ngep->lowmem_mode = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 970 DDI_PROP_DONTPASS, low_memory_mode, 0); 971 972 if (dev_param_p->jumbo) { 973 ngep->default_mtu = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 974 DDI_PROP_DONTPASS, default_mtu, ETHERMTU); 975 } else 976 ngep->default_mtu = ETHERMTU; 977 978 if (ngep->default_mtu > ETHERMTU && 979 ngep->default_mtu <= NGE_MTU_2500) { 980 ngep->buf_size = NGE_JB2500_BUFSZ; 981 ngep->tx_desc = NGE_SEND_JB2500_SLOTS_DESC; 982 ngep->rx_desc = NGE_RECV_JB2500_SLOTS_DESC; 983 ngep->rx_buf = NGE_RECV_JB2500_SLOTS_DESC * 2; 984 ngep->nge_split = NGE_SPLIT_256; 985 } else if (ngep->default_mtu > NGE_MTU_2500 && 986 ngep->default_mtu <= NGE_MTU_4500) { 987 ngep->buf_size = NGE_JB4500_BUFSZ; 988 ngep->tx_desc = NGE_SEND_JB4500_SLOTS_DESC; 989 ngep->rx_desc = NGE_RECV_JB4500_SLOTS_DESC; 990 ngep->rx_buf = NGE_RECV_JB4500_SLOTS_DESC * 2; 991 ngep->nge_split = NGE_SPLIT_256; 992 } else if (ngep->default_mtu > NGE_MTU_4500 && 993 ngep->default_mtu <= NGE_MAX_MTU) { 994 ngep->buf_size = NGE_JB9000_BUFSZ; 995 ngep->tx_desc = NGE_SEND_JB9000_SLOTS_DESC; 996 ngep->rx_desc = NGE_RECV_JB9000_SLOTS_DESC; 997 ngep->rx_buf = NGE_RECV_JB9000_SLOTS_DESC * 2; 998 ngep->nge_split = NGE_SPLIT_256; 999 } else if (ngep->default_mtu > NGE_MAX_MTU) { 1000 ngep->default_mtu = NGE_MAX_MTU; 1001 ngep->buf_size = NGE_JB9000_BUFSZ; 1002 ngep->tx_desc = NGE_SEND_JB9000_SLOTS_DESC; 1003 ngep->rx_desc = NGE_RECV_JB9000_SLOTS_DESC; 1004 ngep->rx_buf = NGE_RECV_JB9000_SLOTS_DESC * 2; 1005 ngep->nge_split = NGE_SPLIT_256; 1006 } else if (ngep->lowmem_mode != 0) { 1007 ngep->default_mtu = ETHERMTU; 1008 ngep->buf_size = NGE_STD_BUFSZ; 1009 ngep->tx_desc = NGE_SEND_LOWMEM_SLOTS_DESC; 1010 ngep->rx_desc = NGE_RECV_LOWMEM_SLOTS_DESC; 1011 ngep->rx_buf = NGE_RECV_LOWMEM_SLOTS_DESC * 2; 1012 ngep->nge_split = NGE_SPLIT_32; 1013 } else { 1014 ngep->default_mtu = ETHERMTU; 1015 ngep->buf_size = NGE_STD_BUFSZ; 1016 ngep->tx_desc = dev_param_p->tx_desc_num; 1017 ngep->rx_desc = dev_param_p->rx_desc_num; 1018 ngep->rx_buf = dev_param_p->rx_desc_num * 2; 1019 ngep->nge_split = dev_param_p->nge_split; 1020 } 1021 1022 nge_check_desc_prop(ngep); 1023 } 1024 1025 1026 static int 1027 nge_reset(nge_t *ngep) 1028 { 1029 int err; 1030 send_ring_t *srp = ngep->send; 1031 1032 ASSERT(mutex_owned(ngep->genlock)); 1033 mutex_enter(srp->tc_lock); 1034 mutex_enter(srp->tx_lock); 1035 1036 nge_tx_recycle_all(ngep); 1037 err = nge_reinit_ring(ngep); 1038 if (err == DDI_FAILURE) { 1039 mutex_exit(srp->tx_lock); 1040 mutex_exit(srp->tc_lock); 1041 return (err); 1042 } 1043 err = nge_chip_reset(ngep); 1044 mutex_exit(srp->tx_lock); 1045 mutex_exit(srp->tc_lock); 1046 if (err == DDI_FAILURE) 1047 return (err); 1048 ngep->watchdog = 0; 1049 ngep->resched_needed = B_FALSE; 1050 ngep->promisc = B_FALSE; 1051 ngep->param_loop_mode = NGE_LOOP_NONE; 1052 ngep->factotum_flag = 0; 1053 ngep->resched_needed = 0; 1054 ngep->nge_mac_state = NGE_MAC_RESET; 1055 ngep->max_sdu = ngep->default_mtu + ETHER_HEAD_LEN + ETHERFCSL; 1056 ngep->max_sdu += VTAG_SIZE; 1057 ngep->rx_def = 0x16; 1058 return (DDI_SUCCESS); 1059 } 1060 1061 static void 1062 nge_m_stop(void *arg) 1063 { 1064 nge_t *ngep = arg; /* private device info */ 1065 1066 NGE_TRACE(("nge_m_stop($%p)", arg)); 1067 1068 /* 1069 * If suspended, adapter is already stopped, just return. 1070 */ 1071 if (ngep->suspended) { 1072 ASSERT(ngep->nge_mac_state == NGE_MAC_STOPPED); 1073 return; 1074 } 1075 1076 /* 1077 * Just stop processing, then record new MAC state 1078 */ 1079 mutex_enter(ngep->genlock); 1080 rw_enter(ngep->rwlock, RW_WRITER); 1081 1082 (void) nge_chip_stop(ngep, B_FALSE); 1083 /* Try to wait all the buffer post to upper layer be released */ 1084 ngep->nge_mac_state = NGE_MAC_STOPPED; 1085 1086 /* Recycle all the TX BD */ 1087 nge_tx_recycle_all(ngep); 1088 nge_fini_rings(ngep); 1089 nge_free_bufs(ngep); 1090 1091 NGE_DEBUG(("nge_m_stop($%p) done", arg)); 1092 1093 rw_exit(ngep->rwlock); 1094 mutex_exit(ngep->genlock); 1095 } 1096 1097 static int 1098 nge_m_start(void *arg) 1099 { 1100 int err; 1101 nge_t *ngep = arg; 1102 1103 NGE_TRACE(("nge_m_start($%p)", arg)); 1104 /* 1105 * If suspended, don't start, as the resume processing 1106 * will recall this function with the suspended flag off. 1107 */ 1108 if (ngep->suspended) 1109 return (DDI_FAILURE); 1110 /* 1111 * Start processing and record new MAC state 1112 */ 1113 mutex_enter(ngep->genlock); 1114 rw_enter(ngep->rwlock, RW_WRITER); 1115 err = nge_alloc_bufs(ngep); 1116 if (err != DDI_SUCCESS) { 1117 nge_problem(ngep, "nge_m_start: DMA buffer allocation failed"); 1118 goto finish; 1119 } 1120 err = nge_init_rings(ngep); 1121 if (err != DDI_SUCCESS) { 1122 nge_free_bufs(ngep); 1123 nge_problem(ngep, "nge_init_rings() failed,err=%x"); 1124 goto finish; 1125 } 1126 err = nge_restart(ngep); 1127 1128 NGE_DEBUG(("nge_m_start($%p) done", arg)); 1129 finish: 1130 rw_exit(ngep->rwlock); 1131 mutex_exit(ngep->genlock); 1132 1133 return (err); 1134 } 1135 1136 static int 1137 nge_m_unicst(void *arg, const uint8_t *macaddr) 1138 { 1139 nge_t *ngep = arg; 1140 1141 NGE_TRACE(("nge_m_unicst($%p)", arg)); 1142 /* 1143 * Remember the new current address in the driver state 1144 * Sync the chip's idea of the address too ... 1145 */ 1146 mutex_enter(ngep->genlock); 1147 1148 ethaddr_copy(macaddr, ngep->cur_uni_addr.addr); 1149 ngep->cur_uni_addr.set = 1; 1150 1151 /* 1152 * If we are suspended, we want to quit now, and not update 1153 * the chip. Doing so might put it in a bad state, but the 1154 * resume will get the unicast address installed. 1155 */ 1156 if (ngep->suspended) 1157 return (DDI_SUCCESS); 1158 1159 nge_chip_sync(ngep); 1160 1161 NGE_DEBUG(("nge_m_unicst($%p) done", arg)); 1162 mutex_exit(ngep->genlock); 1163 1164 return (0); 1165 } 1166 1167 static int 1168 nge_m_promisc(void *arg, boolean_t on) 1169 { 1170 nge_t *ngep = arg; 1171 1172 NGE_TRACE(("nge_m_promisc($%p)", arg)); 1173 /* 1174 * If suspended, we don't do anything, even record the promiscuious 1175 * mode, as we won't properly set it on resume. Just fail. 1176 */ 1177 if (ngep->suspended) 1178 return (DDI_FAILURE); 1179 1180 /* 1181 * Store specified mode and pass to chip layer to update h/w 1182 */ 1183 mutex_enter(ngep->genlock); 1184 if (ngep->promisc == on) { 1185 mutex_exit(ngep->genlock); 1186 NGE_DEBUG(("nge_m_promisc($%p) done", arg)); 1187 return (0); 1188 } 1189 ngep->promisc = on; 1190 nge_chip_sync(ngep); 1191 NGE_DEBUG(("nge_m_promisc($%p) done", arg)); 1192 mutex_exit(ngep->genlock); 1193 1194 return (0); 1195 } 1196 1197 static void nge_mulparam(nge_t *ngep) 1198 { 1199 uint8_t number; 1200 ether_addr_t pand; 1201 ether_addr_t por; 1202 mul_item *plist; 1203 1204 for (number = 0; number < ETHERADDRL; number++) { 1205 pand[number] = 0x00; 1206 por[number] = 0x00; 1207 } 1208 for (plist = ngep->pcur_mulist; plist != NULL; plist = plist->next) { 1209 for (number = 0; number < ETHERADDRL; number++) { 1210 pand[number] &= plist->mul_addr[number]; 1211 por[number] |= plist->mul_addr[number]; 1212 } 1213 } 1214 for (number = 0; number < ETHERADDRL; number++) { 1215 ngep->cur_mul_addr.addr[number] 1216 = pand[number] & por[number]; 1217 ngep->cur_mul_mask.addr[number] 1218 = pand [number] | (~por[number]); 1219 } 1220 } 1221 static int 1222 nge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 1223 { 1224 boolean_t update; 1225 boolean_t b_eq; 1226 nge_t *ngep = arg; 1227 mul_item *plist; 1228 mul_item *plist_prev; 1229 mul_item *pitem; 1230 1231 NGE_TRACE(("nge_m_multicst($%p, %s, %s)", arg, 1232 (add) ? "add" : "remove", ether_sprintf((void *)mca))); 1233 1234 update = B_FALSE; 1235 plist = plist_prev = NULL; 1236 mutex_enter(ngep->genlock); 1237 if (add) { 1238 if (ngep->pcur_mulist != NULL) { 1239 for (plist = ngep->pcur_mulist; plist != NULL; 1240 plist = plist->next) { 1241 b_eq = ether_eq(plist->mul_addr, mca); 1242 if (b_eq) { 1243 plist->ref_cnt++; 1244 break; 1245 } 1246 plist_prev = plist; 1247 } 1248 } 1249 1250 if (plist == NULL) { 1251 pitem = kmem_zalloc(sizeof (mul_item), KM_SLEEP); 1252 ether_copy(mca, pitem->mul_addr); 1253 pitem ->ref_cnt++; 1254 pitem ->next = NULL; 1255 if (plist_prev == NULL) 1256 ngep->pcur_mulist = pitem; 1257 else 1258 plist_prev->next = pitem; 1259 update = B_TRUE; 1260 } 1261 } else { 1262 if (ngep->pcur_mulist != NULL) { 1263 for (plist = ngep->pcur_mulist; plist != NULL; 1264 plist = plist->next) { 1265 b_eq = ether_eq(plist->mul_addr, mca); 1266 if (b_eq) { 1267 update = B_TRUE; 1268 break; 1269 } 1270 plist_prev = plist; 1271 } 1272 1273 if (update) { 1274 if ((plist_prev == NULL) && 1275 (plist->next == NULL)) 1276 ngep->pcur_mulist = NULL; 1277 else if ((plist_prev == NULL) && 1278 (plist->next != NULL)) 1279 ngep->pcur_mulist = plist->next; 1280 else 1281 plist_prev->next = plist->next; 1282 kmem_free(plist, sizeof (mul_item)); 1283 } 1284 } 1285 } 1286 1287 if (update || !ngep->suspended) { 1288 nge_mulparam(ngep); 1289 nge_chip_sync(ngep); 1290 } 1291 NGE_DEBUG(("nge_m_multicst($%p) done", arg)); 1292 mutex_exit(ngep->genlock); 1293 1294 return (0); 1295 } 1296 1297 static void 1298 nge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 1299 { 1300 int err; 1301 int cmd; 1302 nge_t *ngep = arg; 1303 struct iocblk *iocp; 1304 enum ioc_reply status; 1305 boolean_t need_privilege; 1306 1307 /* 1308 * If suspended, we might actually be able to do some of 1309 * these ioctls, but it is harder to make sure they occur 1310 * without actually putting the hardware in an undesireable 1311 * state. So just NAK it. 1312 */ 1313 if (ngep->suspended) { 1314 miocnak(wq, mp, 0, EINVAL); 1315 return; 1316 } 1317 1318 /* 1319 * Validate the command before bothering with the mutex ... 1320 */ 1321 iocp = (struct iocblk *)mp->b_rptr; 1322 iocp->ioc_error = 0; 1323 need_privilege = B_TRUE; 1324 cmd = iocp->ioc_cmd; 1325 1326 NGE_DEBUG(("nge_m_ioctl: cmd 0x%x", cmd)); 1327 switch (cmd) { 1328 default: 1329 NGE_LDB(NGE_DBG_BADIOC, 1330 ("nge_m_ioctl: unknown cmd 0x%x", cmd)); 1331 1332 miocnak(wq, mp, 0, EINVAL); 1333 return; 1334 1335 case NGE_MII_READ: 1336 case NGE_MII_WRITE: 1337 case NGE_SEE_READ: 1338 case NGE_SEE_WRITE: 1339 case NGE_DIAG: 1340 case NGE_PEEK: 1341 case NGE_POKE: 1342 case NGE_PHY_RESET: 1343 case NGE_SOFT_RESET: 1344 case NGE_HARD_RESET: 1345 break; 1346 1347 case LB_GET_INFO_SIZE: 1348 case LB_GET_INFO: 1349 case LB_GET_MODE: 1350 need_privilege = B_FALSE; 1351 break; 1352 case LB_SET_MODE: 1353 break; 1354 1355 case ND_GET: 1356 need_privilege = B_FALSE; 1357 break; 1358 case ND_SET: 1359 break; 1360 } 1361 1362 if (need_privilege) { 1363 /* 1364 * Check for specific net_config privilege. 1365 */ 1366 err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 1367 if (err != 0) { 1368 NGE_DEBUG(("nge_m_ioctl: rejected cmd 0x%x, err %d", 1369 cmd, err)); 1370 miocnak(wq, mp, 0, err); 1371 return; 1372 } 1373 } 1374 1375 mutex_enter(ngep->genlock); 1376 1377 switch (cmd) { 1378 default: 1379 _NOTE(NOTREACHED) 1380 status = IOC_INVAL; 1381 break; 1382 1383 case NGE_MII_READ: 1384 case NGE_MII_WRITE: 1385 case NGE_SEE_READ: 1386 case NGE_SEE_WRITE: 1387 case NGE_DIAG: 1388 case NGE_PEEK: 1389 case NGE_POKE: 1390 case NGE_PHY_RESET: 1391 case NGE_SOFT_RESET: 1392 case NGE_HARD_RESET: 1393 status = nge_chip_ioctl(ngep, mp, iocp); 1394 break; 1395 1396 case LB_GET_INFO_SIZE: 1397 case LB_GET_INFO: 1398 case LB_GET_MODE: 1399 case LB_SET_MODE: 1400 status = nge_loop_ioctl(ngep, mp, iocp); 1401 break; 1402 1403 case ND_GET: 1404 case ND_SET: 1405 status = nge_nd_ioctl(ngep, wq, mp, iocp); 1406 break; 1407 1408 } 1409 1410 /* 1411 * Do we need to reprogram the PHY and/or the MAC? 1412 * Do it now, while we still have the mutex. 1413 * 1414 * Note: update the PHY first, 'cos it controls the 1415 * speed/duplex parameters that the MAC code uses. 1416 */ 1417 1418 NGE_DEBUG(("nge_m_ioctl: cmd 0x%x status %d", cmd, status)); 1419 1420 switch (status) { 1421 case IOC_RESTART_REPLY: 1422 case IOC_RESTART_ACK: 1423 (*ngep->physops->phys_update)(ngep); 1424 nge_chip_sync(ngep); 1425 break; 1426 1427 default: 1428 break; 1429 } 1430 1431 mutex_exit(ngep->genlock); 1432 1433 /* 1434 * Finally, decide how to reply 1435 */ 1436 switch (status) { 1437 1438 default: 1439 case IOC_INVAL: 1440 miocnak(wq, mp, 0, iocp->ioc_error == 0 ? 1441 EINVAL : iocp->ioc_error); 1442 break; 1443 1444 case IOC_DONE: 1445 break; 1446 1447 case IOC_RESTART_ACK: 1448 case IOC_ACK: 1449 miocack(wq, mp, 0, 0); 1450 break; 1451 1452 case IOC_RESTART_REPLY: 1453 case IOC_REPLY: 1454 mp->b_datap->db_type = iocp->ioc_error == 0 ? 1455 M_IOCACK : M_IOCNAK; 1456 qreply(wq, mp); 1457 break; 1458 } 1459 } 1460 1461 static void 1462 nge_chip_blank(void *arg, time_t ticks, uint_t count) 1463 { 1464 _NOTE(ARGUNUSED(arg, ticks, count)); 1465 } 1466 1467 static void 1468 nge_m_resources(void *arg) 1469 { 1470 nge_t *ngep = arg; 1471 recv_ring_t *rrp; 1472 mac_rx_fifo_t mrf; 1473 1474 mutex_enter(ngep->genlock); 1475 1476 /* 1477 * Register Rx rings as resources and save mac 1478 * resource id for future reference 1479 */ 1480 mrf.mrf_type = MAC_RX_FIFO; 1481 mrf.mrf_blank = nge_chip_blank; 1482 mrf.mrf_arg = (void *)ngep; 1483 mrf.mrf_normal_blank_time = NGE_TICKS_CNT; 1484 mrf.mrf_normal_pkt_count = NGE_RX_PKT_CNT; 1485 1486 rrp = ngep->recv; 1487 rrp->handle = mac_resource_add(ngep->mh, (mac_resource_t *)&mrf); 1488 mutex_exit(ngep->genlock); 1489 } 1490 1491 /* ARGSUSED */ 1492 static boolean_t 1493 nge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 1494 { 1495 nge_t *ngep = arg; 1496 nge_dev_spec_param_t *dev_param_p; 1497 1498 dev_param_p = &ngep->dev_spec_param; 1499 1500 switch (cap) { 1501 case MAC_CAPAB_HCKSUM: { 1502 uint32_t *hcksum_txflags = cap_data; 1503 1504 if (dev_param_p->tx_hw_checksum) { 1505 *hcksum_txflags = dev_param_p->tx_hw_checksum; 1506 } else 1507 return (B_FALSE); 1508 break; 1509 } 1510 case MAC_CAPAB_POLL: 1511 /* 1512 * There's nothing for us to fill in, simply returning 1513 * B_TRUE, stating that we support polling is sufficient. 1514 */ 1515 break; 1516 default: 1517 return (B_FALSE); 1518 } 1519 return (B_TRUE); 1520 } 1521 1522 #undef NGE_DBG 1523 #define NGE_DBG NGE_DBG_INIT /* debug flag for this code */ 1524 int 1525 nge_restart(nge_t *ngep) 1526 { 1527 int err = 0; 1528 err += nge_reset(ngep); 1529 err += nge_chip_start(ngep); 1530 1531 if (err) { 1532 ngep->nge_mac_state = NGE_MAC_STOPPED; 1533 return (DDI_FAILURE); 1534 } else { 1535 ngep->nge_mac_state = NGE_MAC_STARTED; 1536 return (DDI_SUCCESS); 1537 } 1538 } 1539 1540 void 1541 nge_wake_factotum(nge_t *ngep) 1542 { 1543 mutex_enter(ngep->softlock); 1544 if (ngep->factotum_flag == 0) { 1545 ngep->factotum_flag = 1; 1546 (void) ddi_intr_trigger_softint(ngep->factotum_hdl, NULL); 1547 } 1548 mutex_exit(ngep->softlock); 1549 } 1550 1551 /* 1552 * High-level cyclic handler 1553 * 1554 * This routine schedules a (low-level) softint callback to the 1555 * factotum. 1556 */ 1557 1558 static void 1559 nge_chip_cyclic(void *arg) 1560 { 1561 nge_t *ngep; 1562 1563 ngep = (nge_t *)arg; 1564 1565 switch (ngep->nge_chip_state) { 1566 default: 1567 return; 1568 1569 case NGE_CHIP_RUNNING: 1570 break; 1571 1572 case NGE_CHIP_FAULT: 1573 case NGE_CHIP_ERROR: 1574 break; 1575 } 1576 1577 nge_wake_factotum(ngep); 1578 } 1579 1580 static void 1581 nge_unattach(nge_t *ngep) 1582 { 1583 send_ring_t *srp; 1584 buff_ring_t *brp; 1585 1586 srp = ngep->send; 1587 brp = ngep->buff; 1588 NGE_TRACE(("nge_unattach($%p)", (void *)ngep)); 1589 1590 /* 1591 * Flag that no more activity may be initiated 1592 */ 1593 ngep->progress &= ~PROGRESS_READY; 1594 ngep->nge_mac_state = NGE_MAC_UNATTACH; 1595 1596 /* 1597 * Quiesce the PHY and MAC (leave it reset but still powered). 1598 * Clean up and free all NGE data structures 1599 */ 1600 if (ngep->periodic_id != NULL) { 1601 ddi_periodic_delete(ngep->periodic_id); 1602 ngep->periodic_id = NULL; 1603 } 1604 1605 if (ngep->progress & PROGRESS_KSTATS) 1606 nge_fini_kstats(ngep); 1607 1608 if (ngep->progress & PROGRESS_NDD) 1609 nge_nd_cleanup(ngep); 1610 1611 if (ngep->progress & PROGRESS_HWINT) { 1612 mutex_enter(ngep->genlock); 1613 nge_restore_mac_addr(ngep); 1614 (void) nge_chip_stop(ngep, B_FALSE); 1615 mutex_exit(ngep->genlock); 1616 } 1617 1618 if (ngep->progress & PROGRESS_SWINT) 1619 nge_rem_intrs(ngep); 1620 1621 if (ngep->progress & PROGRESS_FACTOTUM) 1622 (void) ddi_intr_remove_softint(ngep->factotum_hdl); 1623 1624 if (ngep->progress & PROGRESS_RESCHED) 1625 (void) ddi_intr_remove_softint(ngep->resched_hdl); 1626 1627 if (ngep->progress & PROGRESS_INTR) { 1628 mutex_destroy(srp->tx_lock); 1629 mutex_destroy(srp->tc_lock); 1630 mutex_destroy(&srp->dmah_lock); 1631 mutex_destroy(brp->recycle_lock); 1632 1633 mutex_destroy(ngep->genlock); 1634 mutex_destroy(ngep->softlock); 1635 rw_destroy(ngep->rwlock); 1636 } 1637 1638 if (ngep->progress & PROGRESS_REGS) 1639 ddi_regs_map_free(&ngep->io_handle); 1640 1641 if (ngep->progress & PROGRESS_CFG) 1642 pci_config_teardown(&ngep->cfg_handle); 1643 1644 ddi_remove_minor_node(ngep->devinfo, NULL); 1645 1646 kmem_free(ngep, sizeof (*ngep)); 1647 } 1648 1649 static int 1650 nge_resume(dev_info_t *devinfo) 1651 { 1652 nge_t *ngep; 1653 chip_info_t *infop; 1654 1655 ASSERT(devinfo != NULL); 1656 1657 ngep = ddi_get_driver_private(devinfo); 1658 /* 1659 * If there are state inconsistancies, this is bad. Returning 1660 * DDI_FAILURE here will eventually cause the machine to panic, 1661 * so it is best done here so that there is a possibility of 1662 * debugging the problem. 1663 */ 1664 if (ngep == NULL) 1665 cmn_err(CE_PANIC, 1666 "nge: ngep returned from ddi_get_driver_private was NULL"); 1667 infop = (chip_info_t *)&ngep->chipinfo; 1668 1669 if (ngep->devinfo != devinfo) 1670 cmn_err(CE_PANIC, 1671 "nge: passed devinfo not the same as saved definfo"); 1672 1673 ngep->suspended = B_FALSE; 1674 1675 /* 1676 * Fetch the config space. Even though we have most of it cached, 1677 * some values *might* change across a suspend/resume. 1678 */ 1679 nge_chip_cfg_init(ngep, infop, B_FALSE); 1680 1681 /* 1682 * Start the controller. In this case (and probably most GLDv3 1683 * devices), it is sufficient to call nge_m_start(). 1684 */ 1685 if (nge_m_start((void *)ngep) != DDI_SUCCESS) { 1686 /* 1687 * We note the failure, but return success, as the 1688 * system is still usable without this controller. 1689 */ 1690 cmn_err(CE_WARN, "nge: resume: failed to restart controller"); 1691 } 1692 return (DDI_SUCCESS); 1693 } 1694 1695 /* 1696 * attach(9E) -- Attach a device to the system 1697 * 1698 * Called once for each board successfully probed. 1699 */ 1700 static int 1701 nge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 1702 { 1703 int err; 1704 int i; 1705 int instance; 1706 caddr_t regs; 1707 nge_t *ngep; 1708 chip_info_t *infop; 1709 mac_register_t *macp; 1710 1711 switch (cmd) { 1712 default: 1713 return (DDI_FAILURE); 1714 1715 case DDI_RESUME: 1716 return (nge_resume(devinfo)); 1717 1718 case DDI_ATTACH: 1719 break; 1720 } 1721 1722 ngep = kmem_zalloc(sizeof (*ngep), KM_SLEEP); 1723 instance = ddi_get_instance(devinfo); 1724 ddi_set_driver_private(devinfo, ngep); 1725 ngep->devinfo = devinfo; 1726 1727 (void) snprintf(ngep->ifname, sizeof (ngep->ifname), "%s%d", 1728 NGE_DRIVER_NAME, instance); 1729 err = pci_config_setup(devinfo, &ngep->cfg_handle); 1730 if (err != DDI_SUCCESS) { 1731 nge_problem(ngep, "nge_attach: pci_config_setup() failed"); 1732 goto attach_fail; 1733 } 1734 infop = (chip_info_t *)&ngep->chipinfo; 1735 nge_chip_cfg_init(ngep, infop, B_FALSE); 1736 nge_init_dev_spec_param(ngep); 1737 nge_get_props(ngep); 1738 ngep->progress |= PROGRESS_CFG; 1739 1740 err = ddi_regs_map_setup(devinfo, NGE_PCI_OPREGS_RNUMBER, 1741 ®s, 0, 0, &nge_reg_accattr, &ngep->io_handle); 1742 if (err != DDI_SUCCESS) { 1743 nge_problem(ngep, "nge_attach: ddi_regs_map_setup() failed"); 1744 goto attach_fail; 1745 } 1746 ngep->io_regs = regs; 1747 ngep->progress |= PROGRESS_REGS; 1748 1749 err = nge_register_intrs_and_init_locks(ngep); 1750 if (err != DDI_SUCCESS) { 1751 nge_problem(ngep, "nge_attach:" 1752 " register intrs and init locks failed"); 1753 goto attach_fail; 1754 } 1755 nge_init_ring_param_lock(ngep); 1756 ngep->progress |= PROGRESS_INTR; 1757 1758 mutex_enter(ngep->genlock); 1759 1760 /* 1761 * Initialise link state variables 1762 * Stop, reset & reinitialise the chip. 1763 * Initialise the (internal) PHY. 1764 */ 1765 nge_phys_init(ngep); 1766 err = nge_chip_reset(ngep); 1767 if (err != DDI_SUCCESS) { 1768 nge_problem(ngep, "nge_attach: nge_chip_reset() failed"); 1769 mutex_exit(ngep->genlock); 1770 goto attach_fail; 1771 } 1772 nge_chip_sync(ngep); 1773 1774 /* 1775 * Now that mutex locks are initialized, enable interrupts. 1776 */ 1777 if (ngep->intr_cap & DDI_INTR_FLAG_BLOCK) { 1778 /* Call ddi_intr_block_enable() for MSI interrupts */ 1779 (void) ddi_intr_block_enable(ngep->htable, 1780 ngep->intr_actual_cnt); 1781 } else { 1782 /* Call ddi_intr_enable for MSI or FIXED interrupts */ 1783 for (i = 0; i < ngep->intr_actual_cnt; i++) { 1784 (void) ddi_intr_enable(ngep->htable[i]); 1785 } 1786 } 1787 1788 ngep->link_state = LINK_STATE_UNKNOWN; 1789 ngep->progress |= PROGRESS_HWINT; 1790 1791 /* 1792 * Register NDD-tweakable parameters 1793 */ 1794 if (nge_nd_init(ngep)) { 1795 nge_problem(ngep, "nge_attach: nge_nd_init() failed"); 1796 mutex_exit(ngep->genlock); 1797 goto attach_fail; 1798 } 1799 ngep->progress |= PROGRESS_NDD; 1800 1801 /* 1802 * Create & initialise named kstats 1803 */ 1804 nge_init_kstats(ngep, instance); 1805 ngep->progress |= PROGRESS_KSTATS; 1806 1807 mutex_exit(ngep->genlock); 1808 1809 if ((macp = mac_alloc(MAC_VERSION)) == NULL) 1810 goto attach_fail; 1811 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 1812 macp->m_driver = ngep; 1813 macp->m_dip = devinfo; 1814 macp->m_src_addr = infop->vendor_addr.addr; 1815 macp->m_callbacks = &nge_m_callbacks; 1816 macp->m_min_sdu = 0; 1817 macp->m_max_sdu = ngep->default_mtu; 1818 /* 1819 * Finally, we're ready to register ourselves with the mac 1820 * interface; if this succeeds, we're all ready to start() 1821 */ 1822 err = mac_register(macp, &ngep->mh); 1823 mac_free(macp); 1824 if (err != 0) 1825 goto attach_fail; 1826 1827 /* 1828 * Register a periodical handler. 1829 * nge_chip_cyclic() is invoked in kernel context. 1830 */ 1831 ngep->periodic_id = ddi_periodic_add(nge_chip_cyclic, ngep, 1832 NGE_CYCLIC_PERIOD, DDI_IPL_0); 1833 1834 ngep->progress |= PROGRESS_READY; 1835 return (DDI_SUCCESS); 1836 1837 attach_fail: 1838 nge_unattach(ngep); 1839 return (DDI_FAILURE); 1840 } 1841 1842 /* 1843 * detach(9E) -- Detach a device from the system 1844 */ 1845 static int 1846 nge_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 1847 { 1848 int i; 1849 nge_t *ngep; 1850 mul_item *p, *nextp; 1851 buff_ring_t *brp; 1852 1853 NGE_GTRACE(("nge_detach($%p, %d)", (void *)devinfo, cmd)); 1854 1855 ngep = ddi_get_driver_private(devinfo); 1856 brp = ngep->buff; 1857 1858 switch (cmd) { 1859 default: 1860 return (DDI_FAILURE); 1861 1862 case DDI_SUSPEND: 1863 /* 1864 * Stop the NIC 1865 * I suspect that we can actually suspend if the stop 1866 * routine returns a failure, as the resume will 1867 * effectively fully reset the hardware (i.e. we don't 1868 * really save any hardware state). However, nge_m_stop 1869 * doesn't return an error code. 1870 * Note: This driver doesn't currently support WOL, but 1871 * should it in the future, it is important to 1872 * make sure the PHY remains powered so that the 1873 * wakeup packet can actually be recieved. 1874 */ 1875 nge_m_stop(ngep); 1876 ngep->suspended = B_TRUE; 1877 return (DDI_SUCCESS); 1878 1879 case DDI_DETACH: 1880 break; 1881 } 1882 1883 /* Try to wait all the buffer post to upper layer be released */ 1884 for (i = 0; i < 1000; i++) { 1885 if (brp->rx_hold == 0) 1886 break; 1887 drv_usecwait(1000); 1888 } 1889 1890 /* If there is any posted buffer, reject to detach */ 1891 if (brp->rx_hold != 0) 1892 return (DDI_FAILURE); 1893 1894 /* Recycle the multicast table */ 1895 for (p = ngep->pcur_mulist; p != NULL; p = nextp) { 1896 nextp = p->next; 1897 kmem_free(p, sizeof (mul_item)); 1898 } 1899 ngep->pcur_mulist = NULL; 1900 1901 /* 1902 * Unregister from the GLD subsystem. This can fail, in 1903 * particular if there are DLPI style-2 streams still open - 1904 * in which case we just return failure without shutting 1905 * down chip operations. 1906 */ 1907 if (mac_unregister(ngep->mh) != DDI_SUCCESS) 1908 return (DDI_FAILURE); 1909 1910 /* 1911 * All activity stopped, so we can clean up & exit 1912 */ 1913 nge_unattach(ngep); 1914 return (DDI_SUCCESS); 1915 } 1916 1917 1918 /* 1919 * ========== Module Loading Data & Entry Points ========== 1920 */ 1921 1922 DDI_DEFINE_STREAM_OPS(nge_dev_ops, nulldev, nulldev, nge_attach, nge_detach, 1923 nodev, NULL, D_MP, NULL); 1924 1925 1926 static struct modldrv nge_modldrv = { 1927 &mod_driverops, /* Type of module. This one is a driver */ 1928 nge_ident, /* short description */ 1929 &nge_dev_ops /* driver specific ops */ 1930 }; 1931 1932 static struct modlinkage modlinkage = { 1933 MODREV_1, (void *)&nge_modldrv, NULL 1934 }; 1935 1936 1937 int 1938 _info(struct modinfo *modinfop) 1939 { 1940 return (mod_info(&modlinkage, modinfop)); 1941 } 1942 1943 int 1944 _init(void) 1945 { 1946 int status; 1947 1948 mac_init_ops(&nge_dev_ops, "nge"); 1949 status = mod_install(&modlinkage); 1950 if (status != DDI_SUCCESS) 1951 mac_fini_ops(&nge_dev_ops); 1952 else 1953 mutex_init(nge_log_mutex, NULL, MUTEX_DRIVER, NULL); 1954 1955 return (status); 1956 } 1957 1958 int 1959 _fini(void) 1960 { 1961 int status; 1962 1963 status = mod_remove(&modlinkage); 1964 if (status == DDI_SUCCESS) { 1965 mac_fini_ops(&nge_dev_ops); 1966 mutex_destroy(nge_log_mutex); 1967 } 1968 1969 return (status); 1970 } 1971 1972 /* 1973 * ============ Init MSI/Fixed/SoftInterrupt routines ============== 1974 */ 1975 1976 /* 1977 * Register interrupts and initialize each mutex and condition variables 1978 */ 1979 1980 static int 1981 nge_register_intrs_and_init_locks(nge_t *ngep) 1982 { 1983 int err; 1984 int intr_types; 1985 uint_t soft_prip; 1986 nge_msi_mask msi_mask; 1987 nge_msi_map0_vec map0_vec; 1988 nge_msi_map1_vec map1_vec; 1989 1990 /* 1991 * Add the softint handlers: 1992 * 1993 * Both of these handlers are used to avoid restrictions on the 1994 * context and/or mutexes required for some operations. In 1995 * particular, the hardware interrupt handler and its subfunctions 1996 * can detect a number of conditions that we don't want to handle 1997 * in that context or with that set of mutexes held. So, these 1998 * softints are triggered instead: 1999 * 2000 * the <resched> softint is triggered if if we have previously 2001 * had to refuse to send a packet because of resource shortage 2002 * (we've run out of transmit buffers), but the send completion 2003 * interrupt handler has now detected that more buffers have 2004 * become available. Its only purpose is to call gld_sched() 2005 * to retry the pending transmits (we're not allowed to hold 2006 * driver-defined mutexes across gld_sched()). 2007 * 2008 * the <factotum> is triggered if the h/w interrupt handler 2009 * sees the <link state changed> or <error> bits in the status 2010 * block. It's also triggered periodically to poll the link 2011 * state, just in case we aren't getting link status change 2012 * interrupts ... 2013 */ 2014 err = ddi_intr_add_softint(ngep->devinfo, &ngep->resched_hdl, 2015 DDI_INTR_SOFTPRI_MIN, nge_reschedule, (caddr_t)ngep); 2016 if (err != DDI_SUCCESS) { 2017 nge_problem(ngep, 2018 "nge_attach: add nge_reschedule softintr failed"); 2019 2020 return (DDI_FAILURE); 2021 } 2022 ngep->progress |= PROGRESS_RESCHED; 2023 err = ddi_intr_add_softint(ngep->devinfo, &ngep->factotum_hdl, 2024 DDI_INTR_SOFTPRI_MIN, nge_chip_factotum, (caddr_t)ngep); 2025 if (err != DDI_SUCCESS) { 2026 nge_problem(ngep, 2027 "nge_attach: add nge_chip_factotum softintr failed!"); 2028 2029 return (DDI_FAILURE); 2030 } 2031 if (ddi_intr_get_softint_pri(ngep->factotum_hdl, &soft_prip) 2032 != DDI_SUCCESS) { 2033 nge_problem(ngep, "nge_attach: get softintr priority failed\n"); 2034 2035 return (DDI_FAILURE); 2036 } 2037 ngep->soft_pri = soft_prip; 2038 2039 ngep->progress |= PROGRESS_FACTOTUM; 2040 /* Get supported interrupt types */ 2041 if (ddi_intr_get_supported_types(ngep->devinfo, &intr_types) 2042 != DDI_SUCCESS) { 2043 nge_error(ngep, "ddi_intr_get_supported_types failed\n"); 2044 2045 return (DDI_FAILURE); 2046 } 2047 2048 NGE_DEBUG(("ddi_intr_get_supported_types() returned: %x", 2049 intr_types)); 2050 2051 if ((intr_types & DDI_INTR_TYPE_MSI) && nge_enable_msi) { 2052 2053 /* MSI Configurations for mcp55 chipset */ 2054 if (ngep->chipinfo.device == DEVICE_ID_MCP55_373 || 2055 ngep->chipinfo.device == DEVICE_ID_MCP55_372) { 2056 2057 2058 /* Enable the 8 vectors */ 2059 msi_mask.msi_mask_val = 2060 nge_reg_get32(ngep, NGE_MSI_MASK); 2061 msi_mask.msi_msk_bits.vec0 = NGE_SET; 2062 msi_mask.msi_msk_bits.vec1 = NGE_SET; 2063 msi_mask.msi_msk_bits.vec2 = NGE_SET; 2064 msi_mask.msi_msk_bits.vec3 = NGE_SET; 2065 msi_mask.msi_msk_bits.vec4 = NGE_SET; 2066 msi_mask.msi_msk_bits.vec5 = NGE_SET; 2067 msi_mask.msi_msk_bits.vec6 = NGE_SET; 2068 msi_mask.msi_msk_bits.vec7 = NGE_SET; 2069 nge_reg_put32(ngep, NGE_MSI_MASK, 2070 msi_mask.msi_mask_val); 2071 2072 /* 2073 * Remapping the MSI MAP0 and MAP1. MCP55 2074 * is default mapping all the interrupt to 0 vector. 2075 * Software needs to remapping this. 2076 * This mapping is same as CK804. 2077 */ 2078 map0_vec.msi_map0_val = 2079 nge_reg_get32(ngep, NGE_MSI_MAP0); 2080 map1_vec.msi_map1_val = 2081 nge_reg_get32(ngep, NGE_MSI_MAP1); 2082 map0_vec.vecs_bits.reint_vec = 0; 2083 map0_vec.vecs_bits.rcint_vec = 0; 2084 map0_vec.vecs_bits.miss_vec = 3; 2085 map0_vec.vecs_bits.teint_vec = 5; 2086 map0_vec.vecs_bits.tcint_vec = 5; 2087 map0_vec.vecs_bits.stint_vec = 2; 2088 map0_vec.vecs_bits.mint_vec = 6; 2089 map0_vec.vecs_bits.rfint_vec = 0; 2090 map1_vec.vecs_bits.tfint_vec = 5; 2091 map1_vec.vecs_bits.feint_vec = 6; 2092 map1_vec.vecs_bits.resv8_11 = 3; 2093 map1_vec.vecs_bits.resv12_15 = 1; 2094 map1_vec.vecs_bits.resv16_19 = 0; 2095 map1_vec.vecs_bits.resv20_23 = 7; 2096 map1_vec.vecs_bits.resv24_31 = 0xff; 2097 nge_reg_put32(ngep, NGE_MSI_MAP0, 2098 map0_vec.msi_map0_val); 2099 nge_reg_put32(ngep, NGE_MSI_MAP1, 2100 map1_vec.msi_map1_val); 2101 } 2102 if (nge_add_intrs(ngep, DDI_INTR_TYPE_MSI) != DDI_SUCCESS) { 2103 NGE_DEBUG(("MSI registration failed, " 2104 "trying FIXED interrupt type\n")); 2105 } else { 2106 nge_log(ngep, "Using MSI interrupt type\n"); 2107 2108 ngep->intr_type = DDI_INTR_TYPE_MSI; 2109 ngep->progress |= PROGRESS_SWINT; 2110 } 2111 } 2112 2113 if (!(ngep->progress & PROGRESS_SWINT) && 2114 (intr_types & DDI_INTR_TYPE_FIXED)) { 2115 if (nge_add_intrs(ngep, DDI_INTR_TYPE_FIXED) != DDI_SUCCESS) { 2116 nge_error(ngep, "FIXED interrupt " 2117 "registration failed\n"); 2118 2119 return (DDI_FAILURE); 2120 } 2121 2122 nge_log(ngep, "Using FIXED interrupt type\n"); 2123 2124 ngep->intr_type = DDI_INTR_TYPE_FIXED; 2125 ngep->progress |= PROGRESS_SWINT; 2126 } 2127 2128 2129 if (!(ngep->progress & PROGRESS_SWINT)) { 2130 nge_error(ngep, "No interrupts registered\n"); 2131 2132 return (DDI_FAILURE); 2133 } 2134 mutex_init(ngep->genlock, NULL, MUTEX_DRIVER, 2135 DDI_INTR_PRI(ngep->intr_pri)); 2136 mutex_init(ngep->softlock, NULL, MUTEX_DRIVER, 2137 DDI_INTR_PRI(ngep->soft_pri)); 2138 rw_init(ngep->rwlock, NULL, RW_DRIVER, 2139 DDI_INTR_PRI(ngep->intr_pri)); 2140 2141 return (DDI_SUCCESS); 2142 } 2143 2144 /* 2145 * nge_add_intrs: 2146 * 2147 * Register FIXED or MSI interrupts. 2148 */ 2149 static int 2150 nge_add_intrs(nge_t *ngep, int intr_type) 2151 { 2152 dev_info_t *dip = ngep->devinfo; 2153 int avail, actual, intr_size, count = 0; 2154 int i, flag, ret; 2155 2156 NGE_DEBUG(("nge_add_intrs: interrupt type 0x%x\n", intr_type)); 2157 2158 /* Get number of interrupts */ 2159 ret = ddi_intr_get_nintrs(dip, intr_type, &count); 2160 if ((ret != DDI_SUCCESS) || (count == 0)) { 2161 nge_error(ngep, "ddi_intr_get_nintrs() failure, ret: %d, " 2162 "count: %d", ret, count); 2163 2164 return (DDI_FAILURE); 2165 } 2166 2167 /* Get number of available interrupts */ 2168 ret = ddi_intr_get_navail(dip, intr_type, &avail); 2169 if ((ret != DDI_SUCCESS) || (avail == 0)) { 2170 nge_error(ngep, "ddi_intr_get_navail() failure, " 2171 "ret: %d, avail: %d\n", ret, avail); 2172 2173 return (DDI_FAILURE); 2174 } 2175 2176 if (avail < count) { 2177 NGE_DEBUG(("nitrs() returned %d, navail returned %d\n", 2178 count, avail)); 2179 } 2180 flag = DDI_INTR_ALLOC_NORMAL; 2181 2182 /* Allocate an array of interrupt handles */ 2183 intr_size = count * sizeof (ddi_intr_handle_t); 2184 ngep->htable = kmem_alloc(intr_size, KM_SLEEP); 2185 2186 /* Call ddi_intr_alloc() */ 2187 ret = ddi_intr_alloc(dip, ngep->htable, intr_type, 0, 2188 count, &actual, flag); 2189 2190 if ((ret != DDI_SUCCESS) || (actual == 0)) { 2191 nge_error(ngep, "ddi_intr_alloc() failed %d\n", ret); 2192 2193 kmem_free(ngep->htable, intr_size); 2194 return (DDI_FAILURE); 2195 } 2196 2197 if (actual < count) { 2198 NGE_DEBUG(("Requested: %d, Received: %d\n", 2199 count, actual)); 2200 } 2201 2202 ngep->intr_actual_cnt = actual; 2203 ngep->intr_req_cnt = count; 2204 2205 /* 2206 * Get priority for first msi, assume remaining are all the same 2207 */ 2208 if ((ret = ddi_intr_get_pri(ngep->htable[0], &ngep->intr_pri)) != 2209 DDI_SUCCESS) { 2210 nge_error(ngep, "ddi_intr_get_pri() failed %d\n", ret); 2211 2212 /* Free already allocated intr */ 2213 for (i = 0; i < actual; i++) { 2214 (void) ddi_intr_free(ngep->htable[i]); 2215 } 2216 2217 kmem_free(ngep->htable, intr_size); 2218 2219 return (DDI_FAILURE); 2220 } 2221 /* Test for high level mutex */ 2222 if (ngep->intr_pri >= ddi_intr_get_hilevel_pri()) { 2223 nge_error(ngep, "nge_add_intrs:" 2224 "Hi level interrupt not supported"); 2225 2226 for (i = 0; i < actual; i++) 2227 (void) ddi_intr_free(ngep->htable[i]); 2228 2229 kmem_free(ngep->htable, intr_size); 2230 2231 return (DDI_FAILURE); 2232 } 2233 2234 2235 /* Call ddi_intr_add_handler() */ 2236 for (i = 0; i < actual; i++) { 2237 if ((ret = ddi_intr_add_handler(ngep->htable[i], nge_chip_intr, 2238 (caddr_t)ngep, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) { 2239 nge_error(ngep, "ddi_intr_add_handler() " 2240 "failed %d\n", ret); 2241 2242 /* Free already allocated intr */ 2243 for (i = 0; i < actual; i++) { 2244 (void) ddi_intr_free(ngep->htable[i]); 2245 } 2246 2247 kmem_free(ngep->htable, intr_size); 2248 2249 return (DDI_FAILURE); 2250 } 2251 } 2252 2253 if ((ret = ddi_intr_get_cap(ngep->htable[0], &ngep->intr_cap)) 2254 != DDI_SUCCESS) { 2255 nge_error(ngep, "ddi_intr_get_cap() failed %d\n", ret); 2256 2257 for (i = 0; i < actual; i++) { 2258 (void) ddi_intr_remove_handler(ngep->htable[i]); 2259 (void) ddi_intr_free(ngep->htable[i]); 2260 } 2261 2262 kmem_free(ngep->htable, intr_size); 2263 2264 return (DDI_FAILURE); 2265 } 2266 2267 return (DDI_SUCCESS); 2268 } 2269 2270 /* 2271 * nge_rem_intrs: 2272 * 2273 * Unregister FIXED or MSI interrupts 2274 */ 2275 static void 2276 nge_rem_intrs(nge_t *ngep) 2277 { 2278 int i; 2279 2280 NGE_DEBUG(("nge_rem_intrs\n")); 2281 2282 /* Disable all interrupts */ 2283 if (ngep->intr_cap & DDI_INTR_FLAG_BLOCK) { 2284 /* Call ddi_intr_block_disable() */ 2285 (void) ddi_intr_block_disable(ngep->htable, 2286 ngep->intr_actual_cnt); 2287 } else { 2288 for (i = 0; i < ngep->intr_actual_cnt; i++) { 2289 (void) ddi_intr_disable(ngep->htable[i]); 2290 } 2291 } 2292 2293 /* Call ddi_intr_remove_handler() */ 2294 for (i = 0; i < ngep->intr_actual_cnt; i++) { 2295 (void) ddi_intr_remove_handler(ngep->htable[i]); 2296 (void) ddi_intr_free(ngep->htable[i]); 2297 } 2298 2299 kmem_free(ngep->htable, 2300 ngep->intr_req_cnt * sizeof (ddi_intr_handle_t)); 2301 } 2302