/pcn/src/pcn.c
C | 1748 lines | 1288 code | 337 blank | 123 comment | 204 complexity | 16530b3e839acff0e00f58e39f0a076f MD5 | raw file
1/* 2 * Copyright (c) 2000 Berkeley Software Design, Inc. 3 * Copyright (c) 1997, 1998, 1999, 2000 4 * Bill Paul <wpaul@osd.bsdi.com>. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Bill Paul. 17 * 4. Neither the name of the author nor the names of any co-contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 * THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34#include <sys/varargs.h> 35#include <sys/types.h> 36#include <sys/modctl.h> 37#include <sys/devops.h> 38#include <sys/stream.h> 39#include <sys/strsun.h> 40#include <sys/cmn_err.h> 41#include <sys/ethernet.h> 42#include <sys/kmem.h> 43#include <sys/crc32.h> 44#include <sys/mii.h> 45#include <sys/miiregs.h> 46#include <sys/mac.h> 47#include <sys/mac_ether.h> 48#include <sys/ddi.h> 49#include <sys/sunddi.h> 50#include <sys/vlan.h> 51#include <sys/pci.h> 52#include <sys/conf.h> 53 54#include "pcn.h" 55#include "pcnimpl.h" 56 57#define ETHERVLANMTU (ETHERMAX + 4) 58 59#define CSR_WRITE_4(pcnp, reg, val) \ 60 ddi_put32(pcnp->pcn_regshandle, (uint32_t *)(pcnp->pcn_regs + reg), val) 61 62#define CSR_WRITE_2(pcnp, reg, val) \ 63 ddi_put16(pcnp->pcn_regshandle, (uint16_t *)(pcnp->pcn_regs + reg), val) 64 65#define CSR_READ_4(pcnp, reg) \ 66 ddi_get32(pcnp->pcn_regshandle, (uint32_t *)(pcnp->pcn_regs + reg)) 67 68#define CSR_READ_2(pcnp, reg) \ 69 ddi_get16(pcnp->pcn_regshandle, (uint16_t *)(pcnp->pcn_regs + reg)) 70 71#define PCN_CSR_SETBIT(pcnp, reg, x) \ 72 pcn_csr_write(pcnp, reg, pcn_csr_read(pcnp, reg) | (x)) 73 74#define PCN_CSR_CLRBIT(pcnp, reg, x) \ 75 pcn_csr_write(pcnp, reg, pcn_csr_read(pcnp, reg) & ~(x)) 76 77#define PCN_BCR_SETBIT(pncp, reg, x) \ 78 pcn_bcr_write(pcnp, reg, pcn_bcr_read(pcnp, reg) | (x)) 79 80#define PCN_BCR_CLRBIT(pcnp, reg, x) \ 81 pcn_bcr_write(pcnp, reg, pcn_bcr_read(pcnp, reg) & ~(x)) 82 83static int pcn_attach(dev_info_t *, ddi_attach_cmd_t); 84static int pcn_detach(dev_info_t *, ddi_detach_cmd_t); 85static int pcn_resume(dev_info_t *); 86static int pcn_quiesce(dev_info_t *); 87 88static int pcn_setup_intr(pcn_t *); 89static int pcn_teardown_intr(pcn_t *); 90 91static int pcn_m_unicast(void *, const uint8_t *); 92static int pcn_m_multicast(void *, boolean_t, const uint8_t *); 93static int pcn_m_promisc(void *, boolean_t); 94static mblk_t *pcn_m_tx(void *, mblk_t *); 95static void pcn_m_ioctl(void *, queue_t *, mblk_t *); 96static int pcn_m_stat(void *, uint_t, uint64_t *); 97static int pcn_m_start(void *); 98static void pcn_m_stop(void *); 99static int pcn_m_getprop(void *, const char *, mac_prop_id_t, uint_t, 100 uint_t, void *, uint_t *); 101static int pcn_m_setprop(void *, const char *, mac_prop_id_t, uint_t, 102 const void *); 103 104static unsigned pcn_intr(caddr_t, caddr_t); 105 106static uint16_t pcn_mii_read(void *, uint8_t, uint8_t); 107static void pcn_mii_write(void *, uint8_t, uint8_t, uint16_t); 108static void pcn_mii_notify(void *, link_state_t); 109 110static uint32_t pcn_csr_read(pcn_t *, uint32_t); 111static uint16_t pcn_csr_read16(pcn_t *, uint32_t); 112static void pcn_csr_write(pcn_t *, uint32_t, uint32_t); 113 114static uint32_t pcn_bcr_read(pcn_t *, uint32_t); 115static uint16_t pcn_bcr_read16(pcn_t *, uint32_t); 116static void pcn_bcr_write(pcn_t *, uint32_t, uint32_t); 117 118static boolean_t pcn_send(pcn_t *, mblk_t *); 119 120static int pcn_allocrxring(pcn_t *); 121static int pcn_alloctxring(pcn_t *); 122static void pcn_freetxring(pcn_t *); 123static void pcn_freerxring(pcn_t *); 124static void pcn_resetrings(pcn_t *); 125static int pcn_initialize(pcn_t *); 126static void pcn_enableinterrupts(pcn_t *); 127static void pcn_disableinterrupts(pcn_t *); 128static mblk_t *pcn_receive(pcn_t *); 129static void pcn_resetall(pcn_t *); 130static void pcn_startall(pcn_t *); 131static void pcn_stopall(pcn_t *); 132static void pcn_reclaim(pcn_t *); 133static void pcn_setrxfilt(pcn_t *); 134static void pcn_getfactaddr(pcn_t *); 135static int pcn_set_chipid(pcn_t *, uint32_t); 136static const pcn_type_t *pcn_match(uint16_t, uint16_t); 137static char *pcn_chipid_name(uint32_t); 138 139static void pcn_error(dev_info_t *, char *, ...); 140 141void *pcn_ssp = NULL; 142 143static uchar_t pcn_broadcast[ETHERADDRL] = { 144 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 145}; 146 147static const pcn_type_t pcn_devs[] = { 148 { PCN_VENDORID, PCN_DEVICEID_PCNET, "AMD PCnet/PCI 10/100BaseTX" }, 149 { PCN_VENDORID, PCN_DEVICEID_HOME, "AMD PCnet/Home HomePNA" }, 150 { 0, 0, NULL } 151}; 152 153static const struct pcn_chipid { 154 uint32_t id; 155 char *name; 156} pcn_chipid[] = { 157 { Am79C971, "Am79C971" }, 158 { Am79C972, "Am79C972" }, 159 { Am79C973, "Am79C973" }, 160 { Am79C978, "Am79C978" }, 161 { Am79C975, "Am79C975" }, 162 { Am79C976, "Am79C976" }, 163 { 0, NULL }, 164}; 165 166static mii_ops_t pcn_mii_ops = { 167 MII_OPS_VERSION, 168 pcn_mii_read, 169 pcn_mii_write, 170 pcn_mii_notify, 171 NULL 172}; 173 174static mac_callbacks_t pcn_m_callbacks = { 175 MC_IOCTL | MC_SETPROP | MC_GETPROP, 176 pcn_m_stat, 177 pcn_m_start, 178 pcn_m_stop, 179 pcn_m_promisc, 180 pcn_m_multicast, 181 pcn_m_unicast, 182 pcn_m_tx, 183 pcn_m_ioctl, 184 NULL, /* mc_getcapab */ 185 NULL, /* mc_open */ 186 NULL, /* mc_close */ 187 pcn_m_setprop, 188 pcn_m_getprop 189}; 190 191DDI_DEFINE_STREAM_OPS(pcn_devops, nulldev, nulldev, pcn_attach, pcn_detach, 192 nodev, NULL, D_MP, NULL, pcn_quiesce); 193 194static struct modldrv pcn_modldrv = { 195 &mod_driverops, 196 "AMD PCnet", 197 &pcn_devops 198}; 199 200static struct modlinkage pcn_modlinkage = { 201 MODREV_1, 202 { &pcn_modldrv, NULL } 203}; 204 205static ddi_device_acc_attr_t pcn_devattr = { 206 DDI_DEVICE_ATTR_V0, 207 DDI_STRUCTURE_LE_ACC, 208 DDI_STRICTORDER_ACC 209}; 210 211static ddi_device_acc_attr_t pcn_bufattr = { 212 DDI_DEVICE_ATTR_V0, 213 DDI_NEVERSWAP_ACC, 214 DDI_STRICTORDER_ACC 215}; 216 217static ddi_dma_attr_t pcn_dma_attr = { 218 DMA_ATTR_V0, /* dm_attr_version */ 219 0, /* dma_attr_addr_lo */ 220 0xFFFFFFFFU, /* dma_attr_addr_hi */ 221 0x7FFFFFFFU, /* dma_attr_count_max */ 222 4, /* dma_attr_align */ 223 0x3F, /* dma_attr_burstsizes */ 224 1, /* dma_attr_minxfer */ 225 0xFFFFFFFFU, /* dma_attr_maxxfer */ 226 0xFFFFFFFFU, /* dma_attr_seg */ 227 1, /* dma_attr_sgllen */ 228 1, /* dma_attr_granular */ 229 0 /* dma_attr_flags */ 230}; 231 232static ddi_dma_attr_t pcn_dmadesc_attr = { 233 DMA_ATTR_V0, /* dm_attr_version */ 234 0, /* dma_attr_addr_lo */ 235 0xFFFFFFFFU, /* dma_attr_addr_hi */ 236 0x7FFFFFFFU, /* dma_attr_count_max */ 237 16, /* dma_attr_align */ 238 0x3F, /* dma_attr_burstsizes */ 239 1, /* dma_attr_minxfer */ 240 0xFFFFFFFFU, /* dma_attr_maxxfer */ 241 0xFFFFFFFFU, /* dma_attr_seg */ 242 1, /* dma_attr_sgllen */ 243 1, /* dma_attr_granular */ 244 0 /* dma_attr_flags */ 245}; 246 247/* 248 * DDI entry points 249 */ 250int 251_init(void) 252{ 253 int rc; 254 255 if ((rc = ddi_soft_state_init(&pcn_ssp, sizeof (pcn_t), 1)) != 0) 256 return (rc); 257 258 mac_init_ops(&pcn_devops, "pcn"); 259 if ((rc = mod_install(&pcn_modlinkage)) != DDI_SUCCESS) { 260 mac_fini_ops(&pcn_devops); 261 ddi_soft_state_fini(&pcn_ssp); 262 } 263 264 return (rc); 265} 266 267int 268_fini(void) 269{ 270 int rc; 271 272 if ((rc = mod_remove(&pcn_modlinkage)) == DDI_SUCCESS) { 273 mac_fini_ops(&pcn_devops); 274 ddi_soft_state_fini(&pcn_ssp); 275 } 276 277 return (rc); 278} 279 280int 281_info(struct modinfo *modinfop) 282{ 283 return (mod_info(&pcn_modlinkage, modinfop)); 284} 285 286int 287pcn_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 288{ 289 pcn_t *pcnp; 290 mac_register_t *macp; 291 const pcn_type_t *pcn_type; 292 int instance = ddi_get_instance(dip); 293 int rc; 294 ddi_acc_handle_t pci; 295 uint32_t chipid; 296 uint16_t venid; 297 uint16_t devid; 298 uint16_t svid; 299 uint16_t ssid; 300 uint16_t cachesize; 301 302 switch (cmd) { 303 case DDI_RESUME: 304 return (pcn_resume(dip)); 305 306 case DDI_ATTACH: 307 break; 308 309 default: 310 return (DDI_FAILURE); 311 } 312 313 if (ddi_slaveonly(dip) == DDI_SUCCESS) { 314 pcn_error(dip, "slot does not support PCI bus-master"); 315 return (DDI_FAILURE); 316 } 317 318 if (ddi_intr_hilevel(dip, 0) != 0) { 319 pcn_error(dip, "hilevel interrupts not supported"); 320 return (DDI_FAILURE); 321 } 322 323 if (pci_config_setup(dip, &pci) != DDI_SUCCESS) { 324 pcn_error(dip, "unable to setup PCI config handle"); 325 return (DDI_FAILURE); 326 } 327 328 venid = pci_config_get16(pci, PCI_CONF_VENID); 329 devid = pci_config_get16(pci, PCI_CONF_DEVID); 330 svid = pci_config_get16(pci, PCI_CONF_SUBVENID); 331 ssid = pci_config_get16(pci, PCI_CONF_SUBSYSID); 332 333 if ((pcn_type = pcn_match(venid, devid)) == NULL) { 334 pci_config_teardown(&pci); 335 pcn_error(dip, "Unable to identify PCI card"); 336 return (DDI_FAILURE); 337 } 338 339 if (ddi_prop_update_string(DDI_DEV_T_NONE, dip, "model", 340 pcn_type->pcn_name) != DDI_PROP_SUCCESS) { 341 pci_config_teardown(&pci); 342 pcn_error(dip, "Unable to create model property"); 343 return (DDI_FAILURE); 344 } 345 346 cachesize = pci_config_get8(pci, PCI_CONF_CACHE_LINESZ); 347 348 if (ddi_soft_state_zalloc(pcn_ssp, instance) != DDI_SUCCESS) { 349 pcn_error(dip, "Unable to allocate soft state"); 350 pci_config_teardown(&pci); 351 return (DDI_FAILURE); 352 } 353 354 pcnp = ddi_get_soft_state(pcn_ssp, instance); 355 pcnp->pcn_dip = dip; 356 pcnp->pcn_instance = instance; 357 358 if (pcn_setup_intr(pcnp) != DDI_SUCCESS) { 359 ddi_soft_state_free(pcn_ssp, instance); 360 pci_config_teardown(&pci); 361 return (DDI_FAILURE); 362 } 363 364 mutex_init(&pcnp->pcn_xmtlock, NULL, MUTEX_DRIVER, 365 DDI_INTR_PRI(pcnp->pcn_int_pri)); 366 mutex_init(&pcnp->pcn_intrlock, NULL, MUTEX_DRIVER, 367 DDI_INTR_PRI(pcnp->pcn_int_pri)); 368 369 /* 370 * Enable bus master, IO space, and memory space accesses 371 */ 372 pci_config_put16(pci, PCI_CONF_COMM, 373 pci_config_get16(pci, PCI_CONF_COMM) | PCI_COMM_ME | PCI_COMM_MAE); 374 375 pci_config_teardown(&pci); 376 377 if ((pcnp->pcn_mii = mii_alloc(pcnp, dip, &pcn_mii_ops)) == NULL) 378 goto fail; 379 380 mii_set_pauseable(pcnp->pcn_mii, B_TRUE, B_TRUE); 381 382 if (ddi_regs_map_setup(dip, 1, (caddr_t *)&pcnp->pcn_regs, 0, 0, 383 &pcn_devattr, &pcnp->pcn_regshandle)) { 384 pcn_error(dip, "ddi_regs_map_setup failed"); 385 goto fail; 386 } 387 388 if (pcn_set_chipid(pcnp, (uint32_t)ssid << 16 | (uint32_t)svid) != 389 DDI_SUCCESS) { 390 goto fail; 391 } 392 393 if ((pcn_allocrxring(pcnp) != DDI_SUCCESS) || 394 (pcn_alloctxring(pcnp) != DDI_SUCCESS)) { 395 pcn_error(dip, "unable to allocate DMA resources"); 396 goto fail; 397 } 398 399 mutex_enter(&pcnp->pcn_intrlock); 400 mutex_enter(&pcnp->pcn_xmtlock); 401 rc = pcn_initialize(pcnp); 402 mutex_exit(&pcnp->pcn_xmtlock); 403 mutex_exit(&pcnp->pcn_intrlock); 404 if (rc != DDI_SUCCESS) 405 goto fail; 406 407 pcn_getfactaddr(pcnp); 408 pcnp->pcn_promisc = B_FALSE; 409 410 (void) pcn_m_unicast(pcnp, pcnp->pcn_addr); 411 /* XXX: do we need to add the broadcast addr to the addr filter? */ 412 413 if ((rc = ddi_intr_add_handler(pcnp->pcn_htable, pcn_intr, 414 (caddr_t)pcnp, NULL)) != DDI_SUCCESS) { 415 pcn_error(pcnp->pcn_dip, "failed to add interrupt handler"); 416 return (DDI_FAILURE); 417 } 418 419 if (ddi_intr_enable(pcnp->pcn_htable) != DDI_SUCCESS) { 420 pcn_error(pcnp->pcn_dip, "failed to enable interrupt"); 421 goto fail; 422 } 423 424 if ((macp = mac_alloc(MAC_VERSION)) == NULL) { 425 pcn_error(pcnp->pcn_dip, "mac_alloc failed"); 426 goto fail; 427 } 428 429 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 430 macp->m_driver = pcnp; 431 macp->m_dip = dip; 432 macp->m_src_addr = pcnp->pcn_addr; 433 macp->m_callbacks = &pcn_m_callbacks; 434 macp->m_min_sdu = 0; 435 macp->m_max_sdu = ETHERMTU; 436 macp->m_margin = VLAN_TAGSZ; 437 438 if (mac_register(macp, &pcnp->pcn_mh) == DDI_SUCCESS) { 439 mac_free(macp); 440 ddi_report_dev(dip); 441 442 return (DDI_SUCCESS); 443 } 444 445 mac_free(macp); 446 447fail: 448 ddi_intr_free(pcnp->pcn_htable); 449 ddi_soft_state_free(pcn_ssp, instance); 450 451 return (DDI_FAILURE); 452} 453 454static int 455pcn_set_chipid(pcn_t *pcnp, uint32_t conf_id) 456{ 457 uint32_t chipid; 458 459 /* 460 * Note: we can *NOT* put the chip into 461 * 32-bit mode yet. The le(4) driver will only 462 * work in 16-bit mode, and once the chip 463 * goes into 32-bit mode, the only way to 464 * get it out again is with a hardware reset. 465 * So if pcn_probe() is called before the 466 * le(4) driver's probe routine, the chip will 467 * be locked into 32-bit operation and the 468 * le(4) driver will be unable to attach to it. 469 * Note II: if the chip happens to already 470 * be in 32-bit mode, we still need to check 471 * the chip ID, but first we have to detect 472 * 32-bit mode using only 16-bit operations. 473 * The safest way to do this is to read the 474 * PCI subsystem ID from BCR23/24 and compare 475 * that with the value read from PCI config 476 * space. 477 */ 478 479 chipid = pcn_bcr_read16(pcnp, PCN_BCR_PCISUBSYSID); 480 chipid <<= 16; 481 chipid |= pcn_bcr_read16(pcnp, PCN_BCR_PCISUBVENID); 482 /* 483 * Note III: the test for 0x10001000 is a hack to 484 * pacify VMware, who's pseudo-PCnet interface is 485 * broken. Reading the subsystem register from PCI 486 * config space yields 0x00000000 while reading the 487 * same value from I/O space yields 0x10001000. It's 488 * not supposed to be that way. 489 */ 490 if (chipid == conf_id || chipid == 0x10001000) { 491 /* We're in 16-bit mode. */ 492 chipid = pcn_csr_read16(pcnp, PCN_CSR_CHIPID1); 493 chipid <<= 16; 494 chipid |= pcn_csr_read16(pcnp, PCN_CSR_CHIPID0); 495 } else { 496 chipid = pcn_csr_read(pcnp, PCN_CSR_CHIPID1); 497 chipid <<= 16; 498 chipid |= pcn_csr_read(pcnp, PCN_CSR_CHIPID0); 499 } 500 501 switch ((chipid >> 12) & PART_MASK) { 502 case Am79C971: 503 case Am79C972: 504 case Am79C973: 505 case Am79C975: 506 case Am79C976: 507 case Am79C978: 508 break; 509 default: 510 pcn_error(pcnp->pcn_dip, "Unknown chip id 0x%u", 511 (chipid >> 12) & PART_MASK); 512 return (DDI_FAILURE); 513 } 514 515 if (ddi_prop_update_string(DDI_DEV_T_NONE, pcnp->pcn_dip, "chipid", 516 pcn_chipid_name(chipid)) != DDI_SUCCESS) { 517 pcn_error(pcnp->pcn_dip, "Unable to set chipid property"); 518 return (DDI_FAILURE); 519 } 520 521 return (DDI_SUCCESS); 522} 523 524static int 525pcn_setup_intr(pcn_t *pcnp) 526{ 527 int int_types, int_count, int_actual, int_avail; 528 int i, rc; 529 530 if ((rc = ddi_intr_get_supported_types(pcnp->pcn_dip, &int_types)) != 531 DDI_SUCCESS) { 532 pcn_error(pcnp->pcn_dip, "unable to get supported interrupt " 533 "types"); 534 return (DDI_FAILURE); 535 } 536 537 if ((int_types & DDI_INTR_TYPE_FIXED) == 0) { 538 pcn_error(pcnp->pcn_dip, "fixed interrupts are not supported"); 539 return (DDI_FAILURE); 540 } 541 542 if ((rc = ddi_intr_get_nintrs(pcnp->pcn_dip, DDI_INTR_TYPE_FIXED, 543 &int_count)) != DDI_SUCCESS) { 544 pcn_error(pcnp->pcn_dip, "unable to obtain the number of " 545 "interrupts"); 546 return (DDI_FAILURE); 547 } 548 549 if (int_count != 1) { 550 pcn_error(pcnp->pcn_dip, "interrupt count is %d, expected 1", 551 int_count); 552 return (DDI_FAILURE); 553 } 554 555 rc = ddi_intr_get_navail(pcnp->pcn_dip, DDI_INTR_TYPE_FIXED, &int_avail); 556 if ((rc != DDI_SUCCESS) || (int_avail == 0)) { 557 pcn_error(pcnp->pcn_dip, "ddi_intr_get_avail failed"); 558 return (DDI_FAILURE); 559 } 560 561 rc = ddi_intr_alloc(pcnp->pcn_dip, &pcnp->pcn_htable, DDI_INTR_TYPE_FIXED, 0, 562 int_count, &int_actual, DDI_INTR_ALLOC_STRICT); 563 if ((rc != DDI_SUCCESS) || (int_actual != int_count)) { 564 pcn_error(pcnp->pcn_dip, "unable to allocate fixed interrupt!"); 565 return (DDI_FAILURE); 566 } 567 568 if ((rc = ddi_intr_get_pri(pcnp->pcn_htable, &pcnp->pcn_int_pri)) != 569 DDI_SUCCESS) { 570 pcn_error(pcnp->pcn_dip, "unable to obtain interrupt priority"); 571 ddi_intr_free(pcnp->pcn_htable); 572 return (DDI_FAILURE); 573 } 574 575 return (DDI_SUCCESS); 576} 577 578int 579pcn_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 580{ 581 pcn_t *pcnp; 582 583 pcnp = ddi_get_soft_state(pcn_ssp, ddi_get_instance(dip)); 584 if (pcnp == NULL) { 585 pcn_error(dip, "no soft state in detach!"); 586 return (DDI_FAILURE); 587 } 588 589 switch (cmd) { 590 case DDI_DETACH: 591 if (mac_unregister(pcnp->pcn_mh) != 0) 592 return (DDI_FAILURE); 593 594 mutex_enter(&pcnp->pcn_intrlock); 595 mutex_enter(&pcnp->pcn_xmtlock); 596 pcnp->pcn_flags &= ~PCN_RUNNING; 597 pcn_stopall(pcnp); 598 mutex_exit(&pcnp->pcn_xmtlock); 599 mutex_exit(&pcnp->pcn_intrlock); 600 601 ddi_intr_remove_handler(pcnp->pcn_htable); 602 ddi_intr_free(pcnp->pcn_htable); 603 604 mii_free(pcnp->pcn_mii); 605 606 ddi_prop_remove_all(dip); 607 608 pcn_freerxring(pcnp); 609 pcn_freetxring(pcnp); 610 611 ddi_regs_map_free(&pcnp->pcn_regshandle); 612 mutex_destroy(&pcnp->pcn_intrlock); 613 mutex_destroy(&pcnp->pcn_xmtlock); 614 615 ddi_soft_state_free(pcn_ssp, ddi_get_instance(dip)); 616 return (DDI_SUCCESS); 617 618 case DDI_SUSPEND: 619 mii_suspend(pcnp->pcn_mii); 620 621 mutex_enter(&pcnp->pcn_intrlock); 622 mutex_enter(&pcnp->pcn_xmtlock); 623 pcnp->pcn_flags |= PCN_SUSPENDED; 624 pcn_stopall(pcnp); 625 mutex_exit(&pcnp->pcn_xmtlock); 626 mutex_exit(&pcnp->pcn_intrlock); 627 return (DDI_SUCCESS); 628 629 default: 630 return (DDI_FAILURE); 631 } 632} 633 634int 635pcn_resume(dev_info_t *dip) 636{ 637 pcn_t *pcnp; 638 639 pcnp = ddi_get_soft_state(pcn_ssp, ddi_get_instance(dip)); 640 if (pcnp == NULL) 641 return (DDI_FAILURE); 642 643 mutex_enter(&pcnp->pcn_intrlock); 644 mutex_enter(&pcnp->pcn_xmtlock); 645 646 pcnp->pcn_flags &= ~PCN_SUSPENDED; 647 648 if (!pcn_initialize(pcnp)) { 649 pcn_error(pcnp->pcn_dip, "unable to resume chip"); 650 pcnp->pcn_flags |= PCN_SUSPENDED; 651 mutex_exit(&pcnp->pcn_intrlock); 652 mutex_exit(&pcnp->pcn_xmtlock); 653 return (DDI_SUCCESS); 654 } 655 656 if (pcnp->pcn_flags & PCN_RUNNING) 657 pcn_startall(pcnp); 658 659 mutex_exit(&pcnp->pcn_xmtlock); 660 mutex_exit(&pcnp->pcn_intrlock); 661 662 mii_resume(pcnp->pcn_mii); 663 664 return (DDI_SUCCESS); 665} 666 667int 668pcn_quiesce(dev_info_t *dip) 669{ 670 pcn_t *pcnp; 671 672 pcnp = ddi_get_soft_state(pcn_ssp, ddi_get_instance(dip)); 673 if (pcnp == NULL) 674 return (DDI_FAILURE); 675 676 /* 677 * First suspend the chip, this should drain anything in 678 * in progress. 679 */ 680 PCN_CSR_SETBIT(pcnp, PCN_CSR_EXTCTL1, PCN_EXTCTL1_SPND); 681 682 /* wait a reasonable amount of time for suspend to finish */ 683 drv_usecwait(RESET_DELAY); 684 685 /* abrupt stop */ 686 PCN_CSR_SETBIT(pcnp, PCN_CSR_CSR, PCN_CSR_STOP); 687 688 return (DDI_SUCCESS); 689} 690 691static void 692pcn_setrxfilt(pcn_t *pcnp) 693{ 694 int i; 695 696 if (pcnp->pcn_flags & PCN_SUSPENDED) 697 return; 698 699 /* temporairly suspend card */ 700 PCN_CSR_SETBIT(pcnp, PCN_CSR_EXTCTL1, PCN_EXTCTL1_SPND); 701 702 /* set promiscuous mode */ 703 if (pcnp->pcn_promisc) 704 PCN_CSR_SETBIT(pcnp, PCN_CSR_MODE, PCN_MODE_PROMISC); 705 else 706 PCN_CSR_CLRBIT(pcnp, PCN_CSR_MODE, PCN_MODE_PROMISC); 707 708 /* program mac address */ 709 pcn_csr_write(pcnp, PCN_CSR_PAR0, 710 pcnp->pcn_addr[0] << 8 | pcnp->pcn_addr[1]); 711 pcn_csr_write(pcnp, PCN_CSR_PAR1, 712 pcnp->pcn_addr[2] << 8 | pcnp->pcn_addr[2]); 713 pcn_csr_write(pcnp, PCN_CSR_PAR2, 714 pcnp->pcn_addr[4] << 8 | pcnp->pcn_addr[5]); 715 716 /* 717 * program multicast filter 718 * I'm not sure if this is absolutely necessary, but it appears that 719 * the freebsd driver sets the filter to all 1's when in promiscuous 720 * mode, so we follow suit. 721 */ 722 for (i = 0; i < 4; i++) 723 pcn_csr_write(pcnp, PCN_CSR_MAR0 + i, 724 pcnp->pcn_promisc ? 0xffff : pcnp->pcn_mctab[i]); 725 726 /* reenable card */ 727 PCN_CSR_CLRBIT(pcnp, PCN_CSR_EXTCTL1, PCN_EXTCTL1_SPND); 728} 729 730static int 731pcn_m_multicast(void *arg, boolean_t add, const uint8_t *macaddr) 732{ 733 pcn_t *pcnp = (pcn_t *)arg; 734 int index; 735 uint32_t crc; 736 uint32_t bit; 737 uint32_t newval, oldval; 738 739 /* 740 * PCNet uses the upper 6 bits of the CRC of the macaddr 741 * to index into a 64bit mask 742 */ 743 CRC32(crc, macaddr, ETHERADDRL, -1U, crc32_table); 744 crc = crc >> 26; 745 index = crc / 16; 746 bit = (1 << (crc % 16)); 747 748 mutex_enter(&pcnp->pcn_intrlock); 749 mutex_enter(&pcnp->pcn_xmtlock); 750 newval = oldval = pcnp->pcn_mctab[index]; 751 752 if (add) { 753 pcnp->pcn_mccount[crc]++; 754 if (pcnp->pcn_mccount[crc] == 1) 755 newval |= bit; 756 } else { 757 pcnp->pcn_mccount[crc]--; 758 if (pcnp->pcn_mccount[crc] == 0) 759 newval &= ~bit; 760 } 761 if (newval != oldval) { 762 pcnp->pcn_mctab[index] = newval; 763 pcn_setrxfilt(pcnp); 764 } 765 766 mutex_exit(&pcnp->pcn_xmtlock); 767 mutex_exit(&pcnp->pcn_intrlock); 768 769 return (0); 770} 771 772static int 773pcn_m_promisc(void *arg, boolean_t on) 774{ 775 pcn_t *pcnp = (pcn_t *)arg; 776 777 mutex_enter(&pcnp->pcn_intrlock); 778 mutex_enter(&pcnp->pcn_xmtlock); 779 780 pcnp->pcn_promisc = on; 781 pcn_setrxfilt(pcnp); 782 783 mutex_exit(&pcnp->pcn_xmtlock); 784 mutex_exit(&pcnp->pcn_intrlock); 785 786 return (0); 787} 788 789static int 790pcn_m_unicast(void *arg, const uint8_t *macaddr) 791{ 792 pcn_t *pcnp = (pcn_t *)arg; 793 794 mutex_enter(&pcnp->pcn_intrlock); 795 mutex_enter(&pcnp->pcn_xmtlock); 796 797 bcopy(macaddr, pcnp->pcn_addr, ETHERADDRL); 798 pcn_setrxfilt(pcnp); 799 800 mutex_exit(&pcnp->pcn_xmtlock); 801 mutex_exit(&pcnp->pcn_intrlock); 802 803 return (0); 804} 805 806static mblk_t * 807pcn_m_tx(void *arg, mblk_t *mp) 808{ 809 pcn_t *pcnp = (pcn_t *)arg; 810 mblk_t *nmp; 811 812 mutex_enter(&pcnp->pcn_xmtlock); 813 814 if (pcnp->pcn_flags & PCN_SUSPENDED) { 815 while ((nmp = mp) != NULL) { 816 pcnp->pcn_carrier_errors++; 817 mp = mp->b_next; 818 freemsg(nmp); 819 } 820 mutex_exit(&pcnp->pcn_xmtlock); 821 return (NULL); 822 } 823 824 while (mp != NULL) { 825 nmp = mp->b_next; 826 mp->b_next = NULL; 827 828 if (!pcn_send(pcnp, mp)) { 829 mp->b_next = nmp; 830 break; 831 } 832 mp = nmp; 833 } 834 mutex_exit(&pcnp->pcn_xmtlock); 835 836 return (mp); 837} 838 839static boolean_t 840pcn_send(pcn_t *pcnp, mblk_t *mp) 841{ 842 size_t len; 843 pcn_buf_t *txb; 844 pcn_tx_desc_t *tmd; 845 int txsend; 846 847 ASSERT(mutex_owned(&pcnp->pcn_xmtlock)); 848 ASSERT(mp != NULL); 849 850 len = msgsize(mp); 851 if (len > ETHERVLANMTU) { 852 pcnp->pcn_macxmt_errors++; 853 freemsg(mp); 854 return (B_TRUE); 855 } 856 857 if (pcnp->pcn_txavail < PCN_TXRECLAIM) 858 pcn_reclaim(pcnp); 859 860 if (pcnp->pcn_txavail == 0) { 861 pcnp->pcn_wantw = B_TRUE; 862 pcn_enableinterrupts(pcnp); 863 return (B_FALSE); 864 } 865 866 txsend = pcnp->pcn_txsend; 867 868 txb = pcnp->pcn_txbufs[txsend]; 869 mcopymsg(mp, txb->pb_buf); /* frees mp! */ 870 871 pcnp->pcn_opackets++; 872 pcnp->pcn_obytes += len; 873 if (txb->pb_buf[0] & 0x1) { 874 if (bcmp(txb->pb_buf, pcn_broadcast, ETHERADDRL) != 0) 875 pcnp->pcn_multixmt++; 876 else 877 pcnp->pcn_brdcstxmt++; 878 } 879 880 SYNCBUF(txb, len, DDI_DMA_SYNC_FORDEV); 881 882 tmd = &pcnp->pcn_txdescp[txsend]; 883 tmd->pcn_tbaddr = txb->pb_paddr; 884 tmd->pcn_txctl = PCN_TXCTL_STP|PCN_TXCTL_ENP|PCN_TXCTL_ADD_FCS| 885 PCN_TXCTL_MORE_LTINT|0xf000; 886 /* PCNet wants the 2's complement of the length of the buffer */ 887 tmd->pcn_txctl |= (~(len) + 1) & PCN_TXCTL_BUFSZ; 888 889 /* Spec suggests this should be set last */ 890 tmd->pcn_txctl |= PCN_TXCTL_OWN; 891 SYNCTXDESC(pcnp, txsend, DDI_DMA_SYNC_FORDEV); 892 893 pcnp->pcn_txavail--; 894 pcnp->pcn_txsend = (txsend + 1) % PCN_TXRING; 895 896 pcnp->pcn_txstall_time = gethrtime() + (5 * 1000000000ULL); 897 898 pcn_csr_write(pcnp, PCN_CSR_CSR, PCN_CSR_TX|PCN_CSR_INTEN); 899 900 return (B_TRUE); 901} 902 903static void 904pcn_reclaim(pcn_t *pcnp) 905{ 906 pcn_tx_desc_t *tmdp; 907 908 while (pcnp->pcn_txavail != PCN_TXRING) { 909 int index = pcnp->pcn_txreclaim; 910 911 tmdp = &pcnp->pcn_txdescp[index]; 912 913 /* sync before reading */ 914 SYNCTXDESC(pcnp, index, DDI_DMA_SYNC_FORKERNEL); 915 916 /* check if chip is still working on it */ 917 if (tmdp->pcn_txctl & PCN_TXCTL_OWN) 918 break; 919 920 pcnp->pcn_txavail++; 921 pcnp->pcn_txreclaim = (index + 1) % PCN_TXRING; 922 } 923 924 if (pcnp->pcn_txavail >= PCN_TXRESCHED) 925 if (pcnp->pcn_wantw) { 926 pcnp->pcn_wantw = B_FALSE; 927 pcn_enableinterrupts(pcnp); 928 mac_tx_update(pcnp->pcn_mh); 929 } 930} 931 932static unsigned 933pcn_intr(caddr_t arg1, caddr_t arg2) 934{ 935 pcn_t *pcnp = (pcn_t *)arg1; 936 mblk_t *mp = NULL; 937 uint32_t status; 938 boolean_t do_reset = B_FALSE; 939 940 mutex_enter(&pcnp->pcn_intrlock); 941 942 if (pcnp->pcn_flags & PCN_SUSPENDED) { 943 mutex_exit(&pcnp->pcn_intrlock); 944 return (DDI_INTR_UNCLAIMED); 945 } 946 947 CSR_WRITE_4(pcnp, PCN_IO32_RAP, PCN_CSR_CSR); 948 949 while ((status = CSR_READ_4(pcnp, PCN_IO32_RDP)) & PCN_CSR_INTR) { 950 CSR_WRITE_4(pcnp, PCN_IO32_RDP, status); 951 952 if (status & PCN_CSR_TINT) { 953 mutex_enter(&pcnp->pcn_xmtlock); 954 pcn_reclaim(pcnp); 955 mutex_exit(&pcnp->pcn_xmtlock); 956 } 957 958 if (status & PCN_CSR_RINT) 959 mp = pcn_receive(pcnp); 960 961 if (status & PCN_CSR_ERR) { 962 do_reset = B_TRUE; 963 break; 964 } 965 } 966 967 if (do_reset) { 968 mutex_enter(&pcnp->pcn_xmtlock); 969 pcn_resetall(pcnp); 970 mutex_exit(&pcnp->pcn_xmtlock); 971 mutex_exit(&pcnp->pcn_intrlock); 972 973 mii_reset(pcnp->pcn_mii); 974 } else { 975 mutex_exit(&pcnp->pcn_intrlock); 976 } 977 978 if (mp) 979 mac_rx(pcnp->pcn_mh, NULL, mp); 980 981 return (DDI_INTR_CLAIMED); 982} 983 984static mblk_t * 985pcn_receive(pcn_t *pcnp) 986{ 987 uint32_t len; 988 pcn_buf_t *rxb; 989 pcn_rx_desc_t *rmd; 990 mblk_t *mpchain, **mpp, *mp; 991 int head, cnt; 992 993 mpchain = NULL; 994 mpp = &mpchain; 995 head = pcnp->pcn_rxhead; 996 997 for (cnt = 0; cnt < PCN_RXRING; cnt++) { 998 rmd = &pcnp->pcn_rxdescp[head]; 999 rxb = pcnp->pcn_rxbufs[head]; 1000 1001 SYNCRXDESC(pcnp, head, DDI_DMA_SYNC_FORKERNEL); 1002 if (rmd->pcn_rxstat & PCN_RXSTAT_OWN) 1003 break; 1004 1005 len = rmd->pcn_rxlen - ETHERFCSL; 1006 if (rmd->pcn_rxstat & PCN_RXSTAT_ERR) { 1007 pcnp->pcn_errrcv++; 1008 1009 if (rmd->pcn_rxstat & PCN_RXSTAT_FRAM) 1010 pcnp->pcn_align_errors++; 1011 if (rmd->pcn_rxstat & PCN_RXSTAT_OFLOW) 1012 pcnp->pcn_overflow++; 1013 if (rmd->pcn_rxstat & PCN_RXSTAT_CRC) 1014 pcnp->pcn_fcs_errors++; 1015 } else if (len > ETHERVLANMTU) { 1016 pcnp->pcn_errrcv++; 1017 pcnp->pcn_toolong_errors++; 1018 } else { 1019 mp = allocb(len + PCN_HEADROOM, 0); 1020 if (mp == NULL) { 1021 pcnp->pcn_errrcv++; 1022 pcnp->pcn_norcvbuf++; 1023 goto skip; 1024 } 1025 1026 SYNCBUF(rxb, len, DDI_DMA_SYNC_FORKERNEL); 1027 mp->b_rptr += PCN_HEADROOM; 1028 mp->b_wptr = mp->b_rptr + len; 1029 bcopy((char *)rxb->pb_buf, mp->b_rptr, len); 1030 1031 pcnp->pcn_ipackets++; 1032 pcnp->pcn_rbytes++; 1033 1034 if (rmd->pcn_rxstat & PCN_RXSTAT_LAFM|PCN_RXSTAT_BAM) { 1035 if (rmd->pcn_rxstat & PCN_RXSTAT_BAM) 1036 pcnp->pcn_brdcstrcv++; 1037 else 1038 pcnp->pcn_multircv++; 1039 } 1040 *mpp = mp; 1041 mpp = &mp->b_next; 1042 } 1043 1044skip: 1045 rmd->pcn_rxstat &= ~(PCN_RXSTAT_OWN); 1046 SYNCRXDESC(pcnp, head, DDI_DMA_SYNC_FORDEV); 1047 1048 head = (head + 1) % PCN_RXRING; 1049 } 1050 1051 pcnp->pcn_rxhead = head; 1052 1053 return (mpchain); 1054} 1055 1056static void 1057pcn_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 1058{ 1059 pcn_t *pcnp = (pcn_t *)arg; 1060 1061 if (mii_m_loop_ioctl(pcnp->pcn_mii, wq, mp)) 1062 return; 1063 1064 miocnak(wq, mp, 0, EINVAL); 1065} 1066 1067static int 1068pcn_m_start(void *arg) 1069{ 1070 pcn_t *pcnp = (pcn_t *)arg; 1071 1072 mutex_enter(&pcnp->pcn_intrlock); 1073 mutex_enter(&pcnp->pcn_xmtlock); 1074 1075 pcn_startall(pcnp); 1076 pcnp->pcn_flags |= PCN_RUNNING; 1077 1078 mutex_exit(&pcnp->pcn_xmtlock); 1079 mutex_exit(&pcnp->pcn_intrlock); 1080 1081 mii_start(pcnp->pcn_mii); 1082 1083 return (0); 1084} 1085 1086static void 1087pcn_m_stop(void *arg) 1088{ 1089 pcn_t *pcnp = (pcn_t *)arg; 1090 1091 mii_stop(pcnp->pcn_mii); 1092 1093 mutex_enter(&pcnp->pcn_intrlock); 1094 mutex_enter(&pcnp->pcn_xmtlock); 1095 1096 pcn_stopall(pcnp); 1097 pcnp->pcn_flags &= ~PCN_RUNNING; 1098 1099 mutex_exit(&pcnp->pcn_xmtlock); 1100 mutex_exit(&pcnp->pcn_intrlock); 1101} 1102 1103static int 1104pcn_initialize(pcn_t *pcnp) 1105{ 1106 uint32_t par; 1107 1108 /* 1109 * Issue a reset by reading from the RESET register. 1110 * Note that we don't know if the chip is operating in 1111 * 16-bit or 32-bit mode at this point, so we attempt 1112 * to reset the chip both ways. If one fails, the other 1113 * will succeed. 1114 */ 1115 CSR_READ_2(pcnp, PCN_IO16_RESET); 1116 CSR_READ_4(pcnp, PCN_IO32_RESET); 1117 1118 drv_usecwait(1000); 1119 1120 /* Select 32-bit (DWIO) mode */ 1121 CSR_WRITE_4(pcnp, PCN_IO32_RDP, 0); 1122 1123 /* Select software style 3. */ 1124 pcn_bcr_write(pcnp, PCN_BCR_SSTYLE, PCN_SWSTYLE_PCNETPCI_BURST); 1125 1126 par = 0; 1127 1128 pcn_resetrings(pcnp); 1129 1130 pcn_setrxfilt(pcnp); 1131 1132 /* Enable fast suspend mode. */ 1133 PCN_CSR_SETBIT(pcnp, PCN_CSR_EXTCTL2, PCN_EXTCTL2_FASTSPNDE); 1134 1135 return (DDI_SUCCESS); 1136} 1137 1138static void 1139pcn_resetall(pcn_t *pcnp) 1140{ 1141 pcn_stopall(pcnp); 1142 pcn_startall(pcnp); 1143} 1144 1145static void 1146pcn_startmac(pcn_t *pcnp) 1147{ 1148 ASSERT(mutex_owned(&pcnp->pcn_intrlock)); 1149 ASSERT(mutex_owned(&pcnp->pcn_xmtlock)); 1150 1151 PCN_CSR_SETBIT(pcnp, PCN_CSR_CSR, PCN_CSR_START); 1152 1153 if (pcnp->pcn_flags & PCN_RUNNING) 1154 mac_tx_update(pcnp->pcn_mh); 1155} 1156 1157static void 1158pcn_stopmac(pcn_t *pcnp) 1159{ 1160 ASSERT(mutex_owned(&pcnp->pcn_intrlock)); 1161 ASSERT(mutex_owned(&pcnp->pcn_xmtlock)); 1162 1163 PCN_CSR_SETBIT(pcnp, PCN_CSR_CSR, PCN_CSR_STOP); 1164} 1165 1166static void 1167pcn_startall(pcn_t *pcnp) 1168{ 1169 ASSERT(mutex_owned(&pcnp->pcn_intrlock)); 1170 ASSERT(mutex_owned(&pcnp->pcn_xmtlock)); 1171 1172 pcn_disableinterrupts(pcnp); 1173 (void) pcn_initialize(pcnp); 1174 1175 pcn_enableinterrupts(pcnp); 1176 pcn_startmac(pcnp); 1177} 1178 1179static void 1180pcn_stopall(pcn_t *pcnp) 1181{ 1182 pcn_disableinterrupts(pcnp); 1183 pcn_stopmac(pcnp); 1184} 1185 1186static int 1187pcn_m_stat(void *arg, uint_t stat, uint64_t *val) 1188{ 1189 pcn_t *pcnp = (pcn_t *)arg; 1190 1191 if (mii_m_getstat(pcnp->pcn_mii, stat, val) == 0) 1192 return (0); 1193 1194 switch (stat) { 1195 case MAC_STAT_MULTIRCV: 1196 *val = pcnp->pcn_multircv; 1197 break; 1198 1199 case MAC_STAT_BRDCSTRCV: 1200 *val = pcnp->pcn_brdcstrcv; 1201 break; 1202 1203 case MAC_STAT_MULTIXMT: 1204 *val = pcnp->pcn_multixmt; 1205 break; 1206 1207 case MAC_STAT_BRDCSTXMT: 1208 *val = pcnp->pcn_brdcstxmt; 1209 break; 1210 1211 case MAC_STAT_IPACKETS: 1212 *val = pcnp->pcn_ipackets; 1213 break; 1214 1215 case MAC_STAT_RBYTES: 1216 *val = pcnp->pcn_rbytes; 1217 break; 1218 1219 case MAC_STAT_OPACKETS: 1220 *val = pcnp->pcn_opackets; 1221 break; 1222 1223 case MAC_STAT_OBYTES: 1224 *val = pcnp->pcn_obytes; 1225 break; 1226 1227 case MAC_STAT_NORCVBUF: 1228 *val = pcnp->pcn_norcvbuf; 1229 break; 1230 1231 case MAC_STAT_NOXMTBUF: 1232 *val = 0; 1233 break; 1234 1235 case MAC_STAT_COLLISIONS: 1236 *val = pcnp->pcn_collisions; 1237 break; 1238 1239 case MAC_STAT_IERRORS: 1240 *val = pcnp->pcn_errrcv; 1241 break; 1242 1243 case MAC_STAT_OERRORS: 1244 *val = pcnp->pcn_errxmt; 1245 break; 1246 1247 case ETHER_STAT_ALIGN_ERRORS: 1248 *val = pcnp->pcn_align_errors; 1249 break; 1250 1251 case ETHER_STAT_FCS_ERRORS: 1252 *val = pcnp->pcn_fcs_errors; 1253 break; 1254 1255 case ETHER_STAT_SQE_ERRORS: 1256 *val = pcnp->pcn_sqe_errors; 1257 break; 1258 1259 case ETHER_STAT_DEFER_XMTS: 1260 *val = pcnp->pcn_defer_xmts; 1261 break; 1262 1263 case ETHER_STAT_FIRST_COLLISIONS: 1264 *val = pcnp->pcn_first_collisions; 1265 break; 1266 1267 case ETHER_STAT_MULTI_COLLISIONS: 1268 *val = pcnp->pcn_multi_collisions; 1269 break; 1270 1271 case ETHER_STAT_TX_LATE_COLLISIONS: 1272 *val = pcnp->pcn_tx_late_collisions; 1273 break; 1274 1275 case ETHER_STAT_EX_COLLISIONS: 1276 *val = pcnp->pcn_ex_collisions; 1277 break; 1278 1279 case ETHER_STAT_MACXMT_ERRORS: 1280 *val = pcnp->pcn_macxmt_errors; 1281 break; 1282 1283 case ETHER_STAT_CARRIER_ERRORS: 1284 *val = pcnp->pcn_carrier_errors; 1285 break; 1286 1287 case ETHER_STAT_TOOLONG_ERRORS: 1288 *val = pcnp->pcn_toolong_errors; 1289 break; 1290 1291 case ETHER_STAT_MACRCV_ERRORS: 1292 *val = pcnp->pcn_macrcv_errors; 1293 break; 1294 1295 case MAC_STAT_OVERFLOWS: 1296 *val = pcnp->pcn_overflow; 1297 break; 1298 1299 case MAC_STAT_UNDERFLOWS: 1300 *val = pcnp->pcn_underflow; 1301 break; 1302 1303 case ETHER_STAT_TOOSHORT_ERRORS: 1304 *val = pcnp->pcn_runt; 1305 break; 1306 1307 case ETHER_STAT_JABBER_ERRORS: 1308 *val = pcnp->pcn_jabber; 1309 break; 1310 1311 default: 1312 return (ENOTSUP); 1313 } 1314 return (0); 1315} 1316 1317static int 1318pcn_m_getprop(void *arg, const char *name, mac_prop_id_t num, uint_t flags, 1319 uint_t sz, void *val, uint_t *perm) 1320{ 1321 pcn_t *pcnp = (pcn_t *)arg; 1322 1323 return (mii_m_getprop(pcnp->pcn_mii, name, num, flags, sz, val, perm)); 1324} 1325 1326static int 1327pcn_m_setprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz, 1328 const void *val) 1329{ 1330 pcn_t *pcnp = (pcn_t *)arg; 1331 1332 return (mii_m_setprop(pcnp->pcn_mii, name, num, sz, val)); 1333} 1334 1335static uint16_t 1336pcn_mii_read(void *arg, uint8_t phy, uint8_t reg) 1337{ 1338 pcn_t *pcnp = (pcn_t *)arg; 1339 uint16_t val; 1340 1341 /* 1342 * At least Am79C971 with DP83840A wedge when isolating the 1343 * external PHY so we can't allow multiple external PHYs. 1344 * There are cards that use Am79C971 with both the internal 1345 * and an external PHY though. 1346 * For internal PHYs it doesn't really matter whether we can 1347 * isolate the remaining internal and the external ones in 1348 * the PHY drivers as the internal PHYs have to be enabled 1349 * individually in PCN_BCR_PHYSEL, PCN_CSR_MODE, etc. 1350 * With Am79C97{3,5,8} we don't support switching beetween 1351 * the internal and external PHYs, yet, so we can't allow 1352 * multiple PHYs with these either. 1353 * Am79C97{2,6} actually only support external PHYs (not 1354 * connectable internal ones respond at the usual addresses, 1355 * which don't hurt if we let them show up on the bus) and 1356 * isolating them works. 1357 */ 1358 if (((pcnp->pcn_type == Am79C971 && phy != PCN_PHYAD_10BT) || 1359 pcnp->pcn_type == Am79C973 || pcnp->pcn_type == Am79C975 || 1360 pcnp->pcn_type == Am79C978) && pcnp->pcn_extphyaddr != 0xff && 1361 phy != pcnp->pcn_extphyaddr) 1362 return (0xffff); 1363 1364 pcn_bcr_write(pcnp, PCN_BCR_MIIADDR, reg | (phy << 5)); 1365 val = pcn_bcr_read(pcnp, PCN_BCR_MIIDATA) & 0xFFFF; 1366 if (val == 0xFFFF) 1367 return (val); 1368 1369 if (((pcnp->pcn_type == Am79C971 && phy != PCN_PHYAD_10BT) || 1370 pcnp->pcn_type == Am79C973 || pcnp->pcn_type == Am79C975 || 1371 pcnp->pcn_type == Am79C978) && pcnp->pcn_extphyaddr == 0xff) 1372 pcnp->pcn_extphyaddr = phy; 1373 1374 return (val); 1375} 1376 1377static void 1378pcn_mii_write(void *arg, uint8_t phy, uint8_t reg, uint16_t val) 1379{ 1380 pcn_t *pcnp = (pcn_t *)arg; 1381 1382 pcn_bcr_write(pcnp, PCN_BCR_MIIADDR, reg | (phy << 5)); 1383 pcn_bcr_write(pcnp, PCN_BCR_MIIDATA, val); 1384} 1385 1386static void 1387pcn_mii_notify(void *arg, link_state_t link) 1388{ 1389 pcn_t *pcnp = (pcn_t *)arg; 1390 1391 mac_link_update(pcnp->pcn_mh, link); 1392} 1393 1394static const pcn_type_t * 1395pcn_match(uint16_t vid, uint16_t did) 1396{ 1397 const pcn_type_t *t; 1398 1399 t = pcn_devs; 1400 while (t->pcn_name != NULL) { 1401 if ((vid == t->pcn_vid) && (did == t->pcn_did)) 1402 return (t); 1403 t++; 1404 } 1405 return (NULL); 1406} 1407 1408static char * 1409pcn_chipid_name(uint32_t id) 1410{ 1411 const struct pcn_chipid *p; 1412 1413 p = pcn_chipid; 1414 while (p->name) { 1415 if (id == p->id) 1416 return (p->name); 1417 p++; 1418 } 1419 return ("Unknown"); 1420} 1421 1422static void 1423pcn_getfactaddr(pcn_t *pcnp) 1424{ 1425 uint32_t addr[2]; 1426 1427 addr[0] = CSR_READ_4(pcnp, PCN_IO32_APROM00); 1428 addr[1] = CSR_READ_4(pcnp, PCN_IO32_APROM01); 1429 1430 pcnp->pcn_addr[5] = addr[1] >> 8 & 0x000000ffL; 1431 pcnp->pcn_addr[4] = addr[1] & 0x000000ffL; 1432 pcnp->pcn_addr[3] = addr[0] >> 24; 1433 pcnp->pcn_addr[2] = addr[0] >> 16 & 0x000000ffL; 1434 pcnp->pcn_addr[1] = addr[0] >> 8 & 0x000000ffL; 1435 pcnp->pcn_addr[0] = addr[0] & 0x000000ffL; 1436} 1437 1438static void 1439pcn_enableinterrupts(pcn_t *pcnp) 1440{ 1441 pcn_csr_write(pcnp, PCN_CSR_CSR, PCN_CSR_INTEN); 1442} 1443 1444static void 1445pcn_disableinterrupts(pcn_t *pcnp) 1446{ 1447 PCN_CSR_CLRBIT(pcnp, PCN_CSR_CSR, PCN_CSR_INTEN); 1448} 1449 1450static uint32_t 1451pcn_csr_read(pcn_t *pcnp, uint32_t reg) 1452{ 1453 CSR_WRITE_4(pcnp, PCN_IO32_RAP, reg); 1454 return (CSR_READ_4(pcnp, PCN_IO32_RDP)); 1455} 1456 1457static uint16_t 1458pcn_csr_read16(pcn_t *pcnp, uint32_t reg) 1459{ 1460 CSR_WRITE_2(pcnp, PCN_IO16_RAP, reg); 1461 return (CSR_READ_2(pcnp, PCN_IO16_RDP)); 1462} 1463 1464static void 1465pcn_csr_write(pcn_t *pcnp, uint32_t reg, uint32_t val) 1466{ 1467 CSR_WRITE_4(pcnp, PCN_IO32_RAP, reg); 1468 CSR_WRITE_4(pcnp, PCN_IO32_RDP, val); 1469} 1470 1471static uint32_t 1472pcn_bcr_read(pcn_t *pcnp, uint32_t reg) 1473{ 1474 CSR_WRITE_4(pcnp, PCN_IO32_RAP, reg); 1475 return (CSR_READ_4(pcnp, PCN_IO32_BDP)); 1476} 1477 1478static uint16_t 1479pcn_bcr_read16(pcn_t *pcnp, uint32_t reg) 1480{ 1481 CSR_WRITE_2(pcnp, PCN_IO16_RAP, reg); 1482 return (CSR_READ_2(pcnp, PCN_IO16_BDP)); 1483} 1484 1485static void 1486pcn_bcr_write(pcn_t *pcnp, uint32_t reg, uint32_t val) 1487{ 1488 CSR_WRITE_4(pcnp, PCN_IO32_RAP, reg); 1489 CSR_WRITE_4(pcnp, PCN_IO32_BDP, val); 1490} 1491 1492static void 1493pcn_resetrings(pcn_t *pcnp) 1494{ 1495 int i; 1496 1497 pcnp->pcn_rxhead = 0; 1498 pcnp->pcn_txreclaim = 0; 1499 pcnp->pcn_txsend = 0; 1500 pcnp->pcn_txavail = PCN_TXRING; 1501 1502 /* set addresses of decriptors */ 1503 pcn_csr_write(pcnp, PCN_CSR_RXADDR0, pcnp->pcn_rxdesc_paddr & 0xFFFF); 1504 pcn_csr_write(pcnp, PCN_CSR_RXADDR1, 1505 (pcnp->pcn_rxdesc_paddr >> 16) & 0xFFFF); 1506 1507 pcn_csr_write(pcnp, PCN_CSR_TXADDR0, pcnp->pcn_txdesc_paddr & 0xFFFF); 1508 pcn_csr_write(pcnp, PCN_CSR_TXADDR1, 1509 (pcnp->pcn_txdesc_paddr >> 16) & 0xFFFF); 1510 1511 /* set the ring sizes */ 1512 pcn_csr_write(pcnp, PCN_CSR_RXRINGLEN, (~PCN_RXRING) + 1); 1513 pcn_csr_write(pcnp, PCN_CSR_TXRINGLEN, (~PCN_TXRING) + 1); 1514 1515 /* don't use the initializtation block */ 1516 pcn_csr_write(pcnp, PCN_CSR_IAB1, 0); 1517 1518 /* reset rx descriptor values */ 1519 for (i = 0; i < PCN_RXRING; i++) { 1520 pcn_rx_desc_t *rmd = &pcnp->pcn_rxdescp[i]; 1521 pcn_buf_t *rxb = pcnp->pcn_rxbufs[i]; 1522 1523 rmd->pcn_rbaddr = rxb->pb_paddr; 1524 rmd->pcn_bufsz = (~(PCN_BUFSZ) + 1) & PCN_RXLEN_BUFSZ; 1525 rmd->pcn_bufsz |= PCN_RXLEN_MBO; 1526 rmd->pcn_rxstat = PCN_RXSTAT_STP|PCN_RXSTAT_ENP|PCN_RXSTAT_OWN; 1527 } 1528 1529 /* tx descriptors get set on each tx, so no need to do it again */ 1530} 1531 1532static void 1533pcn_destroybuf(pcn_buf_t *buf) 1534{ 1535 if (buf == NULL) 1536 return; 1537 1538 if (buf->pb_paddr) 1539 (void) ddi_dma_unbind_handle(buf->pb_dmah); 1540 if (buf->pb_acch) 1541 ddi_dma_mem_free(&buf->pb_acch); 1542 if (buf->pb_dmah) 1543 ddi_dma_free_handle(&buf->pb_dmah); 1544 kmem_free(buf, sizeof (*buf)); 1545} 1546 1547static pcn_buf_t * 1548pcn_allocbuf(pcn_t *pcnp) 1549{ 1550 pcn_buf_t *buf; 1551 size_t len; 1552 unsigned ccnt; 1553 ddi_dma_cookie_t dmac; 1554 1555 buf = kmem_zalloc(sizeof (*buf), KM_SLEEP); 1556 1557 if (ddi_dma_alloc_handle(pcnp->pcn_dip, &pcn_dma_attr, DDI_DMA_SLEEP, 1558 NULL, &buf->pb_dmah) != DDI_SUCCESS) { 1559 kmem_free(buf, sizeof (*buf)); 1560 return (NULL); 1561 } 1562 1563 if (ddi_dma_mem_alloc(buf->pb_dmah, PCN_BUFSZ, &pcn_bufattr, 1564 DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &buf->pb_buf, &len, 1565 &buf->pb_acch) != DDI_SUCCESS) { 1566 pcn_destroybuf(buf); 1567 return (NULL); 1568 } 1569 1570 if (ddi_dma_addr_bind_handle(buf->pb_dmah, NULL, buf->pb_buf, len, 1571 DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &dmac, 1572 &ccnt) != DDI_DMA_MAPPED) { 1573 pcn_destroybuf(buf); 1574 return (NULL); 1575 } 1576 buf->pb_paddr = dmac.dmac_address; 1577 1578 return (buf); 1579} 1580 1581static int 1582pcn_alloctxring(pcn_t *pcnp) 1583{ 1584 int rval; 1585 int i; 1586 size_t size; 1587 size_t len; 1588 ddi_dma_cookie_t dmac; 1589 unsigned ncookies; 1590 caddr_t kaddr; 1591 1592 size = PCN_TXRING * sizeof (pcn_tx_desc_t); 1593 1594 rval = ddi_dma_alloc_handle(pcnp->pcn_dip, &pcn_dma_attr, DDI_DMA_SLEEP, 1595 NULL, &pcnp->pcn_txdesc_dmah); 1596 if (rval != DDI_SUCCESS) { 1597 pcn_error(pcnp->pcn_dip, "unable to allocate DMA handle for tx " 1598 "descriptors"); 1599 return (DDI_FAILURE); 1600 } 1601 1602 rval = ddi_dma_mem_alloc(pcnp->pcn_txdesc_dmah, size, &pcn_devattr, 1603 DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &kaddr, &len, 1604 &pcnp->pcn_txdesc_acch); 1605 if (rval != DDI_SUCCESS) { 1606 pcn_error(pcnp->pcn_dip, "unable to allocate DMA memory for tx " 1607 "descriptors"); 1608 return (DDI_FAILURE); 1609 } 1610 1611 rval = ddi_dma_addr_bind_handle(pcnp->pcn_txdesc_dmah, NULL, kaddr, 1612 size, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &dmac, 1613 &ncookies); 1614 if (rval != DDI_DMA_MAPPED) { 1615 pcn_error(pcnp->pcn_dip, "unable to bind DMA for tx " 1616 "descriptors"); 1617 return (DDI_FAILURE); 1618 } 1619 1620 ASSERT(ncookies == 1); 1621 1622 pcnp->pcn_txdesc_paddr = dmac.dmac_address; 1623 pcnp->pcn_txdescp = (void *)kaddr; 1624 1625 pcnp->pcn_txbufs = kmem_zalloc(PCN_TXRING * sizeof (pcn_buf_t *), 1626 KM_SLEEP); 1627 1628 for (i = 0; i < PCN_TXRING; i++) { 1629 pcn_buf_t *txb = pcn_allocbuf(pcnp); 1630 if (txb == NULL) 1631 return (DDI_FAILURE); 1632 pcnp->pcn_txbufs[i] = txb; 1633 } 1634 1635 return (DDI_SUCCESS); 1636} 1637 1638static int 1639pcn_allocrxring(pcn_t *pcnp) 1640{ 1641 int rval; 1642 int i; 1643 size_t len; 1644 size_t size; 1645 ddi_dma_cookie_t dmac; 1646 unsigned ncookies; 1647 caddr_t kaddr; 1648 1649 size = PCN_RXRING * sizeof (pcn_rx_desc_t); 1650 1651 rval = ddi_dma_alloc_handle(pcnp->pcn_dip, &pcn_dmadesc_attr, 1652 DDI_DMA_SLEEP, NULL, &pcnp->pcn_rxdesc_dmah); 1653 if (rval != DDI_SUCCESS) { 1654 pcn_error(pcnp->pcn_dip, "unable to allocate DMA handle for rx " 1655 "descriptors"); 1656 return (DDI_FAILURE); 1657 } 1658 1659 rval = ddi_dma_mem_alloc(pcnp->pcn_rxdesc_dmah, size, &pcn_devattr, 1660 DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &kaddr, &len, 1661 &pcnp->pcn_rxdesc_acch); 1662 if (rval != DDI_SUCCESS) { 1663 pcn_error(pcnp->pcn_dip, "unable to allocate DMA memory for rx " 1664 "descriptors"); 1665 return (DDI_FAILURE); 1666 } 1667 1668 rval = ddi_dma_addr_bind_handle(pcnp->pcn_rxdesc_dmah, NULL, kaddr, 1669 size, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &dmac, 1670 &ncookies); 1671 if (rval != DDI_DMA_MAPPED) { 1672 pcn_error(pcnp->pcn_dip, "unable to bind DMA for rx " 1673 "descriptors"); 1674 return (DDI_FAILURE); 1675 } 1676 1677 ASSERT(ncookies == 1); 1678 1679 pcnp->pcn_rxdesc_paddr = dmac.dmac_address; 1680 pcnp->pcn_rxdescp = (void *)kaddr; 1681 1682 pcnp->pcn_rxbufs = kmem_zalloc(PCN_RXRING * sizeof (pcn_buf_t *), 1683 KM_SLEEP); 1684 1685 for (i = 0; i < PCN_RXRING; i++) { 1686 pcn_buf_t *rxb = pcn_allocbuf(pcnp); 1687 if (rxb == NULL) 1688 return (DDI_FAILURE); 1689 pcnp->pcn_rxbufs[i] = rxb; 1690 } 1691 1692 return (DDI_SUCCESS); 1693} 1694 1695static void 1696pcn_freetxring(pcn_t *pcnp) 1697{ 1698 int i; 1699 1700 for (i = 0; i < PCN_TXRING; i++) 1701 pcn_destroybuf(pcnp->pcn_txbufs[i]); 1702 1703 if (pcnp->pcn_txbufs) 1704 kmem_free(pcnp->pcn_txbufs, PCN_TXRING * sizeof (pcn_buf_t *)); 1705 1706 if (pcnp->pcn_txdesc_paddr) 1707 (void) ddi_dma_unbind_handle(pcnp->pcn_txdesc_dmah); 1708 if (pcnp->pcn_txdesc_acch) 1709 ddi_dma_mem_free(&pcnp->pcn_txdesc_acch); 1710 if (pcnp->pcn_txdesc_dmah) 1711 ddi_dma_free_handle(&pcnp->pcn_txdesc_dmah); 1712} 1713 1714static void 1715pcn_freerxring(pcn_t *pcnp) 1716{ 1717 int i; 1718 1719 for (i = 0; i < PCN_RXRING; i++) 1720 pcn_destroybuf(pcnp->pcn_rxbufs[i]); 1721 1722 if (pcnp->pcn_rxbufs) 1723 kmem_free(pcnp->pcn_rxbufs, PCN_RXRING * sizeof (pcn_buf_t *)); 1724 1725 if (pcnp->pcn_rxdesc_paddr) 1726 (void) ddi_dma_unbind_handle(pcnp->pcn_rxdesc_dmah); 1727 if (pcnp->pcn_rxdesc_acch) 1728 ddi_dma_mem_free(&pcnp->pcn_rxdesc_acch); 1729 if (pcnp->pcn_rxdesc_dmah) 1730 ddi_dma_free_handle(&pcnp->pcn_rxdesc_dmah); 1731} 1732 1733static void 1734pcn_error(dev_info_t *dip, char *fmt, ...) 1735{ 1736 va_list ap; 1737 char buf[256]; 1738 1739 va_start(ap, fmt); 1740 (void) vsnprintf(buf, sizeof (buf), fmt, ap); 1741 va_end(ap); 1742 1743 if (dip) 1744 cmn_err(CE_WARN, "%s%d: %s", ddi_driver_name(dip), 1745 ddi_get_instance(dip), buf); 1746 else 1747 cmn_err(CE_WARN, "pcn: %s", buf); 1748}