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 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 179 #define NGE_M_CALLBACK_FLAGS (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 NULL, 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->intr_moderation = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 957 DDI_PROP_DONTPASS, intr_moderation, NGE_SET); 958 ngep->rx_datahwm = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 959 DDI_PROP_DONTPASS, rx_data_hw, 0x20); 960 ngep->rx_prdlwm = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 961 DDI_PROP_DONTPASS, rx_prd_lw, 0x4); 962 ngep->rx_prdhwm = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 963 DDI_PROP_DONTPASS, rx_prd_hw, 0xc); 964 965 ngep->sw_intr_intv = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 966 DDI_PROP_DONTPASS, sw_intr_intv, SWTR_ITC); 967 ngep->debug = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 968 DDI_PROP_DONTPASS, debug_propname, NGE_DBG_CHIP); 969 ngep->desc_mode = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 970 DDI_PROP_DONTPASS, nge_desc_mode, dev_param_p->desc_type); 971 ngep->lowmem_mode = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 972 DDI_PROP_DONTPASS, low_memory_mode, 0); 973 974 if (dev_param_p->jumbo) { 975 ngep->default_mtu = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 976 DDI_PROP_DONTPASS, default_mtu, ETHERMTU); 977 } else 978 ngep->default_mtu = ETHERMTU; 979 980 if (ngep->default_mtu > ETHERMTU && 981 ngep->default_mtu <= NGE_MTU_2500) { 982 ngep->buf_size = NGE_JB2500_BUFSZ; 983 ngep->tx_desc = NGE_SEND_JB2500_SLOTS_DESC; 984 ngep->rx_desc = NGE_RECV_JB2500_SLOTS_DESC; 985 ngep->rx_buf = NGE_RECV_JB2500_SLOTS_DESC * 2; 986 ngep->nge_split = NGE_SPLIT_256; 987 } else if (ngep->default_mtu > NGE_MTU_2500 && 988 ngep->default_mtu <= NGE_MTU_4500) { 989 ngep->buf_size = NGE_JB4500_BUFSZ; 990 ngep->tx_desc = NGE_SEND_JB4500_SLOTS_DESC; 991 ngep->rx_desc = NGE_RECV_JB4500_SLOTS_DESC; 992 ngep->rx_buf = NGE_RECV_JB4500_SLOTS_DESC * 2; 993 ngep->nge_split = NGE_SPLIT_256; 994 } else if (ngep->default_mtu > NGE_MTU_4500 && 995 ngep->default_mtu <= NGE_MAX_MTU) { 996 ngep->buf_size = NGE_JB9000_BUFSZ; 997 ngep->tx_desc = NGE_SEND_JB9000_SLOTS_DESC; 998 ngep->rx_desc = NGE_RECV_JB9000_SLOTS_DESC; 999 ngep->rx_buf = NGE_RECV_JB9000_SLOTS_DESC * 2; 1000 ngep->nge_split = NGE_SPLIT_256; 1001 } else if (ngep->default_mtu > NGE_MAX_MTU) { 1002 ngep->default_mtu = NGE_MAX_MTU; 1003 ngep->buf_size = NGE_JB9000_BUFSZ; 1004 ngep->tx_desc = NGE_SEND_JB9000_SLOTS_DESC; 1005 ngep->rx_desc = NGE_RECV_JB9000_SLOTS_DESC; 1006 ngep->rx_buf = NGE_RECV_JB9000_SLOTS_DESC * 2; 1007 ngep->nge_split = NGE_SPLIT_256; 1008 } else if (ngep->lowmem_mode != 0) { 1009 ngep->default_mtu = ETHERMTU; 1010 ngep->buf_size = NGE_STD_BUFSZ; 1011 ngep->tx_desc = NGE_SEND_LOWMEM_SLOTS_DESC; 1012 ngep->rx_desc = NGE_RECV_LOWMEM_SLOTS_DESC; 1013 ngep->rx_buf = NGE_RECV_LOWMEM_SLOTS_DESC * 2; 1014 ngep->nge_split = NGE_SPLIT_32; 1015 } else { 1016 ngep->default_mtu = ETHERMTU; 1017 ngep->buf_size = NGE_STD_BUFSZ; 1018 ngep->tx_desc = dev_param_p->tx_desc_num; 1019 ngep->rx_desc = dev_param_p->rx_desc_num; 1020 ngep->rx_buf = dev_param_p->rx_desc_num * 2; 1021 ngep->nge_split = dev_param_p->nge_split; 1022 } 1023 1024 nge_check_desc_prop(ngep); 1025 } 1026 1027 1028 static int 1029 nge_reset(nge_t *ngep) 1030 { 1031 int err; 1032 send_ring_t *srp = ngep->send; 1033 1034 ASSERT(mutex_owned(ngep->genlock)); 1035 mutex_enter(srp->tc_lock); 1036 mutex_enter(srp->tx_lock); 1037 1038 nge_tx_recycle_all(ngep); 1039 err = nge_reinit_ring(ngep); 1040 if (err == DDI_FAILURE) { 1041 mutex_exit(srp->tx_lock); 1042 mutex_exit(srp->tc_lock); 1043 return (err); 1044 } 1045 err = nge_chip_reset(ngep); 1046 mutex_exit(srp->tx_lock); 1047 mutex_exit(srp->tc_lock); 1048 if (err == DDI_FAILURE) 1049 return (err); 1050 ngep->watchdog = 0; 1051 ngep->resched_needed = B_FALSE; 1052 ngep->promisc = B_FALSE; 1053 ngep->param_loop_mode = NGE_LOOP_NONE; 1054 ngep->factotum_flag = 0; 1055 ngep->resched_needed = 0; 1056 ngep->nge_mac_state = NGE_MAC_RESET; 1057 ngep->max_sdu = ngep->default_mtu + ETHER_HEAD_LEN + ETHERFCSL; 1058 ngep->max_sdu += VTAG_SIZE; 1059 ngep->rx_def = 0x16; 1060 return (DDI_SUCCESS); 1061 } 1062 1063 static void 1064 nge_m_stop(void *arg) 1065 { 1066 nge_t *ngep = arg; /* private device info */ 1067 1068 NGE_TRACE(("nge_m_stop($%p)", arg)); 1069 1070 /* 1071 * If suspended, adapter is already stopped, just return. 1072 */ 1073 if (ngep->suspended) { 1074 ASSERT(ngep->nge_mac_state == NGE_MAC_STOPPED); 1075 return; 1076 } 1077 1078 /* 1079 * Just stop processing, then record new MAC state 1080 */ 1081 mutex_enter(ngep->genlock); 1082 rw_enter(ngep->rwlock, RW_WRITER); 1083 1084 (void) nge_chip_stop(ngep, B_FALSE); 1085 /* Try to wait all the buffer post to upper layer be released */ 1086 ngep->nge_mac_state = NGE_MAC_STOPPED; 1087 1088 /* Recycle all the TX BD */ 1089 nge_tx_recycle_all(ngep); 1090 nge_fini_rings(ngep); 1091 nge_free_bufs(ngep); 1092 1093 NGE_DEBUG(("nge_m_stop($%p) done", arg)); 1094 1095 rw_exit(ngep->rwlock); 1096 mutex_exit(ngep->genlock); 1097 } 1098 1099 static int 1100 nge_m_start(void *arg) 1101 { 1102 int err; 1103 nge_t *ngep = arg; 1104 1105 NGE_TRACE(("nge_m_start($%p)", arg)); 1106 /* 1107 * If suspended, don't start, as the resume processing 1108 * will recall this function with the suspended flag off. 1109 */ 1110 if (ngep->suspended) 1111 return (DDI_FAILURE); 1112 /* 1113 * Start processing and record new MAC state 1114 */ 1115 mutex_enter(ngep->genlock); 1116 rw_enter(ngep->rwlock, RW_WRITER); 1117 err = nge_alloc_bufs(ngep); 1118 if (err != DDI_SUCCESS) { 1119 nge_problem(ngep, "nge_m_start: DMA buffer allocation failed"); 1120 goto finish; 1121 } 1122 err = nge_init_rings(ngep); 1123 if (err != DDI_SUCCESS) { 1124 nge_free_bufs(ngep); 1125 nge_problem(ngep, "nge_init_rings() failed,err=%x"); 1126 goto finish; 1127 } 1128 err = nge_restart(ngep); 1129 1130 NGE_DEBUG(("nge_m_start($%p) done", arg)); 1131 finish: 1132 rw_exit(ngep->rwlock); 1133 mutex_exit(ngep->genlock); 1134 1135 return (err); 1136 } 1137 1138 static int 1139 nge_m_unicst(void *arg, const uint8_t *macaddr) 1140 { 1141 nge_t *ngep = arg; 1142 1143 NGE_TRACE(("nge_m_unicst($%p)", arg)); 1144 /* 1145 * Remember the new current address in the driver state 1146 * Sync the chip's idea of the address too ... 1147 */ 1148 mutex_enter(ngep->genlock); 1149 1150 ethaddr_copy(macaddr, ngep->cur_uni_addr.addr); 1151 ngep->cur_uni_addr.set = 1; 1152 1153 /* 1154 * If we are suspended, we want to quit now, and not update 1155 * the chip. Doing so might put it in a bad state, but the 1156 * resume will get the unicast address installed. 1157 */ 1158 if (ngep->suspended) 1159 return (DDI_SUCCESS); 1160 1161 nge_chip_sync(ngep); 1162 1163 NGE_DEBUG(("nge_m_unicst($%p) done", arg)); 1164 mutex_exit(ngep->genlock); 1165 1166 return (0); 1167 } 1168 1169 static int 1170 nge_m_promisc(void *arg, boolean_t on) 1171 { 1172 nge_t *ngep = arg; 1173 1174 NGE_TRACE(("nge_m_promisc($%p)", arg)); 1175 /* 1176 * If suspended, we don't do anything, even record the promiscuious 1177 * mode, as we won't properly set it on resume. Just fail. 1178 */ 1179 if (ngep->suspended) 1180 return (DDI_FAILURE); 1181 1182 /* 1183 * Store specified mode and pass to chip layer to update h/w 1184 */ 1185 mutex_enter(ngep->genlock); 1186 if (ngep->promisc == on) { 1187 mutex_exit(ngep->genlock); 1188 NGE_DEBUG(("nge_m_promisc($%p) done", arg)); 1189 return (0); 1190 } 1191 ngep->promisc = on; 1192 nge_chip_sync(ngep); 1193 NGE_DEBUG(("nge_m_promisc($%p) done", arg)); 1194 mutex_exit(ngep->genlock); 1195 1196 return (0); 1197 } 1198 1199 static void nge_mulparam(nge_t *ngep) 1200 { 1201 uint8_t number; 1202 ether_addr_t pand; 1203 ether_addr_t por; 1204 mul_item *plist; 1205 1206 for (number = 0; number < ETHERADDRL; number++) { 1207 pand[number] = 0x00; 1208 por[number] = 0x00; 1209 } 1210 for (plist = ngep->pcur_mulist; plist != NULL; plist = plist->next) { 1211 for (number = 0; number < ETHERADDRL; number++) { 1212 pand[number] &= plist->mul_addr[number]; 1213 por[number] |= plist->mul_addr[number]; 1214 } 1215 } 1216 for (number = 0; number < ETHERADDRL; number++) { 1217 ngep->cur_mul_addr.addr[number] 1218 = pand[number] & por[number]; 1219 ngep->cur_mul_mask.addr[number] 1220 = pand [number] | (~por[number]); 1221 } 1222 } 1223 static int 1224 nge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 1225 { 1226 boolean_t update; 1227 boolean_t b_eq; 1228 nge_t *ngep = arg; 1229 mul_item *plist; 1230 mul_item *plist_prev; 1231 mul_item *pitem; 1232 1233 NGE_TRACE(("nge_m_multicst($%p, %s, %s)", arg, 1234 (add) ? "add" : "remove", ether_sprintf((void *)mca))); 1235 1236 update = B_FALSE; 1237 plist = plist_prev = NULL; 1238 mutex_enter(ngep->genlock); 1239 if (add) { 1240 if (ngep->pcur_mulist != NULL) { 1241 for (plist = ngep->pcur_mulist; plist != NULL; 1242 plist = plist->next) { 1243 b_eq = ether_eq(plist->mul_addr, mca); 1244 if (b_eq) { 1245 plist->ref_cnt++; 1246 break; 1247 } 1248 plist_prev = plist; 1249 } 1250 } 1251 1252 if (plist == NULL) { 1253 pitem = kmem_zalloc(sizeof (mul_item), KM_SLEEP); 1254 ether_copy(mca, pitem->mul_addr); 1255 pitem ->ref_cnt++; 1256 pitem ->next = NULL; 1257 if (plist_prev == NULL) 1258 ngep->pcur_mulist = pitem; 1259 else 1260 plist_prev->next = pitem; 1261 update = B_TRUE; 1262 } 1263 } else { 1264 if (ngep->pcur_mulist != NULL) { 1265 for (plist = ngep->pcur_mulist; plist != NULL; 1266 plist = plist->next) { 1267 b_eq = ether_eq(plist->mul_addr, mca); 1268 if (b_eq) { 1269 update = B_TRUE; 1270 break; 1271 } 1272 plist_prev = plist; 1273 } 1274 1275 if (update) { 1276 if ((plist_prev == NULL) && 1277 (plist->next == NULL)) 1278 ngep->pcur_mulist = NULL; 1279 else if ((plist_prev == NULL) && 1280 (plist->next != NULL)) 1281 ngep->pcur_mulist = plist->next; 1282 else 1283 plist_prev->next = plist->next; 1284 kmem_free(plist, sizeof (mul_item)); 1285 } 1286 } 1287 } 1288 1289 if (update || !ngep->suspended) { 1290 nge_mulparam(ngep); 1291 nge_chip_sync(ngep); 1292 } 1293 NGE_DEBUG(("nge_m_multicst($%p) done", arg)); 1294 mutex_exit(ngep->genlock); 1295 1296 return (0); 1297 } 1298 1299 static void 1300 nge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 1301 { 1302 int err; 1303 int cmd; 1304 nge_t *ngep = arg; 1305 struct iocblk *iocp; 1306 enum ioc_reply status; 1307 boolean_t need_privilege; 1308 1309 /* 1310 * If suspended, we might actually be able to do some of 1311 * these ioctls, but it is harder to make sure they occur 1312 * without actually putting the hardware in an undesireable 1313 * state. So just NAK it. 1314 */ 1315 if (ngep->suspended) { 1316 miocnak(wq, mp, 0, EINVAL); 1317 return; 1318 } 1319 1320 /* 1321 * Validate the command before bothering with the mutex ... 1322 */ 1323 iocp = (struct iocblk *)mp->b_rptr; 1324 iocp->ioc_error = 0; 1325 need_privilege = B_TRUE; 1326 cmd = iocp->ioc_cmd; 1327 1328 NGE_DEBUG(("nge_m_ioctl: cmd 0x%x", cmd)); 1329 switch (cmd) { 1330 default: 1331 NGE_LDB(NGE_DBG_BADIOC, 1332 ("nge_m_ioctl: unknown cmd 0x%x", cmd)); 1333 1334 miocnak(wq, mp, 0, EINVAL); 1335 return; 1336 1337 case NGE_MII_READ: 1338 case NGE_MII_WRITE: 1339 case NGE_SEE_READ: 1340 case NGE_SEE_WRITE: 1341 case NGE_DIAG: 1342 case NGE_PEEK: 1343 case NGE_POKE: 1344 case NGE_PHY_RESET: 1345 case NGE_SOFT_RESET: 1346 case NGE_HARD_RESET: 1347 break; 1348 1349 case LB_GET_INFO_SIZE: 1350 case LB_GET_INFO: 1351 case LB_GET_MODE: 1352 need_privilege = B_FALSE; 1353 break; 1354 case LB_SET_MODE: 1355 break; 1356 1357 case ND_GET: 1358 need_privilege = B_FALSE; 1359 break; 1360 case ND_SET: 1361 break; 1362 } 1363 1364 if (need_privilege) { 1365 /* 1366 * Check for specific net_config privilege. 1367 */ 1368 err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 1369 if (err != 0) { 1370 NGE_DEBUG(("nge_m_ioctl: rejected cmd 0x%x, err %d", 1371 cmd, err)); 1372 miocnak(wq, mp, 0, err); 1373 return; 1374 } 1375 } 1376 1377 mutex_enter(ngep->genlock); 1378 1379 switch (cmd) { 1380 default: 1381 _NOTE(NOTREACHED) 1382 status = IOC_INVAL; 1383 break; 1384 1385 case NGE_MII_READ: 1386 case NGE_MII_WRITE: 1387 case NGE_SEE_READ: 1388 case NGE_SEE_WRITE: 1389 case NGE_DIAG: 1390 case NGE_PEEK: 1391 case NGE_POKE: 1392 case NGE_PHY_RESET: 1393 case NGE_SOFT_RESET: 1394 case NGE_HARD_RESET: 1395 status = nge_chip_ioctl(ngep, mp, iocp); 1396 break; 1397 1398 case LB_GET_INFO_SIZE: 1399 case LB_GET_INFO: 1400 case LB_GET_MODE: 1401 case LB_SET_MODE: 1402 status = nge_loop_ioctl(ngep, mp, iocp); 1403 break; 1404 1405 case ND_GET: 1406 case ND_SET: 1407 status = nge_nd_ioctl(ngep, wq, mp, iocp); 1408 break; 1409 1410 } 1411 1412 /* 1413 * Do we need to reprogram the PHY and/or the MAC? 1414 * Do it now, while we still have the mutex. 1415 * 1416 * Note: update the PHY first, 'cos it controls the 1417 * speed/duplex parameters that the MAC code uses. 1418 */ 1419 1420 NGE_DEBUG(("nge_m_ioctl: cmd 0x%x status %d", cmd, status)); 1421 1422 switch (status) { 1423 case IOC_RESTART_REPLY: 1424 case IOC_RESTART_ACK: 1425 (*ngep->physops->phys_update)(ngep); 1426 nge_chip_sync(ngep); 1427 break; 1428 1429 default: 1430 break; 1431 } 1432 1433 mutex_exit(ngep->genlock); 1434 1435 /* 1436 * Finally, decide how to reply 1437 */ 1438 switch (status) { 1439 1440 default: 1441 case IOC_INVAL: 1442 miocnak(wq, mp, 0, iocp->ioc_error == 0 ? 1443 EINVAL : iocp->ioc_error); 1444 break; 1445 1446 case IOC_DONE: 1447 break; 1448 1449 case IOC_RESTART_ACK: 1450 case IOC_ACK: 1451 miocack(wq, mp, 0, 0); 1452 break; 1453 1454 case IOC_RESTART_REPLY: 1455 case IOC_REPLY: 1456 mp->b_datap->db_type = iocp->ioc_error == 0 ? 1457 M_IOCACK : M_IOCNAK; 1458 qreply(wq, mp); 1459 break; 1460 } 1461 } 1462 1463 /* ARGSUSED */ 1464 static boolean_t 1465 nge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 1466 { 1467 nge_t *ngep = arg; 1468 nge_dev_spec_param_t *dev_param_p; 1469 1470 dev_param_p = &ngep->dev_spec_param; 1471 1472 switch (cap) { 1473 case MAC_CAPAB_HCKSUM: { 1474 uint32_t *hcksum_txflags = cap_data; 1475 1476 if (dev_param_p->tx_hw_checksum) { 1477 *hcksum_txflags = dev_param_p->tx_hw_checksum; 1478 } else 1479 return (B_FALSE); 1480 break; 1481 } 1482 case MAC_CAPAB_POLL: 1483 /* 1484 * There's nothing for us to fill in, simply returning 1485 * B_TRUE, stating that we support polling is sufficient. 1486 */ 1487 break; 1488 default: 1489 return (B_FALSE); 1490 } 1491 return (B_TRUE); 1492 } 1493 1494 #undef NGE_DBG 1495 #define NGE_DBG NGE_DBG_INIT /* debug flag for this code */ 1496 int 1497 nge_restart(nge_t *ngep) 1498 { 1499 int err = 0; 1500 err += nge_reset(ngep); 1501 err += nge_chip_start(ngep); 1502 1503 if (err) { 1504 ngep->nge_mac_state = NGE_MAC_STOPPED; 1505 return (DDI_FAILURE); 1506 } else { 1507 ngep->nge_mac_state = NGE_MAC_STARTED; 1508 return (DDI_SUCCESS); 1509 } 1510 } 1511 1512 void 1513 nge_wake_factotum(nge_t *ngep) 1514 { 1515 mutex_enter(ngep->softlock); 1516 if (ngep->factotum_flag == 0) { 1517 ngep->factotum_flag = 1; 1518 (void) ddi_intr_trigger_softint(ngep->factotum_hdl, NULL); 1519 } 1520 mutex_exit(ngep->softlock); 1521 } 1522 1523 /* 1524 * High-level cyclic handler 1525 * 1526 * This routine schedules a (low-level) softint callback to the 1527 * factotum. 1528 */ 1529 1530 static void 1531 nge_chip_cyclic(void *arg) 1532 { 1533 nge_t *ngep; 1534 1535 ngep = (nge_t *)arg; 1536 1537 switch (ngep->nge_chip_state) { 1538 default: 1539 return; 1540 1541 case NGE_CHIP_RUNNING: 1542 break; 1543 1544 case NGE_CHIP_FAULT: 1545 case NGE_CHIP_ERROR: 1546 break; 1547 } 1548 1549 nge_wake_factotum(ngep); 1550 } 1551 1552 static void 1553 nge_unattach(nge_t *ngep) 1554 { 1555 send_ring_t *srp; 1556 buff_ring_t *brp; 1557 1558 srp = ngep->send; 1559 brp = ngep->buff; 1560 NGE_TRACE(("nge_unattach($%p)", (void *)ngep)); 1561 1562 /* 1563 * Flag that no more activity may be initiated 1564 */ 1565 ngep->progress &= ~PROGRESS_READY; 1566 ngep->nge_mac_state = NGE_MAC_UNATTACH; 1567 1568 /* 1569 * Quiesce the PHY and MAC (leave it reset but still powered). 1570 * Clean up and free all NGE data structures 1571 */ 1572 if (ngep->periodic_id != NULL) { 1573 ddi_periodic_delete(ngep->periodic_id); 1574 ngep->periodic_id = NULL; 1575 } 1576 1577 if (ngep->progress & PROGRESS_KSTATS) 1578 nge_fini_kstats(ngep); 1579 1580 if (ngep->progress & PROGRESS_NDD) 1581 nge_nd_cleanup(ngep); 1582 1583 if (ngep->progress & PROGRESS_HWINT) { 1584 mutex_enter(ngep->genlock); 1585 nge_restore_mac_addr(ngep); 1586 (void) nge_chip_stop(ngep, B_FALSE); 1587 mutex_exit(ngep->genlock); 1588 } 1589 1590 if (ngep->progress & PROGRESS_SWINT) 1591 nge_rem_intrs(ngep); 1592 1593 if (ngep->progress & PROGRESS_FACTOTUM) 1594 (void) ddi_intr_remove_softint(ngep->factotum_hdl); 1595 1596 if (ngep->progress & PROGRESS_RESCHED) 1597 (void) ddi_intr_remove_softint(ngep->resched_hdl); 1598 1599 if (ngep->progress & PROGRESS_INTR) { 1600 mutex_destroy(srp->tx_lock); 1601 mutex_destroy(srp->tc_lock); 1602 mutex_destroy(&srp->dmah_lock); 1603 mutex_destroy(brp->recycle_lock); 1604 1605 mutex_destroy(ngep->genlock); 1606 mutex_destroy(ngep->softlock); 1607 rw_destroy(ngep->rwlock); 1608 } 1609 1610 if (ngep->progress & PROGRESS_REGS) 1611 ddi_regs_map_free(&ngep->io_handle); 1612 1613 if (ngep->progress & PROGRESS_CFG) 1614 pci_config_teardown(&ngep->cfg_handle); 1615 1616 ddi_remove_minor_node(ngep->devinfo, NULL); 1617 1618 kmem_free(ngep, sizeof (*ngep)); 1619 } 1620 1621 static int 1622 nge_resume(dev_info_t *devinfo) 1623 { 1624 nge_t *ngep; 1625 chip_info_t *infop; 1626 1627 ASSERT(devinfo != NULL); 1628 1629 ngep = ddi_get_driver_private(devinfo); 1630 /* 1631 * If there are state inconsistancies, this is bad. Returning 1632 * DDI_FAILURE here will eventually cause the machine to panic, 1633 * so it is best done here so that there is a possibility of 1634 * debugging the problem. 1635 */ 1636 if (ngep == NULL) 1637 cmn_err(CE_PANIC, 1638 "nge: ngep returned from ddi_get_driver_private was NULL"); 1639 infop = (chip_info_t *)&ngep->chipinfo; 1640 1641 if (ngep->devinfo != devinfo) 1642 cmn_err(CE_PANIC, 1643 "nge: passed devinfo not the same as saved definfo"); 1644 1645 ngep->suspended = B_FALSE; 1646 1647 /* 1648 * Fetch the config space. Even though we have most of it cached, 1649 * some values *might* change across a suspend/resume. 1650 */ 1651 nge_chip_cfg_init(ngep, infop, B_FALSE); 1652 1653 /* 1654 * Start the controller. In this case (and probably most GLDv3 1655 * devices), it is sufficient to call nge_m_start(). 1656 */ 1657 if (nge_m_start((void *)ngep) != DDI_SUCCESS) { 1658 /* 1659 * We note the failure, but return success, as the 1660 * system is still usable without this controller. 1661 */ 1662 cmn_err(CE_WARN, "nge: resume: failed to restart controller"); 1663 } 1664 return (DDI_SUCCESS); 1665 } 1666 1667 /* 1668 * attach(9E) -- Attach a device to the system 1669 * 1670 * Called once for each board successfully probed. 1671 */ 1672 static int 1673 nge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 1674 { 1675 int err; 1676 int i; 1677 int instance; 1678 caddr_t regs; 1679 nge_t *ngep; 1680 chip_info_t *infop; 1681 mac_register_t *macp; 1682 1683 switch (cmd) { 1684 default: 1685 return (DDI_FAILURE); 1686 1687 case DDI_RESUME: 1688 return (nge_resume(devinfo)); 1689 1690 case DDI_ATTACH: 1691 break; 1692 } 1693 1694 ngep = kmem_zalloc(sizeof (*ngep), KM_SLEEP); 1695 instance = ddi_get_instance(devinfo); 1696 ddi_set_driver_private(devinfo, ngep); 1697 ngep->devinfo = devinfo; 1698 1699 (void) snprintf(ngep->ifname, sizeof (ngep->ifname), "%s%d", 1700 NGE_DRIVER_NAME, instance); 1701 err = pci_config_setup(devinfo, &ngep->cfg_handle); 1702 if (err != DDI_SUCCESS) { 1703 nge_problem(ngep, "nge_attach: pci_config_setup() failed"); 1704 goto attach_fail; 1705 } 1706 infop = (chip_info_t *)&ngep->chipinfo; 1707 nge_chip_cfg_init(ngep, infop, B_FALSE); 1708 nge_init_dev_spec_param(ngep); 1709 nge_get_props(ngep); 1710 ngep->progress |= PROGRESS_CFG; 1711 1712 err = ddi_regs_map_setup(devinfo, NGE_PCI_OPREGS_RNUMBER, 1713 ®s, 0, 0, &nge_reg_accattr, &ngep->io_handle); 1714 if (err != DDI_SUCCESS) { 1715 nge_problem(ngep, "nge_attach: ddi_regs_map_setup() failed"); 1716 goto attach_fail; 1717 } 1718 ngep->io_regs = regs; 1719 ngep->progress |= PROGRESS_REGS; 1720 1721 err = nge_register_intrs_and_init_locks(ngep); 1722 if (err != DDI_SUCCESS) { 1723 nge_problem(ngep, "nge_attach:" 1724 " register intrs and init locks failed"); 1725 goto attach_fail; 1726 } 1727 nge_init_ring_param_lock(ngep); 1728 ngep->progress |= PROGRESS_INTR; 1729 1730 mutex_enter(ngep->genlock); 1731 1732 /* 1733 * Initialise link state variables 1734 * Stop, reset & reinitialise the chip. 1735 * Initialise the (internal) PHY. 1736 */ 1737 nge_phys_init(ngep); 1738 err = nge_chip_reset(ngep); 1739 if (err != DDI_SUCCESS) { 1740 nge_problem(ngep, "nge_attach: nge_chip_reset() failed"); 1741 mutex_exit(ngep->genlock); 1742 goto attach_fail; 1743 } 1744 nge_chip_sync(ngep); 1745 1746 /* 1747 * Now that mutex locks are initialized, enable interrupts. 1748 */ 1749 if (ngep->intr_cap & DDI_INTR_FLAG_BLOCK) { 1750 /* Call ddi_intr_block_enable() for MSI interrupts */ 1751 (void) ddi_intr_block_enable(ngep->htable, 1752 ngep->intr_actual_cnt); 1753 } else { 1754 /* Call ddi_intr_enable for MSI or FIXED interrupts */ 1755 for (i = 0; i < ngep->intr_actual_cnt; i++) { 1756 (void) ddi_intr_enable(ngep->htable[i]); 1757 } 1758 } 1759 1760 ngep->link_state = LINK_STATE_UNKNOWN; 1761 ngep->progress |= PROGRESS_HWINT; 1762 1763 /* 1764 * Register NDD-tweakable parameters 1765 */ 1766 if (nge_nd_init(ngep)) { 1767 nge_problem(ngep, "nge_attach: nge_nd_init() failed"); 1768 mutex_exit(ngep->genlock); 1769 goto attach_fail; 1770 } 1771 ngep->progress |= PROGRESS_NDD; 1772 1773 /* 1774 * Create & initialise named kstats 1775 */ 1776 nge_init_kstats(ngep, instance); 1777 ngep->progress |= PROGRESS_KSTATS; 1778 1779 mutex_exit(ngep->genlock); 1780 1781 if ((macp = mac_alloc(MAC_VERSION)) == NULL) 1782 goto attach_fail; 1783 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 1784 macp->m_driver = ngep; 1785 macp->m_dip = devinfo; 1786 macp->m_src_addr = infop->vendor_addr.addr; 1787 macp->m_callbacks = &nge_m_callbacks; 1788 macp->m_min_sdu = 0; 1789 macp->m_max_sdu = ngep->default_mtu; 1790 /* 1791 * Finally, we're ready to register ourselves with the mac 1792 * interface; if this succeeds, we're all ready to start() 1793 */ 1794 err = mac_register(macp, &ngep->mh); 1795 mac_free(macp); 1796 if (err != 0) 1797 goto attach_fail; 1798 1799 /* 1800 * Register a periodical handler. 1801 * nge_chip_cyclic() is invoked in kernel context. 1802 */ 1803 ngep->periodic_id = ddi_periodic_add(nge_chip_cyclic, ngep, 1804 NGE_CYCLIC_PERIOD, DDI_IPL_0); 1805 1806 ngep->progress |= PROGRESS_READY; 1807 return (DDI_SUCCESS); 1808 1809 attach_fail: 1810 nge_unattach(ngep); 1811 return (DDI_FAILURE); 1812 } 1813 1814 /* 1815 * detach(9E) -- Detach a device from the system 1816 */ 1817 static int 1818 nge_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 1819 { 1820 int i; 1821 nge_t *ngep; 1822 mul_item *p, *nextp; 1823 buff_ring_t *brp; 1824 1825 NGE_GTRACE(("nge_detach($%p, %d)", (void *)devinfo, cmd)); 1826 1827 ngep = ddi_get_driver_private(devinfo); 1828 brp = ngep->buff; 1829 1830 switch (cmd) { 1831 default: 1832 return (DDI_FAILURE); 1833 1834 case DDI_SUSPEND: 1835 /* 1836 * Stop the NIC 1837 * I suspect that we can actually suspend if the stop 1838 * routine returns a failure, as the resume will 1839 * effectively fully reset the hardware (i.e. we don't 1840 * really save any hardware state). However, nge_m_stop 1841 * doesn't return an error code. 1842 * Note: This driver doesn't currently support WOL, but 1843 * should it in the future, it is important to 1844 * make sure the PHY remains powered so that the 1845 * wakeup packet can actually be recieved. 1846 */ 1847 nge_m_stop(ngep); 1848 ngep->suspended = B_TRUE; 1849 return (DDI_SUCCESS); 1850 1851 case DDI_DETACH: 1852 break; 1853 } 1854 1855 /* Try to wait all the buffer post to upper layer be released */ 1856 for (i = 0; i < 1000; i++) { 1857 if (brp->rx_hold == 0) 1858 break; 1859 drv_usecwait(1000); 1860 } 1861 1862 /* If there is any posted buffer, reject to detach */ 1863 if (brp->rx_hold != 0) 1864 return (DDI_FAILURE); 1865 1866 /* Recycle the multicast table */ 1867 for (p = ngep->pcur_mulist; p != NULL; p = nextp) { 1868 nextp = p->next; 1869 kmem_free(p, sizeof (mul_item)); 1870 } 1871 ngep->pcur_mulist = NULL; 1872 1873 /* 1874 * Unregister from the GLD subsystem. This can fail, in 1875 * particular if there are DLPI style-2 streams still open - 1876 * in which case we just return failure without shutting 1877 * down chip operations. 1878 */ 1879 if (mac_unregister(ngep->mh) != DDI_SUCCESS) 1880 return (DDI_FAILURE); 1881 1882 /* 1883 * All activity stopped, so we can clean up & exit 1884 */ 1885 nge_unattach(ngep); 1886 return (DDI_SUCCESS); 1887 } 1888 1889 1890 /* 1891 * ========== Module Loading Data & Entry Points ========== 1892 */ 1893 1894 DDI_DEFINE_STREAM_OPS(nge_dev_ops, nulldev, nulldev, nge_attach, nge_detach, 1895 nodev, NULL, D_MP, NULL); 1896 1897 1898 static struct modldrv nge_modldrv = { 1899 &mod_driverops, /* Type of module. This one is a driver */ 1900 nge_ident, /* short description */ 1901 &nge_dev_ops /* driver specific ops */ 1902 }; 1903 1904 static struct modlinkage modlinkage = { 1905 MODREV_1, (void *)&nge_modldrv, NULL 1906 }; 1907 1908 1909 int 1910 _info(struct modinfo *modinfop) 1911 { 1912 return (mod_info(&modlinkage, modinfop)); 1913 } 1914 1915 int 1916 _init(void) 1917 { 1918 int status; 1919 1920 mac_init_ops(&nge_dev_ops, "nge"); 1921 status = mod_install(&modlinkage); 1922 if (status != DDI_SUCCESS) 1923 mac_fini_ops(&nge_dev_ops); 1924 else 1925 mutex_init(nge_log_mutex, NULL, MUTEX_DRIVER, NULL); 1926 1927 return (status); 1928 } 1929 1930 int 1931 _fini(void) 1932 { 1933 int status; 1934 1935 status = mod_remove(&modlinkage); 1936 if (status == DDI_SUCCESS) { 1937 mac_fini_ops(&nge_dev_ops); 1938 mutex_destroy(nge_log_mutex); 1939 } 1940 1941 return (status); 1942 } 1943 1944 /* 1945 * ============ Init MSI/Fixed/SoftInterrupt routines ============== 1946 */ 1947 1948 /* 1949 * Register interrupts and initialize each mutex and condition variables 1950 */ 1951 1952 static int 1953 nge_register_intrs_and_init_locks(nge_t *ngep) 1954 { 1955 int err; 1956 int intr_types; 1957 uint_t soft_prip; 1958 nge_msi_mask msi_mask; 1959 nge_msi_map0_vec map0_vec; 1960 nge_msi_map1_vec map1_vec; 1961 1962 /* 1963 * Add the softint handlers: 1964 * 1965 * Both of these handlers are used to avoid restrictions on the 1966 * context and/or mutexes required for some operations. In 1967 * particular, the hardware interrupt handler and its subfunctions 1968 * can detect a number of conditions that we don't want to handle 1969 * in that context or with that set of mutexes held. So, these 1970 * softints are triggered instead: 1971 * 1972 * the <resched> softint is triggered if if we have previously 1973 * had to refuse to send a packet because of resource shortage 1974 * (we've run out of transmit buffers), but the send completion 1975 * interrupt handler has now detected that more buffers have 1976 * become available. Its only purpose is to call gld_sched() 1977 * to retry the pending transmits (we're not allowed to hold 1978 * driver-defined mutexes across gld_sched()). 1979 * 1980 * the <factotum> is triggered if the h/w interrupt handler 1981 * sees the <link state changed> or <error> bits in the status 1982 * block. It's also triggered periodically to poll the link 1983 * state, just in case we aren't getting link status change 1984 * interrupts ... 1985 */ 1986 err = ddi_intr_add_softint(ngep->devinfo, &ngep->resched_hdl, 1987 DDI_INTR_SOFTPRI_MIN, nge_reschedule, (caddr_t)ngep); 1988 if (err != DDI_SUCCESS) { 1989 nge_problem(ngep, 1990 "nge_attach: add nge_reschedule softintr failed"); 1991 1992 return (DDI_FAILURE); 1993 } 1994 ngep->progress |= PROGRESS_RESCHED; 1995 err = ddi_intr_add_softint(ngep->devinfo, &ngep->factotum_hdl, 1996 DDI_INTR_SOFTPRI_MIN, nge_chip_factotum, (caddr_t)ngep); 1997 if (err != DDI_SUCCESS) { 1998 nge_problem(ngep, 1999 "nge_attach: add nge_chip_factotum softintr failed!"); 2000 2001 return (DDI_FAILURE); 2002 } 2003 if (ddi_intr_get_softint_pri(ngep->factotum_hdl, &soft_prip) 2004 != DDI_SUCCESS) { 2005 nge_problem(ngep, "nge_attach: get softintr priority failed\n"); 2006 2007 return (DDI_FAILURE); 2008 } 2009 ngep->soft_pri = soft_prip; 2010 2011 ngep->progress |= PROGRESS_FACTOTUM; 2012 /* Get supported interrupt types */ 2013 if (ddi_intr_get_supported_types(ngep->devinfo, &intr_types) 2014 != DDI_SUCCESS) { 2015 nge_error(ngep, "ddi_intr_get_supported_types failed\n"); 2016 2017 return (DDI_FAILURE); 2018 } 2019 2020 NGE_DEBUG(("ddi_intr_get_supported_types() returned: %x", 2021 intr_types)); 2022 2023 if ((intr_types & DDI_INTR_TYPE_MSI) && nge_enable_msi) { 2024 2025 /* MSI Configurations for mcp55 chipset */ 2026 if (ngep->chipinfo.device == DEVICE_ID_MCP55_373 || 2027 ngep->chipinfo.device == DEVICE_ID_MCP55_372) { 2028 2029 2030 /* Enable the 8 vectors */ 2031 msi_mask.msi_mask_val = 2032 nge_reg_get32(ngep, NGE_MSI_MASK); 2033 msi_mask.msi_msk_bits.vec0 = NGE_SET; 2034 msi_mask.msi_msk_bits.vec1 = NGE_SET; 2035 msi_mask.msi_msk_bits.vec2 = NGE_SET; 2036 msi_mask.msi_msk_bits.vec3 = NGE_SET; 2037 msi_mask.msi_msk_bits.vec4 = NGE_SET; 2038 msi_mask.msi_msk_bits.vec5 = NGE_SET; 2039 msi_mask.msi_msk_bits.vec6 = NGE_SET; 2040 msi_mask.msi_msk_bits.vec7 = NGE_SET; 2041 nge_reg_put32(ngep, NGE_MSI_MASK, 2042 msi_mask.msi_mask_val); 2043 2044 /* 2045 * Remapping the MSI MAP0 and MAP1. MCP55 2046 * is default mapping all the interrupt to 0 vector. 2047 * Software needs to remapping this. 2048 * This mapping is same as CK804. 2049 */ 2050 map0_vec.msi_map0_val = 2051 nge_reg_get32(ngep, NGE_MSI_MAP0); 2052 map1_vec.msi_map1_val = 2053 nge_reg_get32(ngep, NGE_MSI_MAP1); 2054 map0_vec.vecs_bits.reint_vec = 0; 2055 map0_vec.vecs_bits.rcint_vec = 0; 2056 map0_vec.vecs_bits.miss_vec = 3; 2057 map0_vec.vecs_bits.teint_vec = 5; 2058 map0_vec.vecs_bits.tcint_vec = 5; 2059 map0_vec.vecs_bits.stint_vec = 2; 2060 map0_vec.vecs_bits.mint_vec = 6; 2061 map0_vec.vecs_bits.rfint_vec = 0; 2062 map1_vec.vecs_bits.tfint_vec = 5; 2063 map1_vec.vecs_bits.feint_vec = 6; 2064 map1_vec.vecs_bits.resv8_11 = 3; 2065 map1_vec.vecs_bits.resv12_15 = 1; 2066 map1_vec.vecs_bits.resv16_19 = 0; 2067 map1_vec.vecs_bits.resv20_23 = 7; 2068 map1_vec.vecs_bits.resv24_31 = 0xff; 2069 nge_reg_put32(ngep, NGE_MSI_MAP0, 2070 map0_vec.msi_map0_val); 2071 nge_reg_put32(ngep, NGE_MSI_MAP1, 2072 map1_vec.msi_map1_val); 2073 } 2074 if (nge_add_intrs(ngep, DDI_INTR_TYPE_MSI) != DDI_SUCCESS) { 2075 NGE_DEBUG(("MSI registration failed, " 2076 "trying FIXED interrupt type\n")); 2077 } else { 2078 nge_log(ngep, "Using MSI interrupt type\n"); 2079 2080 ngep->intr_type = DDI_INTR_TYPE_MSI; 2081 ngep->progress |= PROGRESS_SWINT; 2082 } 2083 } 2084 2085 if (!(ngep->progress & PROGRESS_SWINT) && 2086 (intr_types & DDI_INTR_TYPE_FIXED)) { 2087 if (nge_add_intrs(ngep, DDI_INTR_TYPE_FIXED) != DDI_SUCCESS) { 2088 nge_error(ngep, "FIXED interrupt " 2089 "registration failed\n"); 2090 2091 return (DDI_FAILURE); 2092 } 2093 2094 nge_log(ngep, "Using FIXED interrupt type\n"); 2095 2096 ngep->intr_type = DDI_INTR_TYPE_FIXED; 2097 ngep->progress |= PROGRESS_SWINT; 2098 } 2099 2100 2101 if (!(ngep->progress & PROGRESS_SWINT)) { 2102 nge_error(ngep, "No interrupts registered\n"); 2103 2104 return (DDI_FAILURE); 2105 } 2106 mutex_init(ngep->genlock, NULL, MUTEX_DRIVER, 2107 DDI_INTR_PRI(ngep->intr_pri)); 2108 mutex_init(ngep->softlock, NULL, MUTEX_DRIVER, 2109 DDI_INTR_PRI(ngep->soft_pri)); 2110 rw_init(ngep->rwlock, NULL, RW_DRIVER, 2111 DDI_INTR_PRI(ngep->intr_pri)); 2112 2113 return (DDI_SUCCESS); 2114 } 2115 2116 /* 2117 * nge_add_intrs: 2118 * 2119 * Register FIXED or MSI interrupts. 2120 */ 2121 static int 2122 nge_add_intrs(nge_t *ngep, int intr_type) 2123 { 2124 dev_info_t *dip = ngep->devinfo; 2125 int avail, actual, intr_size, count = 0; 2126 int i, flag, ret; 2127 2128 NGE_DEBUG(("nge_add_intrs: interrupt type 0x%x\n", intr_type)); 2129 2130 /* Get number of interrupts */ 2131 ret = ddi_intr_get_nintrs(dip, intr_type, &count); 2132 if ((ret != DDI_SUCCESS) || (count == 0)) { 2133 nge_error(ngep, "ddi_intr_get_nintrs() failure, ret: %d, " 2134 "count: %d", ret, count); 2135 2136 return (DDI_FAILURE); 2137 } 2138 2139 /* Get number of available interrupts */ 2140 ret = ddi_intr_get_navail(dip, intr_type, &avail); 2141 if ((ret != DDI_SUCCESS) || (avail == 0)) { 2142 nge_error(ngep, "ddi_intr_get_navail() failure, " 2143 "ret: %d, avail: %d\n", ret, avail); 2144 2145 return (DDI_FAILURE); 2146 } 2147 2148 if (avail < count) { 2149 NGE_DEBUG(("nitrs() returned %d, navail returned %d\n", 2150 count, avail)); 2151 } 2152 flag = DDI_INTR_ALLOC_NORMAL; 2153 2154 /* Allocate an array of interrupt handles */ 2155 intr_size = count * sizeof (ddi_intr_handle_t); 2156 ngep->htable = kmem_alloc(intr_size, KM_SLEEP); 2157 2158 /* Call ddi_intr_alloc() */ 2159 ret = ddi_intr_alloc(dip, ngep->htable, intr_type, 0, 2160 count, &actual, flag); 2161 2162 if ((ret != DDI_SUCCESS) || (actual == 0)) { 2163 nge_error(ngep, "ddi_intr_alloc() failed %d\n", ret); 2164 2165 kmem_free(ngep->htable, intr_size); 2166 return (DDI_FAILURE); 2167 } 2168 2169 if (actual < count) { 2170 NGE_DEBUG(("Requested: %d, Received: %d\n", 2171 count, actual)); 2172 } 2173 2174 ngep->intr_actual_cnt = actual; 2175 ngep->intr_req_cnt = count; 2176 2177 /* 2178 * Get priority for first msi, assume remaining are all the same 2179 */ 2180 if ((ret = ddi_intr_get_pri(ngep->htable[0], &ngep->intr_pri)) != 2181 DDI_SUCCESS) { 2182 nge_error(ngep, "ddi_intr_get_pri() failed %d\n", ret); 2183 2184 /* Free already allocated intr */ 2185 for (i = 0; i < actual; i++) { 2186 (void) ddi_intr_free(ngep->htable[i]); 2187 } 2188 2189 kmem_free(ngep->htable, intr_size); 2190 2191 return (DDI_FAILURE); 2192 } 2193 /* Test for high level mutex */ 2194 if (ngep->intr_pri >= ddi_intr_get_hilevel_pri()) { 2195 nge_error(ngep, "nge_add_intrs:" 2196 "Hi level interrupt not supported"); 2197 2198 for (i = 0; i < actual; i++) 2199 (void) ddi_intr_free(ngep->htable[i]); 2200 2201 kmem_free(ngep->htable, intr_size); 2202 2203 return (DDI_FAILURE); 2204 } 2205 2206 2207 /* Call ddi_intr_add_handler() */ 2208 for (i = 0; i < actual; i++) { 2209 if ((ret = ddi_intr_add_handler(ngep->htable[i], nge_chip_intr, 2210 (caddr_t)ngep, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) { 2211 nge_error(ngep, "ddi_intr_add_handler() " 2212 "failed %d\n", ret); 2213 2214 /* Free already allocated intr */ 2215 for (i = 0; i < actual; i++) { 2216 (void) ddi_intr_free(ngep->htable[i]); 2217 } 2218 2219 kmem_free(ngep->htable, intr_size); 2220 2221 return (DDI_FAILURE); 2222 } 2223 } 2224 2225 if ((ret = ddi_intr_get_cap(ngep->htable[0], &ngep->intr_cap)) 2226 != DDI_SUCCESS) { 2227 nge_error(ngep, "ddi_intr_get_cap() failed %d\n", ret); 2228 2229 for (i = 0; i < actual; i++) { 2230 (void) ddi_intr_remove_handler(ngep->htable[i]); 2231 (void) ddi_intr_free(ngep->htable[i]); 2232 } 2233 2234 kmem_free(ngep->htable, intr_size); 2235 2236 return (DDI_FAILURE); 2237 } 2238 2239 return (DDI_SUCCESS); 2240 } 2241 2242 /* 2243 * nge_rem_intrs: 2244 * 2245 * Unregister FIXED or MSI interrupts 2246 */ 2247 static void 2248 nge_rem_intrs(nge_t *ngep) 2249 { 2250 int i; 2251 2252 NGE_DEBUG(("nge_rem_intrs\n")); 2253 2254 /* Disable all interrupts */ 2255 if (ngep->intr_cap & DDI_INTR_FLAG_BLOCK) { 2256 /* Call ddi_intr_block_disable() */ 2257 (void) ddi_intr_block_disable(ngep->htable, 2258 ngep->intr_actual_cnt); 2259 } else { 2260 for (i = 0; i < ngep->intr_actual_cnt; i++) { 2261 (void) ddi_intr_disable(ngep->htable[i]); 2262 } 2263 } 2264 2265 /* Call ddi_intr_remove_handler() */ 2266 for (i = 0; i < ngep->intr_actual_cnt; i++) { 2267 (void) ddi_intr_remove_handler(ngep->htable[i]); 2268 (void) ddi_intr_free(ngep->htable[i]); 2269 } 2270 2271 kmem_free(ngep->htable, 2272 ngep->intr_req_cnt * sizeof (ddi_intr_handle_t)); 2273 } 2274