1 /* 2 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 2001-2006 Advanced Micro Devices, Inc. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions are met: 11 * 12 * + Redistributions of source code must retain the above copyright notice, 13 * + this list of conditions and the following disclaimer. 14 * 15 * + Redistributions in binary form must reproduce the above copyright 16 * + notice, this list of conditions and the following disclaimer in the 17 * + documentation and/or other materials provided with the distribution. 18 * 19 * + Neither the name of Advanced Micro Devices, Inc. nor the names of its 20 * + contributors may be used to endorse or promote products derived from 21 * + this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 24 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. OR 28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 34 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 35 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Import/Export/Re-Export/Use/Release/Transfer Restrictions and 38 * Compliance with Applicable Laws. Notice is hereby given that 39 * the software may be subject to restrictions on use, release, 40 * transfer, importation, exportation and/or re-exportation under 41 * the laws and regulations of the United States or other 42 * countries ("Applicable Laws"), which include but are not 43 * limited to U.S. export control laws such as the Export 44 * Administration Regulations and national security controls as 45 * defined thereunder, as well as State Department controls under 46 * the U.S. Munitions List. Permission to use and/or 47 * redistribute the software is conditioned upon compliance with 48 * all Applicable Laws, including U.S. export control laws 49 * regarding specifically designated persons, countries and 50 * nationals of countries subject to national security controls. 51 */ 52 53 /* include files */ 54 #include <sys/disp.h> 55 #include <sys/atomic.h> 56 #include <sys/vlan.h> 57 #include "amd8111s_main.h" 58 59 /* Global macro Definations */ 60 #define ROUNDUP(x, a) (((x) + (a) - 1) & ~((a) - 1)) 61 #define INTERFACE_NAME "amd8111s" 62 #define AMD8111S_SPLIT 128 63 #define AMD8111S_SEND_MAX 64 64 65 static char ident[] = "AMD8111 10/100M Ethernet"; 66 67 /* 68 * Driver Entry Points 69 */ 70 static int amd8111s_attach(dev_info_t *, ddi_attach_cmd_t); 71 static int amd8111s_detach(dev_info_t *, ddi_detach_cmd_t); 72 73 /* 74 * GLD Entry points prototype 75 */ 76 static int amd8111s_m_unicst(void *, const uint8_t *); 77 static int amd8111s_m_promisc(void *, boolean_t); 78 static int amd8111s_m_stat(void *, uint_t, uint64_t *); 79 static void amd8111s_m_ioctl(void *, queue_t *, mblk_t *); 80 static int amd8111s_m_multicst(void *, boolean_t, const uint8_t *addr); 81 static int amd8111s_m_start(void *); 82 static void amd8111s_m_stop(void *); 83 static mblk_t *amd8111s_m_tx(void *, mblk_t *mp); 84 static uint_t amd8111s_intr(caddr_t); 85 86 static int amd8111s_unattach(dev_info_t *, struct LayerPointers *); 87 88 static boolean_t amd8111s_allocate_buffers(struct LayerPointers *); 89 static int amd8111s_odlInit(struct LayerPointers *); 90 static boolean_t amd8111s_allocate_descriptors(struct LayerPointers *); 91 static void amd8111s_free_descriptors(struct LayerPointers *); 92 static boolean_t amd8111s_alloc_dma_ringbuf(struct LayerPointers *, 93 struct amd8111s_dma_ringbuf *, uint32_t, uint32_t); 94 static void amd8111s_free_dma_ringbuf(struct amd8111s_dma_ringbuf *); 95 96 97 static void amd8111s_log(struct LayerPointers *adapter, int level, 98 char *fmt, ...); 99 100 static struct cb_ops amd8111s_cb_ops = { 101 nulldev, 102 nulldev, 103 nodev, 104 nodev, 105 nodev, 106 nodev, 107 nodev, 108 nodev, 109 nodev, 110 nodev, 111 nodev, 112 nochpoll, 113 ddi_prop_op, 114 NULL, 115 D_NEW | D_MP, 116 CB_REV, /* cb_rev */ 117 nodev, /* cb_aread */ 118 nodev /* cb_awrite */ 119 }; 120 121 static struct dev_ops amd8111s_dev_ops = { 122 DEVO_REV, /* devo_rev */ 123 0, /* devo_refcnt */ 124 NULL, /* devo_getinfo */ 125 nulldev, /* devo_identify */ 126 nulldev, /* devo_probe */ 127 amd8111s_attach, /* devo_attach */ 128 amd8111s_detach, /* devo_detach */ 129 nodev, /* devo_reset */ 130 &amd8111s_cb_ops, /* devo_cb_ops */ 131 NULL, /* devo_bus_ops */ 132 nodev, /* devo_power */ 133 ddi_quiesce_not_supported, /* devo_quiesce */ 134 }; 135 136 struct modldrv amd8111s_modldrv = { 137 &mod_driverops, /* Type of module. This one is a driver */ 138 ident, /* short description */ 139 &amd8111s_dev_ops /* driver specific ops */ 140 }; 141 142 struct modlinkage amd8111s_modlinkage = { 143 MODREV_1, { (void *)&amd8111s_modldrv, NULL } 144 }; 145 146 /* 147 * Global Variables 148 */ 149 struct LayerPointers *amd8111sadapter; 150 151 static ddi_dma_attr_t pcn_buff_dma_attr_t = { 152 DMA_ATTR_V0, /* dma_attr_version */ 153 (uint64_t)0, /* dma_attr_addr_lo */ 154 (uint64_t)0xFFFFFFFF, /* dma_attr_addr_hi */ 155 (uint64_t)0xFFFFFFFF, /* dma_attr_count_max */ 156 (uint64_t)1, /* dma_attr_align */ 157 (uint_t)0x7F, /* dma_attr_burstsizes */ 158 (uint32_t)1, /* dma_attr_minxfer */ 159 (uint64_t)0xFFFFFFFF, /* dma_attr_maxxfer */ 160 (uint64_t)0xFFFFFFFF, /* dma_attr_seg */ 161 (int)1, /* dma_attr_sgllen */ 162 (uint32_t)1, /* granularity */ 163 (uint_t)0 /* dma_attr_flags */ 164 }; 165 166 static ddi_dma_attr_t pcn_desc_dma_attr_t = { 167 DMA_ATTR_V0, /* dma_attr_version */ 168 (uint64_t)0, /* dma_attr_addr_lo */ 169 (uint64_t)0xFFFFFFFF, /* dma_attr_addr_hi */ 170 (uint64_t)0x7FFFFFFF, /* dma_attr_count_max */ 171 (uint64_t)0x10, /* dma_attr_align */ 172 (uint_t)0xFFFFFFFFU, /* dma_attr_burstsizes */ 173 (uint32_t)1, /* dma_attr_minxfer */ 174 (uint64_t)0xFFFFFFFF, /* dma_attr_maxxfer */ 175 (uint64_t)0xFFFFFFFF, /* dma_attr_seg */ 176 (int)1, /* dma_attr_sgllen */ 177 (uint32_t)1, /* granularity */ 178 (uint_t)0 /* dma_attr_flags */ 179 }; 180 181 /* PIO access attributes for registers */ 182 static ddi_device_acc_attr_t pcn_acc_attr = { 183 DDI_DEVICE_ATTR_V0, 184 DDI_STRUCTURE_LE_ACC, 185 DDI_STRICTORDER_ACC 186 }; 187 188 189 static mac_callbacks_t amd8111s_m_callbacks = { 190 MC_IOCTL, 191 amd8111s_m_stat, 192 amd8111s_m_start, 193 amd8111s_m_stop, 194 amd8111s_m_promisc, 195 amd8111s_m_multicst, 196 amd8111s_m_unicst, 197 amd8111s_m_tx, 198 NULL, 199 amd8111s_m_ioctl 200 }; 201 202 203 /* 204 * Standard Driver Load Entry Point 205 * It will be called at load time of driver. 206 */ 207 int 208 _init() 209 { 210 int status; 211 mac_init_ops(&amd8111s_dev_ops, "amd8111s"); 212 213 status = mod_install(&amd8111s_modlinkage); 214 if (status != DDI_SUCCESS) { 215 mac_fini_ops(&amd8111s_dev_ops); 216 } 217 218 return (status); 219 } 220 221 /* 222 * Standard Driver Entry Point for Query. 223 * It will be called at any time to get Driver info. 224 */ 225 int 226 _info(struct modinfo *modinfop) 227 { 228 return (mod_info(&amd8111s_modlinkage, modinfop)); 229 } 230 231 /* 232 * Standard Driver Entry Point for Unload. 233 * It will be called at unload time of driver. 234 */ 235 int 236 _fini() 237 { 238 int status; 239 240 status = mod_remove(&amd8111s_modlinkage); 241 if (status == DDI_SUCCESS) { 242 mac_fini_ops(&amd8111s_dev_ops); 243 } 244 245 return (status); 246 } 247 248 /* 249 * Loopback Support 250 */ 251 static lb_property_t loopmodes[] = { 252 { normal, "normal", AMD8111S_LB_NONE }, 253 { external, "100Mbps", AMD8111S_LB_EXTERNAL_100 }, 254 { external, "10Mbps", AMD8111S_LB_EXTERNAL_10 }, 255 { internal, "MAC", AMD8111S_LB_INTERNAL_MAC } 256 }; 257 258 static void 259 amd8111s_set_loop_mode(struct LayerPointers *adapter, uint32_t mode) 260 { 261 262 /* 263 * If the mode isn't being changed, there's nothing to do ... 264 */ 265 if (mode == adapter->pOdl->loopback_mode) 266 return; 267 268 /* 269 * Validate the requested mode and prepare a suitable message 270 * to explain the link down/up cycle that the change will 271 * probably induce ... 272 */ 273 switch (mode) { 274 default: 275 return; 276 277 case AMD8111S_LB_NONE: 278 mdlStopChip(adapter); 279 if (adapter->pOdl->loopback_mode == AMD8111S_LB_INTERNAL_MAC) { 280 cmn_err(CE_NOTE, "LB_NONE restored from Interanl LB"); 281 WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD2, 282 INLOOP); 283 WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD3, 284 FORCE_FULL_DUPLEX | FORCE_LINK_STATUS); 285 } else { 286 cmn_err(CE_NOTE, "LB_NONE restored from Exteranl LB"); 287 WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD2, 288 EXLOOP); 289 } 290 291 amd8111s_reset(adapter); 292 adapter->pOdl->LinkStatus = LINK_STATE_DOWN; 293 adapter->pOdl->rx_fcs_stripped = B_FALSE; 294 mdlStartChip(adapter); 295 break; 296 297 case AMD8111S_LB_EXTERNAL_100: 298 cmn_err(CE_NOTE, "amd8111s_set_loop_mode LB_EXTERNAL_100"); 299 mdlStopChip(adapter); 300 amd8111s_reset(adapter); 301 SetIntrCoalesc(adapter, B_FALSE); 302 mdlPHYAutoNegotiation(adapter, PHY_FORCE_FD_100); 303 WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD2, 304 VAL0 | EXLOOP); 305 adapter->pOdl->LinkStatus = LINK_STATE_UP; 306 adapter->pMdl->Speed = 100; 307 adapter->pMdl->FullDuplex = B_TRUE; 308 /* Tell GLD the state of the physical link. */ 309 mac_link_update(adapter->pOdl->mh, LINK_STATE_UP); 310 311 adapter->pOdl->rx_fcs_stripped = B_TRUE; 312 313 mdlStartChip(adapter); 314 break; 315 316 case AMD8111S_LB_EXTERNAL_10: 317 cmn_err(CE_NOTE, "amd8111s_set_loop_mode LB_EXTERNAL_10"); 318 mdlStopChip(adapter); 319 amd8111s_reset(adapter); 320 SetIntrCoalesc(adapter, B_FALSE); 321 mdlPHYAutoNegotiation(adapter, PHY_FORCE_FD_10); 322 WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD2, 323 VAL0 | EXLOOP); 324 adapter->pOdl->LinkStatus = LINK_STATE_UP; 325 adapter->pMdl->Speed = 10; 326 adapter->pMdl->FullDuplex = B_TRUE; 327 /* Tell GLD the state of the physical link. */ 328 mac_link_update(adapter->pOdl->mh, LINK_STATE_UP); 329 330 adapter->pOdl->rx_fcs_stripped = B_TRUE; 331 332 mdlStartChip(adapter); 333 break; 334 335 case AMD8111S_LB_INTERNAL_MAC: 336 cmn_err(CE_NOTE, "amd8111s_set_loop_mode LB_INTERNAL_MAC"); 337 mdlStopChip(adapter); 338 amd8111s_reset(adapter); 339 SetIntrCoalesc(adapter, B_FALSE); 340 /* Disable Port Manager */ 341 WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD3, 342 EN_PMGR); 343 WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD2, 344 VAL0 | INLOOP); 345 346 WRITE_REG32(adapter, adapter->pMdl->Mem_Address + CMD3, 347 VAL1 | FORCE_FULL_DUPLEX | FORCE_LINK_STATUS); 348 349 adapter->pOdl->LinkStatus = LINK_STATE_UP; 350 adapter->pMdl->FullDuplex = B_TRUE; 351 /* Tell GLD the state of the physical link. */ 352 mac_link_update(adapter->pOdl->mh, LINK_STATE_UP); 353 354 adapter->pOdl->rx_fcs_stripped = B_TRUE; 355 356 mdlStartChip(adapter); 357 break; 358 } 359 360 /* 361 * All OK; tell the caller to reprogram 362 * the PHY and/or MAC for the new mode ... 363 */ 364 adapter->pOdl->loopback_mode = mode; 365 } 366 367 static enum ioc_reply 368 amd8111s_loopback_ioctl(struct LayerPointers *adapter, struct iocblk *iocp, 369 mblk_t *mp) 370 { 371 lb_info_sz_t *lbsp; 372 lb_property_t *lbpp; 373 uint32_t *lbmp; 374 int cmd; 375 376 /* 377 * Validate format of ioctl 378 */ 379 if (mp->b_cont == NULL) 380 return (IOC_INVAL); 381 382 cmd = iocp->ioc_cmd; 383 switch (cmd) { 384 default: 385 /* NOTREACHED */ 386 amd8111s_log(adapter, CE_NOTE, 387 "amd8111s_loop_ioctl: invalid cmd 0x%x", cmd); 388 return (IOC_INVAL); 389 390 case LB_GET_INFO_SIZE: 391 if (iocp->ioc_count != sizeof (lb_info_sz_t)) { 392 amd8111s_log(adapter, CE_NOTE, 393 "wrong LB_GET_INFO_SIZE size"); 394 return (IOC_INVAL); 395 } 396 lbsp = (void *)mp->b_cont->b_rptr; 397 *lbsp = sizeof (loopmodes); 398 break; 399 400 case LB_GET_INFO: 401 if (iocp->ioc_count != sizeof (loopmodes)) { 402 amd8111s_log(adapter, CE_NOTE, 403 "Wrong LB_GET_INFO size"); 404 return (IOC_INVAL); 405 } 406 lbpp = (void *)mp->b_cont->b_rptr; 407 bcopy(loopmodes, lbpp, sizeof (loopmodes)); 408 break; 409 410 case LB_GET_MODE: 411 if (iocp->ioc_count != sizeof (uint32_t)) { 412 amd8111s_log(adapter, CE_NOTE, 413 "Wrong LB_GET_MODE size"); 414 return (IOC_INVAL); 415 } 416 lbmp = (void *)mp->b_cont->b_rptr; 417 *lbmp = adapter->pOdl->loopback_mode; 418 break; 419 420 case LB_SET_MODE: 421 if (iocp->ioc_count != sizeof (uint32_t)) { 422 amd8111s_log(adapter, CE_NOTE, 423 "Wrong LB_SET_MODE size"); 424 return (IOC_INVAL); 425 } 426 lbmp = (void *)mp->b_cont->b_rptr; 427 amd8111s_set_loop_mode(adapter, *lbmp); 428 break; 429 } 430 return (IOC_REPLY); 431 } 432 433 static void 434 amd8111s_m_ioctl(void *arg, queue_t *q, mblk_t *mp) 435 { 436 struct iocblk *iocp; 437 struct LayerPointers *adapter; 438 enum ioc_reply status; 439 440 iocp = (void *)mp->b_rptr; 441 iocp->ioc_error = 0; 442 adapter = arg; 443 444 ASSERT(adapter); 445 if (adapter == NULL) { 446 miocnak(q, mp, 0, EINVAL); 447 return; 448 } 449 450 switch (iocp->ioc_cmd) { 451 452 case LB_GET_INFO_SIZE: 453 case LB_GET_INFO: 454 case LB_GET_MODE: 455 case LB_SET_MODE: 456 status = amd8111s_loopback_ioctl(adapter, iocp, mp); 457 break; 458 459 default: 460 status = IOC_INVAL; 461 break; 462 } 463 464 /* 465 * Decide how to reply 466 */ 467 switch (status) { 468 default: 469 case IOC_INVAL: 470 /* 471 * Error, reply with a NAK and EINVAL or the specified error 472 */ 473 miocnak(q, mp, 0, iocp->ioc_error == 0 ? 474 EINVAL : iocp->ioc_error); 475 break; 476 477 case IOC_DONE: 478 /* 479 * OK, reply already sent 480 */ 481 break; 482 483 case IOC_ACK: 484 /* 485 * OK, reply with an ACK 486 */ 487 miocack(q, mp, 0, 0); 488 break; 489 490 case IOC_REPLY: 491 /* 492 * OK, send prepared reply as ACK or NAK 493 */ 494 mp->b_datap->db_type = iocp->ioc_error == 0 ? 495 M_IOCACK : M_IOCNAK; 496 qreply(q, mp); 497 break; 498 } 499 } 500 501 /* 502 * Copy one packet from dma memory to mblk. Inc dma descriptor pointer. 503 */ 504 static boolean_t 505 amd8111s_recv_copy(struct LayerPointers *pLayerPointers, mblk_t **last_mp) 506 { 507 int length = 0; 508 mblk_t *mp; 509 struct rx_desc *descriptor; 510 struct odl *pOdl = pLayerPointers->pOdl; 511 struct amd8111s_statistics *statistics = &pOdl->statistics; 512 struct nonphysical *pNonphysical = pLayerPointers->pMil 513 ->pNonphysical; 514 515 mutex_enter(&pOdl->mdlRcvLock); 516 descriptor = pNonphysical->RxBufDescQRead->descriptor; 517 (void) ddi_dma_sync(pOdl->rx_desc_dma_handle, 518 pNonphysical->RxBufDescQRead->descriptor - 519 pNonphysical->RxBufDescQStart->descriptor, 520 sizeof (struct rx_desc), DDI_DMA_SYNC_FORCPU); 521 if ((descriptor->Rx_OWN) == 0) { 522 /* 523 * If the frame is received with errors, then set MCNT 524 * of that pkt in ReceiveArray to 0. This packet would 525 * be discarded later and not indicated to OS. 526 */ 527 if (descriptor->Rx_ERR) { 528 statistics->rx_desc_err ++; 529 descriptor->Rx_ERR = 0; 530 if (descriptor->Rx_FRAM == 1) { 531 statistics->rx_desc_err_FRAM ++; 532 descriptor->Rx_FRAM = 0; 533 } 534 if (descriptor->Rx_OFLO == 1) { 535 statistics->rx_desc_err_OFLO ++; 536 descriptor->Rx_OFLO = 0; 537 pOdl->rx_overflow_counter ++; 538 if ((pOdl->rx_overflow_counter > 5) && 539 (pOdl->pause_interval == 0)) { 540 statistics->rx_double_overflow ++; 541 mdlSendPause(pLayerPointers); 542 pOdl->rx_overflow_counter = 0; 543 pOdl->pause_interval = 25; 544 } 545 } 546 if (descriptor->Rx_CRC == 1) { 547 statistics->rx_desc_err_CRC ++; 548 descriptor->Rx_CRC = 0; 549 } 550 if (descriptor->Rx_BUFF == 1) { 551 statistics->rx_desc_err_BUFF ++; 552 descriptor->Rx_BUFF = 0; 553 } 554 goto Next_Descriptor; 555 } 556 557 /* Length of incoming packet */ 558 if (pOdl->rx_fcs_stripped) { 559 length = descriptor->Rx_MCNT -4; 560 } else { 561 length = descriptor->Rx_MCNT; 562 } 563 if (length < 62) { 564 statistics->rx_error_zerosize ++; 565 } 566 567 if ((mp = allocb(length, BPRI_MED)) == NULL) { 568 statistics->rx_allocfail ++; 569 goto failed; 570 } 571 /* Copy from virtual address of incoming packet */ 572 bcopy((long *)*(pNonphysical->RxBufDescQRead->USpaceMap), 573 mp->b_rptr, length); 574 mp->b_wptr = mp->b_rptr + length; 575 statistics->rx_ok_packets ++; 576 if (*last_mp == NULL) { 577 *last_mp = mp; 578 } else { 579 (*last_mp)->b_next = mp; 580 *last_mp = mp; 581 } 582 583 Next_Descriptor: 584 descriptor->Rx_MCNT = 0; 585 descriptor->Rx_SOP = 0; 586 descriptor->Rx_EOP = 0; 587 descriptor->Rx_PAM = 0; 588 descriptor->Rx_BAM = 0; 589 descriptor->TT = 0; 590 descriptor->Rx_OWN = 1; 591 pNonphysical->RxBufDescQRead->descriptor++; 592 pNonphysical->RxBufDescQRead->USpaceMap++; 593 if (pNonphysical->RxBufDescQRead->descriptor > 594 pNonphysical->RxBufDescQEnd->descriptor) { 595 pNonphysical->RxBufDescQRead->descriptor = 596 pNonphysical->RxBufDescQStart->descriptor; 597 pNonphysical->RxBufDescQRead->USpaceMap = 598 pNonphysical->RxBufDescQStart->USpaceMap; 599 } 600 mutex_exit(&pOdl->mdlRcvLock); 601 602 return (B_TRUE); 603 } 604 605 failed: 606 mutex_exit(&pOdl->mdlRcvLock); 607 return (B_FALSE); 608 } 609 610 /* 611 * Get the received packets from NIC card and send them to GLD. 612 */ 613 static void 614 amd8111s_receive(struct LayerPointers *pLayerPointers) 615 { 616 int numOfPkts = 0; 617 struct odl *pOdl; 618 mblk_t *ret_mp = NULL, *last_mp = NULL; 619 620 pOdl = pLayerPointers->pOdl; 621 622 rw_enter(&pOdl->chip_lock, RW_READER); 623 if (!pLayerPointers->run) { 624 rw_exit(&pOdl->chip_lock); 625 return; 626 } 627 628 if (pOdl->pause_interval > 0) 629 pOdl->pause_interval --; 630 631 while (numOfPkts < RX_RING_SIZE) { 632 633 if (!amd8111s_recv_copy(pLayerPointers, &last_mp)) { 634 break; 635 } 636 if (ret_mp == NULL) 637 ret_mp = last_mp; 638 numOfPkts++; 639 } 640 641 if (ret_mp) { 642 mac_rx(pOdl->mh, NULL, ret_mp); 643 } 644 645 (void) ddi_dma_sync(pOdl->rx_desc_dma_handle, 0, 0, 646 DDI_DMA_SYNC_FORDEV); 647 648 mdlReceive(pLayerPointers); 649 650 rw_exit(&pOdl->chip_lock); 651 652 } 653 654 /* 655 * Print message in release-version driver. 656 */ 657 static void 658 amd8111s_log(struct LayerPointers *adapter, int level, char *fmt, ...) 659 { 660 auto char name[32]; 661 auto char buf[256]; 662 va_list ap; 663 664 if (adapter != NULL) { 665 (void) sprintf(name, "amd8111s%d", 666 ddi_get_instance(adapter->pOdl->devinfo)); 667 } else { 668 (void) sprintf(name, "amd8111s"); 669 } 670 va_start(ap, fmt); 671 (void) vsprintf(buf, fmt, ap); 672 va_end(ap); 673 cmn_err(level, "%s: %s", name, buf); 674 } 675 676 /* 677 * To allocate & initilize all resources. 678 * Called by amd8111s_attach(). 679 */ 680 static int 681 amd8111s_odlInit(struct LayerPointers *pLayerPointers) 682 { 683 unsigned long mem_req_array[MEM_REQ_MAX]; 684 unsigned long mem_set_array[MEM_REQ_MAX]; 685 unsigned long *pmem_req_array; 686 unsigned long *pmem_set_array; 687 int i, size; 688 689 for (i = 0; i < MEM_REQ_MAX; i++) { 690 mem_req_array[i] = 0; 691 mem_set_array[i] = 0; 692 } 693 694 milRequestResources(mem_req_array); 695 696 pmem_req_array = mem_req_array; 697 pmem_set_array = mem_set_array; 698 while (*pmem_req_array) { 699 switch (*pmem_req_array) { 700 case VIRTUAL: 701 *pmem_set_array = VIRTUAL; 702 pmem_req_array++; 703 pmem_set_array++; 704 *(pmem_set_array) = *(pmem_req_array); 705 pmem_set_array++; 706 *(pmem_set_array) = (unsigned long) kmem_zalloc( 707 *(pmem_req_array), KM_NOSLEEP); 708 if (*pmem_set_array == NULL) 709 goto odl_init_failure; 710 break; 711 } 712 pmem_req_array++; 713 pmem_set_array++; 714 } 715 716 /* 717 * Initilize memory on lower layers 718 */ 719 milSetResources(pLayerPointers, mem_set_array); 720 721 /* Allocate Rx/Tx descriptors */ 722 if (amd8111s_allocate_descriptors(pLayerPointers) != B_TRUE) { 723 *pmem_set_array = NULL; 724 goto odl_init_failure; 725 } 726 727 /* 728 * Allocate Rx buffer for each Rx descriptor. Then call mil layer 729 * routine to fill physical address of Rx buffer into Rx descriptor. 730 */ 731 if (amd8111s_allocate_buffers(pLayerPointers) == B_FALSE) { 732 amd8111s_free_descriptors(pLayerPointers); 733 *pmem_set_array = NULL; 734 goto odl_init_failure; 735 } 736 milInitGlbds(pLayerPointers); 737 738 return (0); 739 740 odl_init_failure: 741 /* 742 * Free All memory allocated so far 743 */ 744 pmem_req_array = mem_set_array; 745 while ((*pmem_req_array) && (pmem_req_array != pmem_set_array)) { 746 switch (*pmem_req_array) { 747 case VIRTUAL: 748 pmem_req_array++; /* Size */ 749 size = *(pmem_req_array); 750 pmem_req_array++; /* Virtual Address */ 751 if (pmem_req_array == NULL) 752 return (1); 753 kmem_free((int *)*pmem_req_array, size); 754 break; 755 } 756 pmem_req_array++; 757 } 758 return (1); 759 } 760 761 /* 762 * Allocate and initialize Tx/Rx descriptors 763 */ 764 static boolean_t 765 amd8111s_allocate_descriptors(struct LayerPointers *pLayerPointers) 766 { 767 struct odl *pOdl = pLayerPointers->pOdl; 768 struct mil *pMil = pLayerPointers->pMil; 769 dev_info_t *devinfo = pOdl->devinfo; 770 uint_t length, count, i; 771 size_t real_length; 772 773 /* 774 * Allocate Rx descriptors 775 */ 776 if (ddi_dma_alloc_handle(devinfo, &pcn_desc_dma_attr_t, DDI_DMA_SLEEP, 777 NULL, &pOdl->rx_desc_dma_handle) != DDI_SUCCESS) { 778 amd8111s_log(pLayerPointers, CE_WARN, 779 "ddi_dma_alloc_handle for Rx desc failed"); 780 pOdl->rx_desc_dma_handle = NULL; 781 return (B_FALSE); 782 } 783 784 length = sizeof (struct rx_desc) * RX_RING_SIZE + ALIGNMENT; 785 if (ddi_dma_mem_alloc(pOdl->rx_desc_dma_handle, length, 786 &pcn_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 787 NULL, (caddr_t *)&pMil->Rx_desc_original, &real_length, 788 &pOdl->rx_desc_acc_handle) != DDI_SUCCESS) { 789 790 amd8111s_log(pLayerPointers, CE_WARN, 791 "ddi_dma_mem_handle for Rx desc failed"); 792 ddi_dma_free_handle(&pOdl->rx_desc_dma_handle); 793 pOdl->rx_desc_dma_handle = NULL; 794 return (B_FALSE); 795 } 796 797 if (ddi_dma_addr_bind_handle(pOdl->rx_desc_dma_handle, 798 NULL, (caddr_t)pMil->Rx_desc_original, real_length, 799 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 800 NULL, &pOdl->rx_desc_dma_cookie, 801 &count) != DDI_SUCCESS) { 802 803 amd8111s_log(pLayerPointers, CE_WARN, 804 "ddi_dma_addr_bind_handle for Rx desc failed"); 805 ddi_dma_mem_free(&pOdl->rx_desc_acc_handle); 806 ddi_dma_free_handle(&pOdl->rx_desc_dma_handle); 807 pOdl->rx_desc_dma_handle = NULL; 808 return (B_FALSE); 809 } 810 ASSERT(count == 1); 811 812 /* Initialize Rx descriptors related variables */ 813 pMil->Rx_desc = (struct rx_desc *) 814 ((pMil->Rx_desc_original + ALIGNMENT) & ~ALIGNMENT); 815 pMil->Rx_desc_pa = (unsigned int) 816 ((pOdl->rx_desc_dma_cookie.dmac_laddress + ALIGNMENT) & ~ALIGNMENT); 817 818 pLayerPointers->pMdl->init_blk->RDRA = pMil->Rx_desc_pa; 819 820 821 /* 822 * Allocate Tx descriptors 823 */ 824 if (ddi_dma_alloc_handle(devinfo, &pcn_desc_dma_attr_t, DDI_DMA_SLEEP, 825 NULL, &pOdl->tx_desc_dma_handle) != DDI_SUCCESS) { 826 amd8111s_log(pLayerPointers, CE_WARN, 827 "ddi_dma_alloc_handle for Tx desc failed"); 828 goto allocate_desc_fail; 829 } 830 831 length = sizeof (struct tx_desc) * TX_RING_SIZE + ALIGNMENT; 832 if (ddi_dma_mem_alloc(pOdl->tx_desc_dma_handle, length, 833 &pcn_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 834 NULL, (caddr_t *)&pMil->Tx_desc_original, &real_length, 835 &pOdl->tx_desc_acc_handle) != DDI_SUCCESS) { 836 837 amd8111s_log(pLayerPointers, CE_WARN, 838 "ddi_dma_mem_handle for Tx desc failed"); 839 ddi_dma_free_handle(&pOdl->tx_desc_dma_handle); 840 goto allocate_desc_fail; 841 } 842 843 if (ddi_dma_addr_bind_handle(pOdl->tx_desc_dma_handle, 844 NULL, (caddr_t)pMil->Tx_desc_original, real_length, 845 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 846 NULL, &pOdl->tx_desc_dma_cookie, 847 &count) != DDI_SUCCESS) { 848 849 amd8111s_log(pLayerPointers, CE_WARN, 850 "ddi_dma_addr_bind_handle for Tx desc failed"); 851 ddi_dma_mem_free(&pOdl->tx_desc_acc_handle); 852 ddi_dma_free_handle(&pOdl->tx_desc_dma_handle); 853 goto allocate_desc_fail; 854 } 855 ASSERT(count == 1); 856 /* Set the DMA area to all zeros */ 857 bzero((caddr_t)pMil->Tx_desc_original, length); 858 859 /* Initialize Tx descriptors related variables */ 860 pMil->Tx_desc = (struct tx_desc *) 861 ((pMil->Tx_desc_original + ALIGNMENT) & ~ALIGNMENT); 862 pMil->pNonphysical->TxDescQRead = pMil->Tx_desc; 863 pMil->pNonphysical->TxDescQWrite = pMil->Tx_desc; 864 pMil->pNonphysical->TxDescQStart = pMil->Tx_desc; 865 pMil->pNonphysical->TxDescQEnd = &(pMil->Tx_desc[TX_RING_SIZE -1]); 866 867 /* Physical Addr of Tx_desc_original & Tx_desc */ 868 pLayerPointers->pMil->Tx_desc_pa = 869 ((pOdl->tx_desc_dma_cookie.dmac_laddress + ALIGNMENT) & 870 ~ALIGNMENT); 871 872 /* Setting the reserved bits in the tx descriptors */ 873 for (i = 0; i < TX_RING_SIZE; i++) { 874 pMil->pNonphysical->TxDescQWrite->Tx_RES0 = 0x0f; 875 pMil->pNonphysical->TxDescQWrite->Tx_OWN = 0; 876 pMil->pNonphysical->TxDescQWrite++; 877 } 878 pMil->pNonphysical->TxDescQWrite = pMil->pNonphysical->TxDescQStart; 879 880 pLayerPointers->pMdl->init_blk->TDRA = pMil->Tx_desc_pa; 881 882 return (B_TRUE); 883 884 allocate_desc_fail: 885 pOdl->tx_desc_dma_handle = NULL; 886 (void) ddi_dma_unbind_handle(pOdl->rx_desc_dma_handle); 887 ddi_dma_mem_free(&pOdl->rx_desc_acc_handle); 888 ddi_dma_free_handle(&pOdl->rx_desc_dma_handle); 889 pOdl->rx_desc_dma_handle = NULL; 890 return (B_FALSE); 891 } 892 893 /* 894 * Free Tx/Rx descriptors 895 */ 896 static void 897 amd8111s_free_descriptors(struct LayerPointers *pLayerPointers) 898 { 899 struct odl *pOdl = pLayerPointers->pOdl; 900 901 /* Free Rx descriptors */ 902 if (pOdl->rx_desc_dma_handle) { 903 (void) ddi_dma_unbind_handle(pOdl->rx_desc_dma_handle); 904 ddi_dma_mem_free(&pOdl->rx_desc_acc_handle); 905 ddi_dma_free_handle(&pOdl->rx_desc_dma_handle); 906 pOdl->rx_desc_dma_handle = NULL; 907 } 908 909 /* Free Rx descriptors */ 910 if (pOdl->tx_desc_dma_handle) { 911 (void) ddi_dma_unbind_handle(pOdl->tx_desc_dma_handle); 912 ddi_dma_mem_free(&pOdl->tx_desc_acc_handle); 913 ddi_dma_free_handle(&pOdl->tx_desc_dma_handle); 914 pOdl->tx_desc_dma_handle = NULL; 915 } 916 } 917 918 /* 919 * Allocate Tx/Rx Ring buffer 920 */ 921 static boolean_t 922 amd8111s_alloc_dma_ringbuf(struct LayerPointers *pLayerPointers, 923 struct amd8111s_dma_ringbuf *pRing, 924 uint32_t ring_size, uint32_t msg_size) 925 { 926 uint32_t idx, msg_idx = 0, msg_acc; 927 dev_info_t *devinfo = pLayerPointers->pOdl->devinfo; 928 size_t real_length; 929 uint_t count = 0; 930 931 ASSERT(pcn_buff_dma_attr_t.dma_attr_align == 1); 932 pRing->dma_buf_sz = msg_size; 933 pRing->ring_size = ring_size; 934 pRing->trunk_num = AMD8111S_SPLIT; 935 pRing->buf_sz = msg_size * ring_size; 936 if (ring_size < pRing->trunk_num) 937 pRing->trunk_num = ring_size; 938 ASSERT((pRing->buf_sz % pRing->trunk_num) == 0); 939 940 pRing->trunk_sz = pRing->buf_sz / pRing->trunk_num; 941 ASSERT((pRing->trunk_sz % pRing->dma_buf_sz) == 0); 942 943 pRing->msg_buf = kmem_zalloc(sizeof (struct amd8111s_msgbuf) * 944 ring_size, KM_NOSLEEP); 945 pRing->dma_hdl = kmem_zalloc(sizeof (ddi_dma_handle_t) * 946 pRing->trunk_num, KM_NOSLEEP); 947 pRing->acc_hdl = kmem_zalloc(sizeof (ddi_acc_handle_t) * 948 pRing->trunk_num, KM_NOSLEEP); 949 pRing->dma_cookie = kmem_zalloc(sizeof (ddi_dma_cookie_t) * 950 pRing->trunk_num, KM_NOSLEEP); 951 pRing->trunk_addr = kmem_zalloc(sizeof (caddr_t) * 952 pRing->trunk_num, KM_NOSLEEP); 953 if (pRing->msg_buf == NULL || pRing->dma_hdl == NULL || 954 pRing->acc_hdl == NULL || pRing->trunk_addr == NULL || 955 pRing->dma_cookie == NULL) { 956 amd8111s_log(pLayerPointers, CE_NOTE, 957 "kmem_zalloc failed"); 958 goto failed; 959 } 960 961 for (idx = 0; idx < pRing->trunk_num; ++idx) { 962 if (ddi_dma_alloc_handle(devinfo, &pcn_buff_dma_attr_t, 963 DDI_DMA_SLEEP, NULL, &(pRing->dma_hdl[idx])) 964 != DDI_SUCCESS) { 965 966 amd8111s_log(pLayerPointers, CE_WARN, 967 "ddi_dma_alloc_handle failed"); 968 goto failed; 969 } else if (ddi_dma_mem_alloc(pRing->dma_hdl[idx], 970 pRing->trunk_sz, &pcn_acc_attr, DDI_DMA_STREAMING, 971 DDI_DMA_SLEEP, NULL, 972 (caddr_t *)&(pRing->trunk_addr[idx]), 973 (size_t *)(&real_length), &pRing->acc_hdl[idx]) 974 != DDI_SUCCESS) { 975 976 amd8111s_log(pLayerPointers, CE_WARN, 977 "ddi_dma_mem_alloc failed"); 978 goto failed; 979 } else if (real_length != pRing->trunk_sz) { 980 amd8111s_log(pLayerPointers, CE_WARN, 981 "ddi_dma_mem_alloc failed"); 982 goto failed; 983 } else if (ddi_dma_addr_bind_handle(pRing->dma_hdl[idx], 984 NULL, (caddr_t)pRing->trunk_addr[idx], real_length, 985 DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, 986 &pRing->dma_cookie[idx], &count) != DDI_DMA_MAPPED) { 987 988 amd8111s_log(pLayerPointers, CE_WARN, 989 "ddi_dma_addr_bind_handle failed"); 990 goto failed; 991 } else { 992 for (msg_acc = 0; 993 msg_acc < pRing->trunk_sz / pRing->dma_buf_sz; 994 ++ msg_acc) { 995 pRing->msg_buf[msg_idx].offset = 996 msg_acc * pRing->dma_buf_sz; 997 pRing->msg_buf[msg_idx].vir_addr = 998 pRing->trunk_addr[idx] + 999 pRing->msg_buf[msg_idx].offset; 1000 pRing->msg_buf[msg_idx].phy_addr = 1001 pRing->dma_cookie[idx].dmac_laddress + 1002 pRing->msg_buf[msg_idx].offset; 1003 pRing->msg_buf[msg_idx].p_hdl = 1004 pRing->dma_hdl[idx]; 1005 msg_idx ++; 1006 } 1007 } 1008 } 1009 1010 pRing->free = pRing->msg_buf; 1011 pRing->next = pRing->msg_buf; 1012 pRing->curr = pRing->msg_buf; 1013 1014 return (B_TRUE); 1015 failed: 1016 amd8111s_free_dma_ringbuf(pRing); 1017 return (B_FALSE); 1018 } 1019 1020 /* 1021 * Free Tx/Rx ring buffer 1022 */ 1023 static void 1024 amd8111s_free_dma_ringbuf(struct amd8111s_dma_ringbuf *pRing) 1025 { 1026 int idx; 1027 1028 if (pRing->dma_cookie != NULL) { 1029 for (idx = 0; idx < pRing->trunk_num; idx ++) { 1030 if (pRing->dma_cookie[idx].dmac_laddress == 0) { 1031 break; 1032 } 1033 (void) ddi_dma_unbind_handle(pRing->dma_hdl[idx]); 1034 } 1035 kmem_free(pRing->dma_cookie, 1036 sizeof (ddi_dma_cookie_t) * pRing->trunk_num); 1037 } 1038 1039 if (pRing->acc_hdl != NULL) { 1040 for (idx = 0; idx < pRing->trunk_num; idx ++) { 1041 if (pRing->acc_hdl[idx] == NULL) 1042 break; 1043 ddi_dma_mem_free(&pRing->acc_hdl[idx]); 1044 } 1045 kmem_free(pRing->acc_hdl, 1046 sizeof (ddi_acc_handle_t) * pRing->trunk_num); 1047 } 1048 1049 if (pRing->dma_hdl != NULL) { 1050 for (idx = 0; idx < pRing->trunk_num; idx ++) { 1051 if (pRing->dma_hdl[idx] == 0) { 1052 break; 1053 } 1054 ddi_dma_free_handle(&pRing->dma_hdl[idx]); 1055 } 1056 kmem_free(pRing->dma_hdl, 1057 sizeof (ddi_dma_handle_t) * pRing->trunk_num); 1058 } 1059 1060 if (pRing->msg_buf != NULL) { 1061 kmem_free(pRing->msg_buf, 1062 sizeof (struct amd8111s_msgbuf) * pRing->ring_size); 1063 } 1064 1065 if (pRing->trunk_addr != NULL) { 1066 kmem_free(pRing->trunk_addr, 1067 sizeof (caddr_t) * pRing->trunk_num); 1068 } 1069 1070 bzero(pRing, sizeof (*pRing)); 1071 } 1072 1073 1074 /* 1075 * Allocate all Tx buffer. 1076 * Allocate a Rx buffer for each Rx descriptor. Then 1077 * call mil routine to fill physical address of Rx 1078 * buffer into Rx descriptors 1079 */ 1080 static boolean_t 1081 amd8111s_allocate_buffers(struct LayerPointers *pLayerPointers) 1082 { 1083 struct odl *pOdl = pLayerPointers->pOdl; 1084 1085 /* 1086 * Allocate rx Buffers 1087 */ 1088 if (amd8111s_alloc_dma_ringbuf(pLayerPointers, &pOdl->rx_buf, 1089 RX_RING_SIZE, RX_BUF_SIZE) == B_FALSE) { 1090 amd8111s_log(pLayerPointers, CE_WARN, 1091 "amd8111s_alloc_dma_ringbuf for tx failed"); 1092 goto allocate_buf_fail; 1093 } 1094 1095 /* 1096 * Allocate Tx buffers 1097 */ 1098 if (amd8111s_alloc_dma_ringbuf(pLayerPointers, &pOdl->tx_buf, 1099 TX_COALESC_SIZE, TX_BUF_SIZE) == B_FALSE) { 1100 amd8111s_log(pLayerPointers, CE_WARN, 1101 "amd8111s_alloc_dma_ringbuf for tx failed"); 1102 goto allocate_buf_fail; 1103 } 1104 1105 /* 1106 * Initilize the mil Queues 1107 */ 1108 milInitGlbds(pLayerPointers); 1109 1110 milInitRxQ(pLayerPointers); 1111 1112 return (B_TRUE); 1113 1114 allocate_buf_fail: 1115 1116 amd8111s_log(pLayerPointers, CE_WARN, 1117 "amd8111s_allocate_buffers failed"); 1118 return (B_FALSE); 1119 } 1120 1121 /* 1122 * Free all Rx/Tx buffer 1123 */ 1124 1125 static void 1126 amd8111s_free_buffers(struct LayerPointers *pLayerPointers) 1127 { 1128 /* Free Tx buffers */ 1129 amd8111s_free_dma_ringbuf(&pLayerPointers->pOdl->tx_buf); 1130 1131 /* Free Rx Buffers */ 1132 amd8111s_free_dma_ringbuf(&pLayerPointers->pOdl->rx_buf); 1133 } 1134 1135 /* 1136 * Try to recycle all the descriptors and Tx buffers 1137 * which are already freed by hardware. 1138 */ 1139 static int 1140 amd8111s_recycle_tx(struct LayerPointers *pLayerPointers) 1141 { 1142 struct nonphysical *pNonphysical; 1143 uint32_t count = 0; 1144 1145 pNonphysical = pLayerPointers->pMil->pNonphysical; 1146 while (pNonphysical->TxDescQRead->Tx_OWN == 0 && 1147 pNonphysical->TxDescQRead != pNonphysical->TxDescQWrite) { 1148 pLayerPointers->pOdl->tx_buf.free = 1149 NEXT(pLayerPointers->pOdl->tx_buf, free); 1150 pNonphysical->TxDescQRead++; 1151 if (pNonphysical->TxDescQRead > pNonphysical->TxDescQEnd) { 1152 pNonphysical->TxDescQRead = pNonphysical->TxDescQStart; 1153 } 1154 count ++; 1155 } 1156 1157 if (pLayerPointers->pMil->tx_reschedule) 1158 ddi_trigger_softintr(pLayerPointers->pOdl->drain_id); 1159 1160 return (count); 1161 } 1162 1163 /* 1164 * Get packets in the Tx buffer, then copy them to the send buffer. 1165 * Trigger hardware to send out packets. 1166 */ 1167 static void 1168 amd8111s_send_serial(struct LayerPointers *pLayerPointers) 1169 { 1170 struct nonphysical *pNonphysical; 1171 uint32_t count; 1172 1173 pNonphysical = pLayerPointers->pMil->pNonphysical; 1174 1175 mutex_enter(&pLayerPointers->pOdl->mdlSendLock); 1176 1177 for (count = 0; count < AMD8111S_SEND_MAX; count ++) { 1178 if (pLayerPointers->pOdl->tx_buf.curr == 1179 pLayerPointers->pOdl->tx_buf.next) { 1180 break; 1181 } 1182 /* to verify if it needs to recycle the tx Buf */ 1183 if (((pNonphysical->TxDescQWrite + 1 > 1184 pNonphysical->TxDescQEnd) ? pNonphysical->TxDescQStart : 1185 (pNonphysical->TxDescQWrite + 1)) == 1186 pNonphysical->TxDescQRead) 1187 if (amd8111s_recycle_tx(pLayerPointers) == 0) { 1188 pLayerPointers->pOdl 1189 ->statistics.tx_no_descriptor ++; 1190 break; 1191 } 1192 1193 /* Fill packet length */ 1194 pNonphysical->TxDescQWrite->Tx_BCNT = (uint16_t)pLayerPointers 1195 ->pOdl->tx_buf.curr->msg_size; 1196 1197 /* Fill physical buffer address */ 1198 pNonphysical->TxDescQWrite->Tx_Base_Addr = (unsigned int) 1199 pLayerPointers->pOdl->tx_buf.curr->phy_addr; 1200 1201 pNonphysical->TxDescQWrite->Tx_SOP = 1; 1202 pNonphysical->TxDescQWrite->Tx_EOP = 1; 1203 pNonphysical->TxDescQWrite->Tx_ADD_FCS = 1; 1204 pNonphysical->TxDescQWrite->Tx_LTINT = 1; 1205 pNonphysical->TxDescQWrite->Tx_USPACE = 0; 1206 pNonphysical->TxDescQWrite->Tx_OWN = 1; 1207 1208 pNonphysical->TxDescQWrite++; 1209 if (pNonphysical->TxDescQWrite > pNonphysical->TxDescQEnd) { 1210 pNonphysical->TxDescQWrite = pNonphysical->TxDescQStart; 1211 } 1212 1213 pLayerPointers->pOdl->tx_buf.curr = 1214 NEXT(pLayerPointers->pOdl->tx_buf, curr); 1215 1216 } 1217 1218 pLayerPointers->pOdl->statistics.tx_ok_packets += count; 1219 1220 mutex_exit(&pLayerPointers->pOdl->mdlSendLock); 1221 1222 /* Call mdlTransmit to send the pkt out on the network */ 1223 mdlTransmit(pLayerPointers); 1224 1225 } 1226 1227 /* 1228 * Softintr entrance. try to send out packets in the Tx buffer. 1229 * If reschedule is True, call mac_tx_update to re-enable the 1230 * transmit 1231 */ 1232 static uint_t 1233 amd8111s_send_drain(caddr_t arg) 1234 { 1235 struct LayerPointers *pLayerPointers = (void *)arg; 1236 1237 amd8111s_send_serial(pLayerPointers); 1238 1239 if (pLayerPointers->pMil->tx_reschedule && 1240 NEXT(pLayerPointers->pOdl->tx_buf, next) != 1241 pLayerPointers->pOdl->tx_buf.free) { 1242 mac_tx_update(pLayerPointers->pOdl->mh); 1243 pLayerPointers->pMil->tx_reschedule = B_FALSE; 1244 } 1245 1246 return (DDI_INTR_CLAIMED); 1247 } 1248 1249 /* 1250 * Get a Tx buffer 1251 */ 1252 static struct amd8111s_msgbuf * 1253 amd8111s_getTxbuf(struct LayerPointers *pLayerPointers) 1254 { 1255 struct amd8111s_msgbuf *tmp, *next; 1256 1257 mutex_enter(&pLayerPointers->pOdl->mdlSendLock); 1258 next = NEXT(pLayerPointers->pOdl->tx_buf, next); 1259 if (next == pLayerPointers->pOdl->tx_buf.free) { 1260 tmp = NULL; 1261 } else { 1262 tmp = pLayerPointers->pOdl->tx_buf.next; 1263 pLayerPointers->pOdl->tx_buf.next = next; 1264 } 1265 mutex_exit(&pLayerPointers->pOdl->mdlSendLock); 1266 1267 return (tmp); 1268 } 1269 1270 static boolean_t 1271 amd8111s_send(struct LayerPointers *pLayerPointers, mblk_t *mp) 1272 { 1273 struct odl *pOdl; 1274 size_t frag_len; 1275 mblk_t *tmp; 1276 struct amd8111s_msgbuf *txBuf; 1277 uint8_t *pMsg; 1278 1279 pOdl = pLayerPointers->pOdl; 1280 1281 /* alloc send buffer */ 1282 txBuf = amd8111s_getTxbuf(pLayerPointers); 1283 if (txBuf == NULL) { 1284 pOdl->statistics.tx_no_buffer ++; 1285 pLayerPointers->pMil->tx_reschedule = B_TRUE; 1286 amd8111s_send_serial(pLayerPointers); 1287 return (B_FALSE); 1288 } 1289 1290 /* copy packet to send buffer */ 1291 txBuf->msg_size = 0; 1292 pMsg = (uint8_t *)txBuf->vir_addr; 1293 for (tmp = mp; tmp; tmp = tmp->b_cont) { 1294 frag_len = MBLKL(tmp); 1295 bcopy(tmp->b_rptr, pMsg, frag_len); 1296 txBuf->msg_size += frag_len; 1297 pMsg += frag_len; 1298 } 1299 freemsg(mp); 1300 1301 amd8111s_send_serial(pLayerPointers); 1302 1303 return (B_TRUE); 1304 } 1305 1306 /* 1307 * (GLD Entry Point) Send the message block to lower layer 1308 */ 1309 static mblk_t * 1310 amd8111s_m_tx(void *arg, mblk_t *mp) 1311 { 1312 struct LayerPointers *pLayerPointers = arg; 1313 mblk_t *next; 1314 1315 rw_enter(&pLayerPointers->pOdl->chip_lock, RW_READER); 1316 if (!pLayerPointers->run) { 1317 pLayerPointers->pOdl->statistics.tx_afterunplumb ++; 1318 freemsgchain(mp); 1319 mp = NULL; 1320 } 1321 1322 while (mp != NULL) { 1323 next = mp->b_next; 1324 mp->b_next = NULL; 1325 if (!amd8111s_send(pLayerPointers, mp)) { 1326 /* Send fail */ 1327 mp->b_next = next; 1328 break; 1329 } 1330 mp = next; 1331 } 1332 1333 rw_exit(&pLayerPointers->pOdl->chip_lock); 1334 return (mp); 1335 } 1336 1337 /* 1338 * (GLD Entry Point) Interrupt Service Routine 1339 */ 1340 static uint_t 1341 amd8111s_intr(caddr_t arg) 1342 { 1343 unsigned int intrCauses; 1344 struct LayerPointers *pLayerPointers = (void *)arg; 1345 1346 /* Read the interrupt status from mdl */ 1347 intrCauses = mdlReadInterrupt(pLayerPointers); 1348 1349 if (intrCauses == 0) { 1350 pLayerPointers->pOdl->statistics.intr_OTHER ++; 1351 return (DDI_INTR_UNCLAIMED); 1352 } 1353 1354 if (intrCauses & LCINT) { 1355 if (mdlReadLink(pLayerPointers) == LINK_UP) { 1356 mdlGetActiveMediaInfo(pLayerPointers); 1357 /* Link status changed */ 1358 if (pLayerPointers->pOdl->LinkStatus != 1359 LINK_STATE_UP) { 1360 pLayerPointers->pOdl->LinkStatus = 1361 LINK_STATE_UP; 1362 mac_link_update(pLayerPointers->pOdl->mh, 1363 LINK_STATE_UP); 1364 } 1365 } else { 1366 if (pLayerPointers->pOdl->LinkStatus != 1367 LINK_STATE_DOWN) { 1368 pLayerPointers->pOdl->LinkStatus = 1369 LINK_STATE_DOWN; 1370 mac_link_update(pLayerPointers->pOdl->mh, 1371 LINK_STATE_DOWN); 1372 } 1373 } 1374 } 1375 /* 1376 * RINT0: Receive Interrupt is set by the controller after the last 1377 * descriptor of a receive frame for this ring has been updated by 1378 * writing a 0 to the OWNership bit. 1379 */ 1380 if (intrCauses & RINT0) { 1381 pLayerPointers->pOdl->statistics.intr_RINT0 ++; 1382 amd8111s_receive(pLayerPointers); 1383 } 1384 1385 /* 1386 * TINT0: Transmit Interrupt is set by the controller after the OWN bit 1387 * in the last descriptor of a transmit frame in this particular ring 1388 * has been cleared to indicate the frame has been copied to the 1389 * transmit FIFO. 1390 */ 1391 if (intrCauses & TINT0) { 1392 pLayerPointers->pOdl->statistics.intr_TINT0 ++; 1393 /* 1394 * if desc ring is NULL and tx buf is not NULL, it should 1395 * drain tx buffer 1396 */ 1397 amd8111s_send_serial(pLayerPointers); 1398 } 1399 1400 if (intrCauses & STINT) { 1401 pLayerPointers->pOdl->statistics.intr_STINT ++; 1402 } 1403 1404 1405 return (DDI_INTR_CLAIMED); 1406 } 1407 1408 /* 1409 * To re-initilize data structures. 1410 */ 1411 static void 1412 amd8111s_sw_reset(struct LayerPointers *pLayerPointers) 1413 { 1414 /* Reset all Tx/Rx queues and descriptors */ 1415 milResetTxQ(pLayerPointers); 1416 milInitRxQ(pLayerPointers); 1417 } 1418 1419 /* 1420 * Send all pending tx packets 1421 */ 1422 static void 1423 amd8111s_tx_drain(struct LayerPointers *adapter) 1424 { 1425 struct tx_desc *pTx_desc = adapter->pMil->pNonphysical->TxDescQStart; 1426 int i, desc_count = 0; 1427 for (i = 0; i < 30; i++) { 1428 while ((pTx_desc->Tx_OWN == 0) && (desc_count < TX_RING_SIZE)) { 1429 /* This packet has been transmitted */ 1430 pTx_desc ++; 1431 desc_count ++; 1432 } 1433 if (desc_count == TX_RING_SIZE) { 1434 break; 1435 } 1436 /* Wait 1 ms */ 1437 drv_usecwait(1000); 1438 } 1439 adapter->pOdl->statistics.tx_draintime = i; 1440 } 1441 1442 /* 1443 * (GLD Entry Point) To start card will be called at 1444 * ifconfig plumb 1445 */ 1446 static int 1447 amd8111s_m_start(void *arg) 1448 { 1449 struct LayerPointers *pLayerPointers = arg; 1450 struct odl *pOdl = pLayerPointers->pOdl; 1451 1452 amd8111s_sw_reset(pLayerPointers); 1453 mdlHWReset(pLayerPointers); 1454 rw_enter(&pOdl->chip_lock, RW_WRITER); 1455 pLayerPointers->run = B_TRUE; 1456 rw_exit(&pOdl->chip_lock); 1457 return (0); 1458 } 1459 1460 /* 1461 * (GLD Entry Point) To stop card will be called at 1462 * ifconfig unplumb 1463 */ 1464 static void 1465 amd8111s_m_stop(void *arg) 1466 { 1467 struct LayerPointers *pLayerPointers = (struct LayerPointers *)arg; 1468 struct odl *pOdl = pLayerPointers->pOdl; 1469 1470 /* Ensure send all pending tx packets */ 1471 amd8111s_tx_drain(pLayerPointers); 1472 /* 1473 * Stop the controller and disable the controller interrupt 1474 */ 1475 rw_enter(&pOdl->chip_lock, RW_WRITER); 1476 mdlStopChip(pLayerPointers); 1477 pLayerPointers->run = B_FALSE; 1478 rw_exit(&pOdl->chip_lock); 1479 } 1480 1481 /* 1482 * To clean up all 1483 */ 1484 static void 1485 amd8111s_free_resource(struct LayerPointers *pLayerPointers) 1486 { 1487 unsigned long mem_free_array[100]; 1488 unsigned long *pmem_free_array, size; 1489 1490 /* Free Rx/Tx descriptors */ 1491 amd8111s_free_descriptors(pLayerPointers); 1492 1493 /* Free memory on lower layers */ 1494 milFreeResources(pLayerPointers, mem_free_array); 1495 pmem_free_array = mem_free_array; 1496 while (*pmem_free_array) { 1497 switch (*pmem_free_array) { 1498 case VIRTUAL: 1499 size = *(++pmem_free_array); 1500 pmem_free_array++; 1501 kmem_free((void *)*(pmem_free_array), size); 1502 break; 1503 } 1504 pmem_free_array++; 1505 } 1506 1507 amd8111s_free_buffers(pLayerPointers); 1508 } 1509 1510 /* 1511 * (GLD Enty pointer) To add/delete multi cast addresses 1512 * 1513 */ 1514 static int 1515 amd8111s_m_multicst(void *arg, boolean_t add, const uint8_t *addr) 1516 { 1517 struct LayerPointers *pLayerPointers = arg; 1518 1519 if (add) { 1520 /* Add a multicast entry */ 1521 mdlAddMulticastAddress(pLayerPointers, (UCHAR *)addr); 1522 } else { 1523 /* Delete a multicast entry */ 1524 mdlDeleteMulticastAddress(pLayerPointers, (UCHAR *)addr); 1525 } 1526 1527 return (0); 1528 } 1529 1530 #ifdef AMD8111S_DEBUG 1531 /* 1532 * The size of MIB registers is only 32 bits. Dump them before one 1533 * of them overflows. 1534 */ 1535 static void 1536 amd8111s_dump_mib(struct LayerPointers *pLayerPointers) 1537 { 1538 struct amd8111s_statistics *adapterStat; 1539 1540 adapterStat = &pLayerPointers->pOdl->statistics; 1541 1542 adapterStat->mib_dump_counter ++; 1543 1544 /* 1545 * Rx Counters 1546 */ 1547 adapterStat->rx_mib_unicst_packets += 1548 mdlReadMib(pLayerPointers, RcvUniCastPkts); 1549 adapterStat->rx_mib_multicst_packets += 1550 mdlReadMib(pLayerPointers, RcvMultiCastPkts); 1551 adapterStat->rx_mib_broadcst_packets += 1552 mdlReadMib(pLayerPointers, RcvBroadCastPkts); 1553 adapterStat->rx_mib_macctrl_packets += 1554 mdlReadMib(pLayerPointers, RcvMACCtrl); 1555 adapterStat->rx_mib_flowctrl_packets += 1556 mdlReadMib(pLayerPointers, RcvFlowCtrl); 1557 1558 adapterStat->rx_mib_bytes += 1559 mdlReadMib(pLayerPointers, RcvOctets); 1560 adapterStat->rx_mib_good_bytes += 1561 mdlReadMib(pLayerPointers, RcvGoodOctets); 1562 1563 adapterStat->rx_mib_undersize_packets += 1564 mdlReadMib(pLayerPointers, RcvUndersizePkts); 1565 adapterStat->rx_mib_oversize_packets += 1566 mdlReadMib(pLayerPointers, RcvOversizePkts); 1567 1568 adapterStat->rx_mib_drop_packets += 1569 mdlReadMib(pLayerPointers, RcvDropPktsRing0); 1570 adapterStat->rx_mib_align_err_packets += 1571 mdlReadMib(pLayerPointers, RcvAlignmentErrors); 1572 adapterStat->rx_mib_fcs_err_packets += 1573 mdlReadMib(pLayerPointers, RcvFCSErrors); 1574 adapterStat->rx_mib_symbol_err_packets += 1575 mdlReadMib(pLayerPointers, RcvSymbolErrors); 1576 adapterStat->rx_mib_miss_packets += 1577 mdlReadMib(pLayerPointers, RcvMissPkts); 1578 1579 /* 1580 * Tx Counters 1581 */ 1582 adapterStat->tx_mib_packets += 1583 mdlReadMib(pLayerPointers, XmtPackets); 1584 adapterStat->tx_mib_multicst_packets += 1585 mdlReadMib(pLayerPointers, XmtMultiCastPkts); 1586 adapterStat->tx_mib_broadcst_packets += 1587 mdlReadMib(pLayerPointers, XmtBroadCastPkts); 1588 adapterStat->tx_mib_flowctrl_packets += 1589 mdlReadMib(pLayerPointers, XmtFlowCtrl); 1590 1591 adapterStat->tx_mib_bytes += 1592 mdlReadMib(pLayerPointers, XmtOctets); 1593 1594 adapterStat->tx_mib_defer_trans_packets += 1595 mdlReadMib(pLayerPointers, XmtDeferredTransmit); 1596 adapterStat->tx_mib_collision_packets += 1597 mdlReadMib(pLayerPointers, XmtCollisions); 1598 adapterStat->tx_mib_one_coll_packets += 1599 mdlReadMib(pLayerPointers, XmtOneCollision); 1600 adapterStat->tx_mib_multi_coll_packets += 1601 mdlReadMib(pLayerPointers, XmtMultipleCollision); 1602 adapterStat->tx_mib_late_coll_packets += 1603 mdlReadMib(pLayerPointers, XmtLateCollision); 1604 adapterStat->tx_mib_ex_coll_packets += 1605 mdlReadMib(pLayerPointers, XmtExcessiveCollision); 1606 1607 1608 /* Clear all MIB registers */ 1609 WRITE_REG16(pLayerPointers, pLayerPointers->pMdl->Mem_Address 1610 + MIB_ADDR, MIB_CLEAR); 1611 } 1612 #endif 1613 1614 /* 1615 * (GLD Entry Point) set/unset promiscus mode 1616 */ 1617 static int 1618 amd8111s_m_promisc(void *arg, boolean_t on) 1619 { 1620 struct LayerPointers *pLayerPointers = arg; 1621 1622 if (on) { 1623 mdlSetPromiscuous(pLayerPointers); 1624 } else { 1625 mdlDisablePromiscuous(pLayerPointers); 1626 } 1627 1628 return (0); 1629 } 1630 1631 /* 1632 * (Gld Entry point) Changes the Mac address of card 1633 */ 1634 static int 1635 amd8111s_m_unicst(void *arg, const uint8_t *macaddr) 1636 { 1637 struct LayerPointers *pLayerPointers = arg; 1638 1639 mdlDisableInterrupt(pLayerPointers); 1640 mdlSetMacAddress(pLayerPointers, (unsigned char *)macaddr); 1641 mdlEnableInterrupt(pLayerPointers); 1642 1643 return (0); 1644 } 1645 1646 /* 1647 * Reset the card 1648 */ 1649 void 1650 amd8111s_reset(struct LayerPointers *pLayerPointers) 1651 { 1652 amd8111s_sw_reset(pLayerPointers); 1653 mdlHWReset(pLayerPointers); 1654 } 1655 1656 /* 1657 * attach(9E) -- Attach a device to the system 1658 * 1659 * Called once for each board after successfully probed. 1660 * will do 1661 * a. creating minor device node for the instance. 1662 * b. allocate & Initilize four layers (call odlInit) 1663 * c. get MAC address 1664 * d. initilize pLayerPointers to gld private pointer 1665 * e. register with GLD 1666 * if any action fails does clean up & returns DDI_FAILURE 1667 * else retursn DDI_SUCCESS 1668 */ 1669 static int 1670 amd8111s_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 1671 { 1672 mac_register_t *macp; 1673 struct LayerPointers *pLayerPointers; 1674 struct odl *pOdl; 1675 ddi_acc_handle_t *pci_handle; 1676 ddi_device_acc_attr_t dev_attr; 1677 caddr_t addrp = NULL; 1678 1679 switch (cmd) { 1680 case DDI_ATTACH: 1681 break; 1682 default: 1683 return (DDI_FAILURE); 1684 } 1685 1686 pLayerPointers = (struct LayerPointers *) 1687 kmem_zalloc(sizeof (struct LayerPointers), KM_SLEEP); 1688 amd8111sadapter = pLayerPointers; 1689 1690 /* Get device instance number */ 1691 pLayerPointers->instance = ddi_get_instance(devinfo); 1692 ddi_set_driver_private(devinfo, (caddr_t)pLayerPointers); 1693 1694 pOdl = (struct odl *)kmem_zalloc(sizeof (struct odl), KM_SLEEP); 1695 pLayerPointers->pOdl = pOdl; 1696 1697 pOdl->devinfo = devinfo; 1698 1699 /* 1700 * Here, we only allocate memory for struct odl and initilize it. 1701 * All other memory allocation & initilization will be done in odlInit 1702 * later on this routine. 1703 */ 1704 if (ddi_get_iblock_cookie(devinfo, 0, &pLayerPointers->pOdl->iblock) 1705 != DDI_SUCCESS) { 1706 amd8111s_log(pLayerPointers, CE_NOTE, 1707 "attach: get iblock cookies failed"); 1708 goto attach_failure; 1709 } 1710 1711 rw_init(&pOdl->chip_lock, NULL, RW_DRIVER, (void *)pOdl->iblock); 1712 mutex_init(&pOdl->mdlSendLock, "amd8111s Send Protection Lock", 1713 MUTEX_DRIVER, (void *)pOdl->iblock); 1714 mutex_init(&pOdl->mdlRcvLock, "amd8111s Rcv Protection Lock", 1715 MUTEX_DRIVER, (void *)pOdl->iblock); 1716 1717 /* Setup PCI space */ 1718 if (pci_config_setup(devinfo, &pOdl->pci_handle) != DDI_SUCCESS) { 1719 return (DDI_FAILURE); 1720 } 1721 pLayerPointers->attach_progress = AMD8111S_ATTACH_PCI; 1722 pci_handle = &pOdl->pci_handle; 1723 1724 pOdl->vendor_id = pci_config_get16(*pci_handle, PCI_CONF_VENID); 1725 pOdl->device_id = pci_config_get16(*pci_handle, PCI_CONF_DEVID); 1726 1727 /* 1728 * Allocate and initialize all resource and map device registers. 1729 * If failed, it returns a non-zero value. 1730 */ 1731 if (amd8111s_odlInit(pLayerPointers) != 0) { 1732 goto attach_failure; 1733 } 1734 pLayerPointers->attach_progress |= AMD8111S_ATTACH_RESOURCE; 1735 1736 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 1737 dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 1738 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 1739 1740 if (ddi_regs_map_setup(devinfo, 1, &addrp, 0, 4096, &dev_attr, 1741 &(pLayerPointers->pOdl->MemBasehandle)) != 0) { 1742 amd8111s_log(pLayerPointers, CE_NOTE, 1743 "attach: ddi_regs_map_setup failed"); 1744 goto attach_failure; 1745 } 1746 pLayerPointers->pMdl->Mem_Address = (unsigned long)addrp; 1747 1748 /* Initialize HW */ 1749 mdlOpen(pLayerPointers); 1750 mdlGetActiveMediaInfo(pLayerPointers); 1751 pLayerPointers->attach_progress |= AMD8111S_ATTACH_REGS; 1752 1753 /* 1754 * Setup the interrupt 1755 */ 1756 if (ddi_add_intr(devinfo, 0, &pOdl->iblock, 0, amd8111s_intr, 1757 (caddr_t)pLayerPointers) != DDI_SUCCESS) { 1758 goto attach_failure; 1759 } 1760 pLayerPointers->attach_progress |= AMD8111S_ATTACH_INTRADDED; 1761 1762 /* 1763 * Setup soft intr 1764 */ 1765 if (ddi_add_softintr(devinfo, DDI_SOFTINT_LOW, &pOdl->drain_id, 1766 NULL, NULL, amd8111s_send_drain, 1767 (caddr_t)pLayerPointers) != DDI_SUCCESS) { 1768 goto attach_failure; 1769 } 1770 pLayerPointers->attach_progress |= AMD8111S_ATTACH_RESCHED; 1771 1772 /* 1773 * Initilize the mac structure 1774 */ 1775 if ((macp = mac_alloc(MAC_VERSION)) == NULL) 1776 goto attach_failure; 1777 1778 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 1779 macp->m_driver = pLayerPointers; 1780 macp->m_dip = devinfo; 1781 /* Get MAC address */ 1782 mdlGetMacAddress(pLayerPointers, (unsigned char *)pOdl->MacAddress); 1783 macp->m_src_addr = pOdl->MacAddress; 1784 macp->m_callbacks = &amd8111s_m_callbacks; 1785 macp->m_min_sdu = 0; 1786 /* 1518 - 14 (ether header) - 4 (CRC) */ 1787 macp->m_max_sdu = ETHERMTU; 1788 macp->m_margin = VLAN_TAGSZ; 1789 1790 /* 1791 * Finally, we're ready to register ourselves with the MAC layer 1792 * interface; if this succeeds, we're ready to start. 1793 */ 1794 if (mac_register(macp, &pOdl->mh) != DDI_SUCCESS) { 1795 mac_free(macp); 1796 goto attach_failure; 1797 } 1798 mac_free(macp); 1799 1800 pLayerPointers->attach_progress |= AMD8111S_ATTACH_MACREGED; 1801 1802 return (DDI_SUCCESS); 1803 1804 attach_failure: 1805 (void) amd8111s_unattach(devinfo, pLayerPointers); 1806 return (DDI_FAILURE); 1807 1808 } 1809 1810 /* 1811 * detach(9E) -- Detach a device from the system 1812 * 1813 * It is called for each device instance when the system is preparing to 1814 * unload a dynamically unloadable driver. 1815 * will Do 1816 * a. check if any driver buffers are held by OS. 1817 * b. do clean up of all allocated memory if it is not in use by OS. 1818 * c. un register with GLD 1819 * d. return DDI_SUCCESS on succes full free & unregister 1820 * else GLD_FAILURE 1821 */ 1822 static int 1823 amd8111s_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 1824 { 1825 struct LayerPointers *pLayerPointers; 1826 1827 switch (cmd) { 1828 case DDI_DETACH: 1829 break; 1830 default: 1831 return (DDI_FAILURE); 1832 } 1833 1834 /* 1835 * Get the driver private (struct LayerPointers *) structure 1836 */ 1837 if ((pLayerPointers = (struct LayerPointers *)ddi_get_driver_private 1838 (devinfo)) == NULL) { 1839 return (DDI_FAILURE); 1840 } 1841 1842 return (amd8111s_unattach(devinfo, pLayerPointers)); 1843 } 1844 1845 static int 1846 amd8111s_unattach(dev_info_t *devinfo, struct LayerPointers *pLayerPointers) 1847 { 1848 struct odl *pOdl = pLayerPointers->pOdl; 1849 1850 if (pLayerPointers->attach_progress & AMD8111S_ATTACH_MACREGED) { 1851 /* Unregister driver from the GLD interface */ 1852 if (mac_unregister(pOdl->mh) != DDI_SUCCESS) { 1853 return (DDI_FAILURE); 1854 } 1855 } 1856 1857 if (pLayerPointers->attach_progress & AMD8111S_ATTACH_INTRADDED) { 1858 ddi_remove_intr(devinfo, 0, pOdl->iblock); 1859 } 1860 1861 if (pLayerPointers->attach_progress & AMD8111S_ATTACH_RESCHED) { 1862 ddi_remove_softintr(pOdl->drain_id); 1863 } 1864 1865 if (pLayerPointers->attach_progress & AMD8111S_ATTACH_REGS) { 1866 /* Stop HW */ 1867 mdlStopChip(pLayerPointers); 1868 ddi_regs_map_free(&(pOdl->MemBasehandle)); 1869 } 1870 1871 if (pLayerPointers->attach_progress & AMD8111S_ATTACH_RESOURCE) { 1872 /* Free All memory allocated */ 1873 amd8111s_free_resource(pLayerPointers); 1874 } 1875 1876 if (pLayerPointers->attach_progress & AMD8111S_ATTACH_PCI) { 1877 pci_config_teardown(&pOdl->pci_handle); 1878 mutex_destroy(&pOdl->mdlSendLock); 1879 mutex_destroy(&pOdl->mdlRcvLock); 1880 rw_destroy(&pOdl->chip_lock); 1881 } 1882 1883 kmem_free(pOdl, sizeof (struct odl)); 1884 kmem_free(pLayerPointers, sizeof (struct LayerPointers)); 1885 1886 return (DDI_SUCCESS); 1887 } 1888 1889 /* 1890 * (GLD Entry Point)GLD will call this entry point perodicaly to 1891 * get driver statistices. 1892 */ 1893 static int 1894 amd8111s_m_stat(void *arg, uint_t stat, uint64_t *val) 1895 { 1896 struct LayerPointers *pLayerPointers = arg; 1897 struct amd8111s_statistics *adapterStat; 1898 1899 adapterStat = &pLayerPointers->pOdl->statistics; 1900 1901 switch (stat) { 1902 1903 /* 1904 * Current Status 1905 */ 1906 case MAC_STAT_IFSPEED: 1907 *val = pLayerPointers->pMdl->Speed * 1000000; 1908 break; 1909 1910 case ETHER_STAT_LINK_DUPLEX: 1911 if (pLayerPointers->pMdl->FullDuplex) { 1912 *val = LINK_DUPLEX_FULL; 1913 } else { 1914 *val = LINK_DUPLEX_HALF; 1915 } 1916 break; 1917 1918 /* 1919 * Capabilities 1920 */ 1921 case ETHER_STAT_CAP_1000FDX: 1922 *val = 0; 1923 break; 1924 1925 case ETHER_STAT_CAP_1000HDX: 1926 *val = 0; 1927 break; 1928 1929 case ETHER_STAT_CAP_100FDX: 1930 *val = 1; 1931 break; 1932 1933 case ETHER_STAT_CAP_100HDX: 1934 *val = 1; 1935 break; 1936 1937 case ETHER_STAT_CAP_10FDX: 1938 *val = 1; 1939 break; 1940 1941 case ETHER_STAT_CAP_10HDX: 1942 *val = 1; 1943 break; 1944 1945 case ETHER_STAT_CAP_ASMPAUSE: 1946 *val = 1; 1947 break; 1948 1949 case ETHER_STAT_CAP_PAUSE: 1950 *val = 1; 1951 break; 1952 1953 case ETHER_STAT_CAP_AUTONEG: 1954 *val = 1; 1955 break; 1956 1957 case ETHER_STAT_ADV_CAP_1000FDX: 1958 *val = 0; 1959 break; 1960 1961 case ETHER_STAT_ADV_CAP_1000HDX: 1962 *val = 0; 1963 break; 1964 1965 case ETHER_STAT_ADV_CAP_100FDX: 1966 *val = 1; 1967 break; 1968 1969 case ETHER_STAT_ADV_CAP_100HDX: 1970 *val = 1; 1971 break; 1972 1973 case ETHER_STAT_ADV_CAP_10FDX: 1974 *val = 1; 1975 break; 1976 1977 case ETHER_STAT_ADV_CAP_10HDX: 1978 *val = 1; 1979 break; 1980 1981 case ETHER_STAT_ADV_CAP_ASMPAUSE: 1982 *val = 1; 1983 break; 1984 1985 case ETHER_STAT_ADV_CAP_PAUSE: 1986 *val = 1; 1987 break; 1988 1989 case ETHER_STAT_ADV_CAP_AUTONEG: 1990 *val = 1; 1991 break; 1992 1993 /* 1994 * Rx Counters 1995 */ 1996 case MAC_STAT_IPACKETS: 1997 *val = adapterStat->rx_mib_unicst_packets + 1998 adapterStat->rx_mib_multicst_packets + 1999 adapterStat->rx_mib_broadcst_packets + 2000 mdlReadMib(pLayerPointers, RcvUniCastPkts) + 2001 mdlReadMib(pLayerPointers, RcvMultiCastPkts) + 2002 mdlReadMib(pLayerPointers, RcvBroadCastPkts); 2003 break; 2004 2005 case MAC_STAT_RBYTES: 2006 *val = adapterStat->rx_mib_bytes + 2007 mdlReadMib(pLayerPointers, RcvOctets); 2008 break; 2009 2010 case MAC_STAT_MULTIRCV: 2011 *val = adapterStat->rx_mib_multicst_packets + 2012 mdlReadMib(pLayerPointers, RcvMultiCastPkts); 2013 break; 2014 2015 case MAC_STAT_BRDCSTRCV: 2016 *val = adapterStat->rx_mib_broadcst_packets + 2017 mdlReadMib(pLayerPointers, RcvBroadCastPkts); 2018 break; 2019 2020 case MAC_STAT_NORCVBUF: 2021 *val = adapterStat->rx_allocfail + 2022 adapterStat->rx_mib_drop_packets + 2023 mdlReadMib(pLayerPointers, RcvDropPktsRing0); 2024 break; 2025 2026 case MAC_STAT_IERRORS: 2027 *val = adapterStat->rx_mib_align_err_packets + 2028 adapterStat->rx_mib_fcs_err_packets + 2029 adapterStat->rx_mib_symbol_err_packets + 2030 mdlReadMib(pLayerPointers, RcvAlignmentErrors) + 2031 mdlReadMib(pLayerPointers, RcvFCSErrors) + 2032 mdlReadMib(pLayerPointers, RcvSymbolErrors); 2033 break; 2034 2035 case ETHER_STAT_ALIGN_ERRORS: 2036 *val = adapterStat->rx_mib_align_err_packets + 2037 mdlReadMib(pLayerPointers, RcvAlignmentErrors); 2038 break; 2039 2040 case ETHER_STAT_FCS_ERRORS: 2041 *val = adapterStat->rx_mib_fcs_err_packets + 2042 mdlReadMib(pLayerPointers, RcvFCSErrors); 2043 break; 2044 2045 /* 2046 * Tx Counters 2047 */ 2048 case MAC_STAT_OPACKETS: 2049 *val = adapterStat->tx_mib_packets + 2050 mdlReadMib(pLayerPointers, XmtPackets); 2051 break; 2052 2053 case MAC_STAT_OBYTES: 2054 *val = adapterStat->tx_mib_bytes + 2055 mdlReadMib(pLayerPointers, XmtOctets); 2056 break; 2057 2058 case MAC_STAT_MULTIXMT: 2059 *val = adapterStat->tx_mib_multicst_packets + 2060 mdlReadMib(pLayerPointers, XmtMultiCastPkts); 2061 break; 2062 2063 case MAC_STAT_BRDCSTXMT: 2064 *val = adapterStat->tx_mib_broadcst_packets + 2065 mdlReadMib(pLayerPointers, XmtBroadCastPkts); 2066 break; 2067 2068 case MAC_STAT_NOXMTBUF: 2069 *val = adapterStat->tx_no_descriptor; 2070 break; 2071 2072 case MAC_STAT_OERRORS: 2073 *val = adapterStat->tx_mib_ex_coll_packets + 2074 mdlReadMib(pLayerPointers, XmtExcessiveCollision); 2075 break; 2076 2077 case MAC_STAT_COLLISIONS: 2078 *val = adapterStat->tx_mib_ex_coll_packets + 2079 mdlReadMib(pLayerPointers, XmtCollisions); 2080 break; 2081 2082 case ETHER_STAT_FIRST_COLLISIONS: 2083 *val = adapterStat->tx_mib_one_coll_packets + 2084 mdlReadMib(pLayerPointers, XmtOneCollision); 2085 break; 2086 2087 case ETHER_STAT_MULTI_COLLISIONS: 2088 *val = adapterStat->tx_mib_multi_coll_packets + 2089 mdlReadMib(pLayerPointers, XmtMultipleCollision); 2090 break; 2091 2092 case ETHER_STAT_EX_COLLISIONS: 2093 *val = adapterStat->tx_mib_ex_coll_packets + 2094 mdlReadMib(pLayerPointers, XmtExcessiveCollision); 2095 break; 2096 2097 case ETHER_STAT_TX_LATE_COLLISIONS: 2098 *val = adapterStat->tx_mib_late_coll_packets + 2099 mdlReadMib(pLayerPointers, XmtLateCollision); 2100 break; 2101 2102 case ETHER_STAT_DEFER_XMTS: 2103 *val = adapterStat->tx_mib_defer_trans_packets + 2104 mdlReadMib(pLayerPointers, XmtDeferredTransmit); 2105 break; 2106 2107 default: 2108 return (ENOTSUP); 2109 } 2110 return (0); 2111 } 2112 2113 /* 2114 * Memory Read Function Used by MDL to set card registers. 2115 */ 2116 unsigned char 2117 READ_REG8(struct LayerPointers *pLayerPointers, long x) 2118 { 2119 return (ddi_get8(pLayerPointers->pOdl->MemBasehandle, (uint8_t *)x)); 2120 } 2121 2122 int 2123 READ_REG16(struct LayerPointers *pLayerPointers, long x) 2124 { 2125 return (ddi_get16(pLayerPointers->pOdl->MemBasehandle, 2126 (uint16_t *)(x))); 2127 } 2128 2129 long 2130 READ_REG32(struct LayerPointers *pLayerPointers, long x) 2131 { 2132 return (ddi_get32(pLayerPointers->pOdl->MemBasehandle, 2133 (uint32_t *)(x))); 2134 } 2135 2136 void 2137 WRITE_REG8(struct LayerPointers *pLayerPointers, long x, int y) 2138 { 2139 ddi_put8(pLayerPointers->pOdl->MemBasehandle, (uint8_t *)(x), y); 2140 } 2141 2142 void 2143 WRITE_REG16(struct LayerPointers *pLayerPointers, long x, int y) 2144 { 2145 ddi_put16(pLayerPointers->pOdl->MemBasehandle, (uint16_t *)(x), y); 2146 } 2147 2148 void 2149 WRITE_REG32(struct LayerPointers *pLayerPointers, long x, int y) 2150 { 2151 ddi_put32(pLayerPointers->pOdl->MemBasehandle, (uint32_t *)(x), y); 2152 } 2153 2154 void 2155 WRITE_REG64(struct LayerPointers *pLayerPointers, long x, char *y) 2156 { 2157 int i; 2158 for (i = 0; i < 8; i++) { 2159 WRITE_REG8(pLayerPointers, (x + i), y[i]); 2160 } 2161 }