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