1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Domain specific portion of the Starcat Management Network Driver 31 */ 32 33 #include <sys/types.h> 34 #include <sys/proc.h> 35 #include <sys/kmem.h> 36 #include <sys/stat.h> 37 #include <sys/kstat.h> 38 #include <sys/ksynch.h> 39 #include <sys/stream.h> 40 #include <sys/dlpi.h> 41 #include <sys/stropts.h> 42 #include <sys/strsubr.h> 43 #include <sys/debug.h> 44 #include <sys/conf.h> 45 #include <sys/kstr.h> 46 #include <sys/errno.h> 47 #include <sys/ethernet.h> 48 #include <sys/byteorder.h> 49 #include <sys/ddi.h> 50 #include <sys/sunddi.h> 51 #include <sys/modctl.h> 52 #include <sys/strsun.h> 53 #include <sys/pci.h> 54 #include <sys/callb.h> 55 #include <sys/pci.h> 56 #include <sys/iosramio.h> 57 #include <sys/mboxsc.h> 58 #include <netinet/in.h> 59 #include <inet/common.h> 60 #include <inet/mi.h> 61 #include <inet/nd.h> 62 #include <sys/socket.h> 63 #include <netinet/igmp_var.h> 64 #include <netinet/ip6.h> 65 #include <netinet/icmp6.h> 66 #include <inet/ip.h> 67 #include <inet/ip6.h> 68 #include <sys/dman.h> 69 #include <sys/ddi_impldefs.h> 70 #include <sys/sunndi.h> 71 72 #define MAN_SCHIZO_BINDING_NAME "pci108e,8001" 73 #define MAN_XMITS_BINDING_NAME "pci108e,8002" 74 75 int man_is_on_domain = TRUE; 76 77 /* 78 * Domain side function prototypes. 79 */ 80 int man_get_iosram(manc_t *); 81 int man_domain_configure(void); 82 int man_domain_deconfigure(void); 83 int man_path_discovery(void); 84 int man_dossc_switch(uint32_t); 85 int man_dr_attach(dev_info_t *); 86 int man_dr_detach(dev_info_t *); 87 static int man_dr_submit_work_wait(dev_info_t *, int); 88 static int man_find_devs(mi_path_t *, uchar_t); 89 static int man_dip_is_schizoxmits0_pcib(dev_info_t *, int *, int *); 90 static int man_dip_is_eri(dev_info_t *, man_dev_t *); 91 static int man_dip_is_attached(dev_info_t *); 92 static int man_get_eri_dev_info(dev_info_t *, man_dev_t *); 93 static int man_mbox_initialized = FALSE; 94 95 /* 96 * Externs 97 */ 98 extern int man_pg_cmd(mi_path_t *, man_work_t *); 99 extern kmutex_t man_lock; 100 extern void *man_softstate; 101 extern man_work_t *man_work_alloc(int, int); 102 extern void man_work_free(man_work_t *); 103 extern void man_work_add(man_workq_t *, man_work_t *); 104 extern man_workq_t *man_bwork_q; 105 extern man_workq_t *man_iwork_q; 106 extern queue_t *man_ctl_wq; 107 108 #if defined(DEBUG) 109 static void man_print_manc(manc_t *); 110 extern uint32_t man_debug; 111 #endif /* DEBUG */ 112 113 int 114 man_domain_configure(void) 115 { 116 int status = 0; 117 118 /* 119 * man_mbox_initialized is protected by inner perimiter lock. 120 */ 121 if (man_mbox_initialized == TRUE) 122 goto exit; 123 124 status = mboxsc_init(IOSRAM_KEY_SCMD, MBOXSC_MBOX_IN, NULL); 125 126 if (status != 0) { 127 cmn_err(CE_WARN, "man_domain_configure: failed to initialize" 128 " MBOXSC_MBOX_IN, errno = %d", status); 129 goto exit; 130 } 131 132 status = mboxsc_init(IOSRAM_KEY_MDSC, MBOXSC_MBOX_OUT, NULL); 133 if (status != 0) { 134 mboxsc_fini(IOSRAM_KEY_SCMD); 135 cmn_err(CE_WARN, "man_domain_configure: failed to initialize" 136 " MBOXSC_MBOX_OUT, errno = %d", status); 137 goto exit; 138 } 139 140 man_mbox_initialized = TRUE; 141 142 status = man_path_discovery(); 143 if (status != 0) { 144 mboxsc_fini(IOSRAM_KEY_SCMD); 145 mboxsc_fini(IOSRAM_KEY_MDSC); 146 man_mbox_initialized = FALSE; 147 } 148 149 exit: 150 return (status); 151 } 152 153 /* 154 * Build pathgroup connecting a domain to the SSC. Only called on domains 155 * at first man_open. On the SSC, pathgroups are built by IOCTL requests 156 * from the MAN daemon (see man_ioctl and mand(1M)). 157 * 158 * Locks held 159 * - exclusive innerperim. 160 */ 161 int 162 man_path_discovery(void) 163 { 164 manc_t manc; 165 mi_path_t mpath; 166 int num_devs; 167 int status = 0; 168 int i; 169 170 MAN_DBG(MAN_CONFIG, ("man_path_discovery:")); 171 172 if (status = man_get_iosram(&manc)) { 173 goto exit; 174 } 175 176 /* 177 * If manc_ip_type indicates MAN network is not enabled 178 * for this domain, then lets just bailout from here as if no 179 * devices were found. 180 */ 181 if ((manc.manc_ip_type != AF_INET) && 182 (manc.manc_ip_type != AF_INET6)) { 183 goto exit; 184 } 185 186 MAN_DBGCALL(MAN_CONFIG, man_print_manc(&manc)); 187 188 /* 189 * Extract SC ethernet address from IOSRAM. 190 */ 191 ether_copy(&manc.manc_sc_eaddr, &mpath.mip_eaddr); 192 193 mpath.mip_pg_id = 0; /* SC is always pathgroup ID 0 */ 194 mpath.mip_man_ppa = 0; /* Domain only has one ppa, 0 */ 195 196 /* 197 * Get list of present devices, and update man_paths[] as needed. 198 */ 199 num_devs = man_find_devs(&mpath, MAN_MAX_EXPANDERS); 200 if (num_devs <= 0) { 201 status = ENODEV; 202 goto exit; 203 } 204 205 mpath.mip_cmd = MI_PATH_ASSIGN; 206 207 mutex_enter(&man_lock); 208 status = man_pg_cmd(&mpath, NULL); 209 if (status) { 210 mutex_exit(&man_lock); 211 goto exit; 212 } 213 214 /* 215 * Now activate the ethernet on the golden io board. 216 */ 217 for (i = 0; i < num_devs; i++) { 218 if (mpath.mip_devs[i].mdev_exp_id == manc.manc_golden_iob) 219 mpath.mip_devs[0] = mpath.mip_devs[i]; 220 } 221 mpath.mip_ndevs = 1; 222 mpath.mip_cmd = MI_PATH_ACTIVATE; 223 status = man_pg_cmd(&mpath, NULL); 224 mutex_exit(&man_lock); 225 226 exit: 227 MAN_DBG(MAN_CONFIG, ("man_path_discovery: returns %d\n", status)); 228 229 return (status); 230 } 231 232 int 233 man_domain_deconfigure(void) 234 { 235 236 mboxsc_fini(IOSRAM_KEY_SCMD); 237 mboxsc_fini(IOSRAM_KEY_MDSC); 238 /* 239 * We are about to unload and know that there are no open 240 * streams, so this change outside of the perimiter is ok. 241 */ 242 man_mbox_initialized = FALSE; 243 244 return (0); 245 } 246 247 /* 248 * Add a work request to the inner perimeter with the new eri device info. 249 */ 250 /* ARGSUSED */ 251 int 252 man_dr_attach(dev_info_t *dip) 253 { 254 man_t *manp; 255 man_work_t *wp; 256 int status = 0; 257 man_dev_t mdev; 258 259 260 mutex_enter(&man_lock); 261 manp = ddi_get_soft_state(man_softstate, 0); 262 if (manp == NULL || manp->man_pg == NULL) { 263 goto exit; 264 } 265 266 if (man_get_eri_dev_info(dip, &mdev) == FALSE) { 267 status = ENODEV; 268 goto exit; 269 } 270 MAN_DBG(MAN_DR, ("man_dr_attach: dip major = %d instance =%d", 271 mdev.mdev_major, mdev.mdev_ppa)); 272 wp = man_work_alloc(MAN_WORK_DRATTACH, KM_NOSLEEP); 273 if (wp == NULL) { 274 status = ENOMEM; 275 goto exit; 276 } 277 278 wp->mw_arg.a_man_ppa = 0; /* Domain only has one ppa, 0 */ 279 wp->mw_arg.a_pg_id = 0; /* SC is always pathgroup ID 0 */ 280 wp->mw_arg.a_sf_dev = mdev; 281 wp->mw_flags = MAN_WFLAGS_NOWAITER; 282 283 man_work_add(man_iwork_q, wp); 284 285 if (man_ctl_wq) 286 qenable(man_ctl_wq); 287 288 exit: 289 mutex_exit(&man_lock); 290 291 return (status); 292 } 293 294 int 295 man_dr_detach(dev_info_t *dip) 296 { 297 man_t *manp; 298 int status = 0; 299 int retries = 0; 300 301 302 mutex_enter(&man_lock); 303 manp = ddi_get_soft_state(man_softstate, 0); 304 if (manp == NULL || manp->man_pg == NULL) { 305 mutex_exit(&man_lock); 306 goto exit; 307 } 308 mutex_exit(&man_lock); 309 310 /* 311 * Arrange to have the detaching path switched if it is active. 312 * We will cv_wait_sig for the switch to complete if it is needed. 313 */ 314 again: 315 status = man_dr_submit_work_wait(dip, MAN_WORK_DRSWITCH); 316 if (status == EAGAIN && retries < manp->man_dr_retries) { 317 /* 318 * Delay a bit and retry. 319 */ 320 MAN_DBG(MAN_DR, 321 ("man_dr_detach(switch): EAGAIN - retrying...")); 322 retries++; 323 delay(drv_usectohz(manp->man_dr_delay)); 324 goto again; 325 } 326 327 if (status) 328 goto exit; 329 330 retries = 0; 331 332 /* 333 * Detaching device no longer in use, remove it from our 334 * pathgroup. 335 */ 336 status = man_dr_submit_work_wait(dip, MAN_WORK_DRDETACH); 337 if (status == EAGAIN && retries < manp->man_dr_retries) { 338 MAN_DBG(MAN_DR, 339 ("man_dr_detach(detach): EAGAIN - retrying...")); 340 retries++; 341 goto again; 342 } 343 344 exit: 345 MAN_DBG(MAN_DR, ("man_dr_detach: returns %d", status)); 346 return (status); 347 } 348 349 static int 350 man_dr_submit_work_wait(dev_info_t *dip, int work_type) 351 { 352 man_work_t *wp; 353 int status = 0; 354 355 wp = man_work_alloc(work_type, KM_NOSLEEP); 356 if (wp == NULL) { 357 status = ENOMEM; 358 goto exit; 359 } 360 361 wp->mw_arg.a_man_ppa = 0; 362 wp->mw_arg.a_pg_id = 0; 363 wp->mw_arg.a_sf_dev.mdev_major = ddi_name_to_major(ddi_get_name(dip)); 364 wp->mw_arg.a_sf_dev.mdev_ppa = ddi_get_instance(dip); 365 366 mutex_enter(&man_lock); 367 wp->mw_flags = MAN_WFLAGS_CVWAITER; 368 man_work_add(man_iwork_q, wp); 369 370 /* TBD - change to ASSERT ? */ 371 if (man_ctl_wq) 372 qenable(man_ctl_wq); 373 374 while (!(wp->mw_flags & MAN_WFLAGS_DONE)) { 375 if (!cv_wait_sig(&wp->mw_cv, &man_lock)) { 376 wp->mw_flags &= ~MAN_WFLAGS_CVWAITER; 377 status = EINTR; 378 break; 379 } 380 } 381 382 /* 383 * Note that if cv_wait_sig() returns zero because a signal 384 * was received, MAN_WFLAGS_DONE may not be set. 385 * This will happen if man_dr_submit_work_wait() reacquires 386 * man_lock before man_iwork() can acquire man_lock just before 387 * signalling its work is complete. 388 * In this case, it is not necessary to call man_work_free() 389 * here because it will be called by man_iwork() because 390 * MAN_WFLAGS_CVWAITER was cleared. 391 * Should man_iwork() obtain man_lock to signal completion, 392 * MAN_WFLAGS_DONE will be set which will ensure man_work_free() 393 * is called here. 394 */ 395 if (wp->mw_flags & MAN_WFLAGS_DONE) { 396 status = wp->mw_status; 397 man_work_free(wp); 398 } 399 400 mutex_exit(&man_lock); 401 402 exit: 403 return (status); 404 } 405 406 /* 407 * Notify SSC of switch request and wait for response. 408 */ 409 int 410 man_dossc_switch(uint32_t exp_id) 411 { 412 uint64_t req_tid; 413 uint32_t req_cmd; 414 uint64_t resp_tid; 415 uint32_t resp_cmd; 416 uint32_t type; 417 man_mbox_msg_t req; 418 man_mbox_msg_t resp; 419 uint32_t length; 420 int status = 0; 421 422 /* 423 * There should be nothing in inbound mailbox. 424 */ 425 resp_tid = resp_cmd = type = 0; 426 length = sizeof (man_mbox_msg_t); 427 bzero((char *)&resp, sizeof (man_mbox_msg_t)); 428 while (mboxsc_getmsg(IOSRAM_KEY_SCMD, &type, &resp_cmd, &resp_tid, 429 &length, &resp, 0) == 0) { 430 431 resp_tid = resp_cmd = type = 0; 432 length = sizeof (man_mbox_msg_t); 433 bzero((char *)&resp, sizeof (man_mbox_msg_t)); 434 435 MAN_DBG(MAN_IOSRAM, ("man_dossc_switch: dumping message")); 436 MAN_DBG(MAN_IOSRAM, ("\tcommand = 0x%x", resp_cmd)); 437 } 438 439 MAN_DBG(MAN_IOSRAM, ("man_dossc_switch: sending message")); 440 441 bzero((char *)&req, sizeof (man_mbox_msg_t)); 442 req.mb_status = 0; 443 req.mb_exp_id = exp_id; 444 req_tid = 0; 445 req_cmd = MAN_WORK_SWITCH; 446 447 status = mboxsc_putmsg(IOSRAM_KEY_MDSC, MBOXSC_MSG_REQUEST, 448 req_cmd, &req_tid, sizeof (man_mbox_msg_t), &req, 449 MAN_IOSRAM_TIMEOUT); 450 451 if (status != 0) { 452 cmn_err(CE_WARN, "man_dossc_switch: mboxsc_putmsg failed," 453 " errno = %d", status); 454 goto exit; 455 } 456 457 bzero((char *)&resp, sizeof (man_mbox_msg_t)); 458 459 resp_tid = type = resp_cmd = 0; 460 length = sizeof (man_mbox_msg_t); 461 status = mboxsc_getmsg(IOSRAM_KEY_SCMD, &type, &resp_cmd, &resp_tid, 462 &length, (void *)&resp, MAN_IOSRAM_TIMEOUT); 463 if (status != 0) { 464 cmn_err(CE_WARN, "man_dossc_switch: mboxsc_getmsg failed," 465 " errno = %d", status); 466 goto exit; 467 } 468 469 MAN_DBG(MAN_IOSRAM, ("man_dossc_switch: received message")); 470 471 if (req_cmd != resp_cmd || req_tid != resp_tid) { 472 cmn_err(CE_WARN, "man_dossc_switch: failed," 473 " cmd/transid mismatch (%d, %d)/(%d, %d)", 474 req_cmd, resp_cmd, (int)req_tid, (int)resp_tid); 475 status = EINVAL; 476 goto exit; 477 } 478 479 status = resp.mb_status; 480 if (status != 0) { 481 cmn_err(CE_WARN, "man_dossc_switch: failed errno == %d", 482 status); 483 } 484 exit: 485 return (status); 486 } 487 488 489 /* 490 * Read IOSRAM info. 491 */ 492 int 493 man_get_iosram(manc_t *mcp) 494 { 495 int status; 496 497 if (mcp == NULL) 498 return (EINVAL); 499 500 status = iosram_rd(IOSRAM_KEY_MANC, 0, sizeof (manc_t), (caddr_t)mcp); 501 if (status) { 502 cmn_err(CE_WARN, "man_get_iosram: iosram_rd failed" 503 " errno = %d\n", status); 504 return (status); 505 } 506 507 MAN_DBG(MAN_PATH, ("man_get_iosram:")); 508 MAN_DBGCALL(MAN_PATH, man_print_manc(mcp)); 509 510 if (mcp->manc_magic != IOSRAM_KEY_MANC) { 511 cmn_err(CE_WARN, "man_get_iosram: bad magic - got(0x%x)" 512 " expected(0x%x)\n", mcp->manc_magic, IOSRAM_KEY_MANC); 513 status = EIO; 514 } else if (mcp->manc_version != MANC_VERSION) { 515 cmn_err(CE_WARN, "man_get_iosram: version mismatch -" 516 " got(0x%x) expected(0x%x)\n", mcp->manc_version, 517 MANC_VERSION); 518 status = EIO; 519 } 520 521 return (status); 522 } 523 524 #if defined(MAN_NO_IOSRAM) 525 526 static manc_t manc = { 527 IOSRAM_KEY_MANC, 528 MANC_VERSION, 529 0, 530 AF_INET, 531 /* 0x10010102, Two */ 532 0x10010103, /* Scot */ 533 0xFF000000, /* Scot netmask */ 534 0x10010101, /* SC 10.1.1.1 */ 535 {0}, /* AF_INET6 addrs */ 536 {0}, /* AF_INET6 addrs */ 537 {0}, 538 /* {0x8, 0x0, 0x20, 0x21, 0x44, 0x83}, Domain eaddr "two" */ 539 {0x8, 0x0, 0x20, 0x8f, 0x84, 0x63}, /* Domain eaddr "scot" */ 540 {0x8, 0x0, 0x20, 0x1f, 0xe3, 0x46}, /* SC eaddr "one" */ 541 0x1, 542 0x1 543 }; 544 545 546 /* 547 * Get IOSRAM info or release it. 548 */ 549 int 550 man_get_iosram(manc_t *mcp) 551 { 552 int status = 0; 553 554 if (mcp == NULL) 555 return (EINVAL); 556 557 *mcp = manc; 558 559 if (mcp->manc_magic != IOSRAM_KEY_MANC) { 560 cmn_err(CE_WARN, "man_get_iosram: bad magic - got(0x%x)" 561 " expected(0x%x)\n", mcp->manc_magic, IOSRAM_KEY_MANC); 562 status = EIO; 563 } else if (mcp->manc_version != MANC_VERSION) { 564 cmn_err(CE_WARN, "man_get_iosram: version mismatch -" 565 " got(0x%x) expected(0x%x)\n", mcp->manc_version, 566 MANC_VERSION); 567 status = EIO; 568 } 569 570 return (status); 571 } 572 #endif /* MAN_NO_IOSRAM */ 573 574 /* 575 * Find all RIOs on the IO boards for the domain. We walk all the children 576 * of the root node looking for a PCI devinfo with a safari port ID of 577 * 0xDC that has a child with device ID of 3. This is gauranteed to be 578 * the network portion of the RIO by virtue of the way Starcats are 579 * physically built. 580 */ 581 static int 582 man_find_devs(mi_path_t *mipathp, uchar_t golden_iob) 583 { 584 dev_info_t *bus_dip; 585 dev_info_t *eri_dip; 586 dev_info_t *rdip, *pdip; 587 int exp_id; 588 int found = 0; 589 int circ; 590 int circ2; 591 man_dev_t ndev; 592 int xmits; 593 594 MAN_DBG(MAN_PATH, ("man_find_devs: mdevpp(0x%p) golden_iob(%d)\n", 595 (void *)(mipathp), golden_iob)); 596 597 /* 598 * Hold parent busy while walking its child list. 599 */ 600 rdip = ddi_root_node(); 601 ndi_devi_enter(rdip, &circ); 602 bus_dip = ddi_get_child(rdip); 603 604 while (bus_dip != NULL) { 605 exp_id = -1; 606 xmits = 0; 607 if (man_dip_is_schizoxmits0_pcib(bus_dip, &exp_id, &xmits)) { 608 eri_dip = NULL; 609 pdip = bus_dip; 610 if (xmits) { 611 /* 612 * If this is XMITS0 PCI_B leaf, then the 613 * pci_pci bridge which is the only child, 614 * is the parent to MAN RIO. 615 */ 616 pdip = ddi_get_child(bus_dip); 617 if (pdip == NULL) { 618 bus_dip = ddi_get_next_sibling(bus_dip); 619 continue; 620 } 621 } 622 ndi_devi_enter(pdip, &circ2); 623 eri_dip = ddi_get_child(pdip); 624 while (eri_dip != NULL) { 625 MAN_DBG(MAN_PATH, ("man_find_devs: " 626 "eri_dip %s\n", 627 ddi_binding_name(eri_dip))); 628 if (man_dip_is_eri(eri_dip, &ndev) && 629 man_dip_is_attached(eri_dip)) { 630 631 ASSERT(exp_id != -1); 632 ndev.mdev_exp_id = exp_id; 633 ndev.mdev_state = MDEV_ASSIGNED; 634 mipathp->mip_devs[found] = ndev; 635 found++; 636 637 MAN_DBG(MAN_PATH, 638 ("man_find_devs: found eri maj(%d) " 639 "ppa(%d) on expander(%d)\n", 640 ndev.mdev_major, 641 ndev.mdev_ppa, exp_id)); 642 } 643 eri_dip = ddi_get_next_sibling(eri_dip); 644 } 645 ndi_devi_exit(pdip, circ2); 646 } 647 bus_dip = ddi_get_next_sibling(bus_dip); 648 } 649 ndi_devi_exit(rdip, circ); 650 651 MAN_DBG(MAN_PATH, ("man_find_devs returns found = %d\n", found)); 652 653 mipathp->mip_ndevs = found; 654 return (found); 655 } 656 657 /* 658 * Verify if the dip passed is an instance of 'eri' and set 659 * the device info in mdevp. 660 */ 661 static int 662 man_get_eri_dev_info(dev_info_t *dip, man_dev_t *mdevp) 663 { 664 dev_info_t *parent_dip; 665 int exp_id; 666 int xmits; 667 char *name; 668 669 ASSERT(dip != NULL); 670 /* 671 * Verify if the parent is schizo(xmits)0 and pci B leaf. 672 */ 673 if (((parent_dip = ddi_get_parent(dip)) == NULL) || 674 ((name = ddi_binding_name(parent_dip)) == NULL)) 675 return (FALSE); 676 if (strcmp(name, MAN_SCHIZO_BINDING_NAME) != 0) { 677 /* 678 * This RIO could be on XMITS, so get the dip to 679 * XMITS PCI Leaf. 680 */ 681 if ((parent_dip = ddi_get_parent(parent_dip)) == NULL) 682 return (FALSE); 683 if (((name = ddi_binding_name(parent_dip)) == NULL) || 684 (strcmp(name, MAN_XMITS_BINDING_NAME) != 0)) { 685 return (FALSE); 686 } 687 } 688 if (man_dip_is_schizoxmits0_pcib(parent_dip, &exp_id, &xmits) == FALSE) 689 return (FALSE); 690 691 /* 692 * Make sure it is attached. 693 */ 694 if (man_dip_is_attached(dip) == FALSE) { 695 MAN_DBG(MAN_DR, ("man_get_eri_dev_info: " 696 "dip 0x%p not attached\n", dip)); 697 return (FALSE); 698 } 699 mdevp->mdev_exp_id = exp_id; 700 mdevp->mdev_ppa = ddi_get_instance(dip); 701 mdevp->mdev_major = 702 ddi_name_to_major(ddi_get_name(dip)); 703 mdevp->mdev_state = MDEV_ASSIGNED; 704 return (TRUE); 705 } 706 707 /* 708 * MAN RIO is connected to SCHIZO/XMITS 0 and PCI_B Leaf. 709 * Incase of XMITS, it is actually connected to a PCI Bridge(21154) 710 * which is directly connected to the PCI_B leaf of XMITS0. 711 * 712 * This function verifies if the given dip is SCHIZO/XMITS 0 and 713 * PCI_B Leaf. This is done as follows: 714 * 715 * - Check the binding name to verify SCHIZO/XMITS. 716 * - Verify the Device type to be "pci". 717 * - Verify the PortID to be ending with 0x1C 718 * - Verify the the CSR base to be 0x70.0000. 719 */ 720 static int 721 man_dip_is_schizoxmits0_pcib(dev_info_t *dip, int *exp_id, int *xmits) 722 { 723 char dtype[MAN_DDI_BUFLEN]; 724 int portid; 725 uint_t pci_csr_base; 726 struct pci_phys_spec *regbuf = NULL; 727 int length = MAN_DDI_BUFLEN; 728 char *name; 729 730 ASSERT(dip != NULL); 731 *exp_id = -1; 732 if ((name = ddi_binding_name(dip)) == NULL) 733 return (FALSE); 734 if (strcmp(name, MAN_SCHIZO_BINDING_NAME) == 0) { 735 MAN_DBG(MAN_PATH, ("man_dip_is_schizoxmits0_pcib: " 736 "SCHIZO found 0x%p\n", dip)); 737 } else if (strcmp(name, MAN_XMITS_BINDING_NAME) == 0) { 738 *xmits = TRUE; 739 MAN_DBG(MAN_PATH, ("man_dip_is_schizoxmits0_pcib: " 740 "XMITS found 0x%p\n", dip)); 741 } else 742 return (FALSE); 743 if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, MAN_DEVTYPE_PROP, 744 (caddr_t)dtype, &length) == DDI_PROP_SUCCESS) { 745 746 MAN_DBG(MAN_PATH, ("dtype: %s\n", dtype)); 747 if (strncmp(dtype, MAN_DEVTYPE_PCI, 3) != 0) 748 goto notfound; 749 750 /* 751 * Get safari ID (DDI port ID). 752 */ 753 if ((portid = (int)ddi_getprop(DDI_DEV_T_ANY, dip, 0, 754 MAN_PORTID_PROP, -1)) == -1) { 755 756 MAN_DBG(MAN_PATH, ("ddi_getpropp: failed\n")); 757 goto notfound; 758 } 759 760 /* 761 * All schizo 0 safari IDs end in 0x1C. 762 */ 763 if ((portid & MAN_SCHIZO_MASK) != MAN_SCHIZO_0_ID) 764 goto notfound; 765 766 /* 767 * All PCI nodes "B" are at configspace 0x70.0000 768 */ 769 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 770 MAN_REG_PROP, (caddr_t)®buf, 771 &length) != DDI_PROP_SUCCESS) { 772 773 MAN_DBG(MAN_PATH, ("ddi_getlongprop_buf: failed")); 774 goto notfound; 775 } 776 777 pci_csr_base = regbuf[0].pci_phys_mid & PCI_CONF_ADDR_MASK; 778 kmem_free(regbuf, length); 779 if (pci_csr_base == MAN_PCI_B_CSR_BASE) { 780 781 MAN_DBG(MAN_PATH, ("man_dip_is_schizoxmits0_pcib:" 782 " found PCI B at dip(0x%p)\n", (void *)dip)); 783 784 *exp_id = portid >> 5; 785 return (TRUE); 786 } 787 } 788 789 notfound: 790 return (FALSE); 791 } 792 793 static int 794 man_dip_is_eri(dev_info_t *dip, man_dev_t *ndevp) 795 { 796 struct pci_phys_spec *regbuf = NULL; 797 int length = 0; 798 uint_t pci_device; 799 uint_t pci_function; 800 801 MAN_DBG(MAN_PATH, ("man_dip_is_eri: dip(0x%p) ndevp(0x%p)\n", 802 (void *)dip, (void *)ndevp)); 803 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 804 MAN_REG_PROP, (caddr_t)®buf, 805 &length) == DDI_PROP_SUCCESS) { 806 807 pci_device = PCI_REG_DEV_G(regbuf->pci_phys_hi); 808 pci_function = PCI_REG_FUNC_G(regbuf->pci_phys_hi); 809 kmem_free(regbuf, length); 810 811 /* 812 * The network function of the RIO ASIC will always 813 * be device 3 and function 1 ("network@3,1"). 814 */ 815 if (pci_device == 3 && pci_function == 1) { 816 ndevp->mdev_ppa = ddi_get_instance(dip); 817 ndevp->mdev_major = 818 ddi_name_to_major(ddi_get_name(dip)); 819 820 MAN_DBG(MAN_PATH, ("man_dip_is_eri: found eri maj(%d)" 821 " ppa(%d)\n", ndevp->mdev_major, ndevp->mdev_ppa)); 822 823 return (TRUE); 824 } 825 } 826 827 MAN_DBG(MAN_PATH, ("man_dip_is_eri: returns FALSE\n")); 828 829 return (FALSE); 830 } 831 832 static int 833 man_dip_is_attached(dev_info_t *dip) 834 { 835 int state; 836 837 state = ddi_get_devstate(dip); 838 if (i_ddi_devi_attached(dip) || (state == DDI_DEVSTATE_UP)) { 839 /* 840 * The instance info is more important for us, 841 * so verify. 842 */ 843 if (ddi_get_instance(dip) >= 0) { 844 return (TRUE); 845 } 846 cmn_err(CE_WARN, "man_dip_is_attached: " 847 "eri 0x%p instance is not set yet", dip); 848 849 } 850 return (FALSE); 851 } 852 853 #if defined(DEBUG) 854 static void 855 man_print_manc(manc_t *mcp) 856 { 857 cmn_err(CE_CONT, "\tmcp(0x%p)\n\n", (void *)mcp); 858 859 if (mcp == NULL) 860 return; 861 862 cmn_err(CE_CONT, "\tmagic: 0x%x\n", mcp->manc_magic); 863 cmn_err(CE_CONT, "\tversion: 0x%x\n", mcp->manc_version); 864 cmn_err(CE_CONT, "\tcsum: %d\n", mcp->manc_csum); 865 cmn_err(CE_CONT, "\tdom_eaddr: %s\n", 866 ether_sprintf(&mcp->manc_dom_eaddr)); 867 cmn_err(CE_CONT, "\tsc_eaddr: %s\n", 868 ether_sprintf(&mcp->manc_sc_eaddr)); 869 cmn_err(CE_CONT, "\tiob_bitmap: 0x%x\n", mcp->manc_iob_bitmap); 870 cmn_err(CE_CONT, "\tgolden_iob: %d\n", mcp->manc_golden_iob); 871 872 } 873 874 #endif /* DEBUG */ 875