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 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 26 /* 27 * PCI-IDE bus nexus driver 28 */ 29 30 #include <sys/types.h> 31 #include <sys/cmn_err.h> 32 #include <sys/conf.h> 33 #include <sys/errno.h> 34 #include <sys/debug.h> 35 #include <sys/ddidmareq.h> 36 #include <sys/ddi_impldefs.h> 37 #include <sys/dma_engine.h> 38 #include <sys/modctl.h> 39 #include <sys/ddi.h> 40 #include <sys/sunddi.h> 41 #include <sys/sunndi.h> 42 #include <sys/mach_intr.h> 43 #include <sys/kmem.h> 44 #include <sys/pci.h> 45 #include <sys/promif.h> 46 #include <sys/pci_intr_lib.h> 47 #include <sys/apic.h> 48 49 int pciide_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 50 int pciide_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 51 52 #define PCIIDE_NATIVE_MODE(dip) \ 53 (!ddi_prop_exists(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \ 54 "compatibility-mode")) 55 56 #define PCIIDE_PRE26(dip) \ 57 ddi_prop_exists(DDI_DEV_T_ANY, (dip), 0, "ignore-hardware-nodes") 58 59 #define PCI_IDE_IF_BM_CAP_MASK 0x80 60 61 #define PCIIDE_PDSIZE (sizeof (struct ddi_parent_private_data) + \ 62 sizeof (struct intrspec)) 63 64 #ifdef DEBUG 65 static int pci_ide_debug = 0; 66 #define PDBG(fmt) \ 67 if (pci_ide_debug) { \ 68 prom_printf fmt; \ 69 } 70 #else 71 #define PDBG(fmt) 72 #endif 73 74 #ifndef TRUE 75 #define TRUE 1 76 #endif 77 #ifndef FALSE 78 #define FALSE 0 79 #endif 80 81 /* 82 * bus_ops functions 83 */ 84 85 static int pciide_bus_map(dev_info_t *dip, dev_info_t *rdip, 86 ddi_map_req_t *mp, off_t offset, off_t len, 87 caddr_t *vaddrp); 88 89 static int pciide_ddi_ctlops(dev_info_t *dip, dev_info_t *rdip, 90 ddi_ctl_enum_t ctlop, void *arg, 91 void *result); 92 93 static int pciide_get_pri(dev_info_t *dip, dev_info_t *rdip, 94 ddi_intr_handle_impl_t *hdlp, int *pri); 95 96 static int pciide_intr_ops(dev_info_t *dip, dev_info_t *rdip, 97 ddi_intr_op_t intr_op, 98 ddi_intr_handle_impl_t *hdlp, void *result); 99 100 static struct intrspec *pciide_get_ispec(dev_info_t *dip, dev_info_t *rdip, 101 int inum); 102 103 /* 104 * Local Functions 105 */ 106 static int pciide_initchild(dev_info_t *mydip, dev_info_t *cdip); 107 108 static void pciide_compat_setup(dev_info_t *mydip, dev_info_t *cdip, 109 int dev); 110 static int pciide_pre26_rnumber_map(dev_info_t *mydip, int rnumber); 111 static int pciide_map_rnumber(int canonical_rnumber, int pri_native, 112 int sec_native); 113 static int pciide_alloc_intr(dev_info_t *, dev_info_t *, 114 ddi_intr_handle_impl_t *, void *); 115 static int pciide_free_intr(dev_info_t *, dev_info_t *, 116 ddi_intr_handle_impl_t *); 117 118 extern int (*psm_intr_ops)(dev_info_t *, ddi_intr_handle_impl_t *, 119 psm_intr_op_t, int *); 120 121 /* 122 * Config information 123 */ 124 125 struct bus_ops pciide_bus_ops = { 126 BUSO_REV, 127 pciide_bus_map, 128 0, 129 0, 130 0, 131 i_ddi_map_fault, 132 ddi_dma_map, 133 ddi_dma_allochdl, 134 ddi_dma_freehdl, 135 ddi_dma_bindhdl, 136 ddi_dma_unbindhdl, 137 ddi_dma_flush, 138 ddi_dma_win, 139 ddi_dma_mctl, 140 pciide_ddi_ctlops, 141 ddi_bus_prop_op, 142 0, /* (*bus_get_eventcookie)(); */ 143 0, /* (*bus_add_eventcall)(); */ 144 0, /* (*bus_remove_eventcall)(); */ 145 0, /* (*bus_post_event)(); */ 146 0, 147 0, 148 0, 149 0, 150 0, 151 0, 152 0, 153 0, 154 pciide_intr_ops 155 }; 156 157 struct dev_ops pciide_ops = { 158 DEVO_REV, /* devo_rev, */ 159 0, /* refcnt */ 160 ddi_no_info, /* info */ 161 nulldev, /* identify */ 162 nulldev, /* probe */ 163 pciide_attach, /* attach */ 164 pciide_detach, /* detach */ 165 nodev, /* reset */ 166 (struct cb_ops *)0, /* driver operations */ 167 &pciide_bus_ops, /* bus operations */ 168 NULL, /* power */ 169 ddi_quiesce_not_needed, /* quiesce */ 170 }; 171 172 /* 173 * Module linkage information for the kernel. 174 */ 175 176 static struct modldrv modldrv = { 177 &mod_driverops, /* Type of module. This is PCI-IDE bus driver */ 178 "pciide nexus driver for 'PCI-IDE' 1.26", 179 &pciide_ops, /* driver ops */ 180 }; 181 182 static struct modlinkage modlinkage = { 183 MODREV_1, 184 &modldrv, 185 NULL 186 }; 187 188 189 int 190 _init(void) 191 { 192 return (mod_install(&modlinkage)); 193 } 194 195 int 196 _fini(void) 197 { 198 return (mod_remove(&modlinkage)); 199 } 200 201 int 202 _info(struct modinfo *modinfop) 203 { 204 return (mod_info(&modlinkage, modinfop)); 205 } 206 207 int 208 pciide_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 209 { 210 uint16_t cmdreg; 211 ddi_acc_handle_t conf_hdl = NULL; 212 int rc; 213 214 switch (cmd) { 215 case DDI_ATTACH: 216 /* 217 * Make sure bus-mastering is enabled, even if 218 * BIOS didn't. 219 */ 220 rc = pci_config_setup(dip, &conf_hdl); 221 222 /* 223 * In case of error, return SUCCESS. This is because 224 * bus-mastering could be already enabled by BIOS. 225 */ 226 if (rc != DDI_SUCCESS) 227 return (DDI_SUCCESS); 228 229 cmdreg = pci_config_get16(conf_hdl, PCI_CONF_COMM); 230 if ((cmdreg & PCI_COMM_ME) == 0) { 231 pci_config_put16(conf_hdl, PCI_CONF_COMM, 232 cmdreg | PCI_COMM_ME); 233 } 234 pci_config_teardown(&conf_hdl); 235 return (DDI_SUCCESS); 236 237 case DDI_RESUME: 238 /* Restore our PCI configuration header */ 239 if (pci_restore_config_regs(dip) != DDI_SUCCESS) { 240 /* 241 * XXXX 242 * This is a pretty bad thing. However, for some 243 * reason it always happens. To further complicate 244 * things, it appears if we just ignore this, we 245 * properly resume. For now, all I want to do is 246 * to generate this message so that it doesn't get 247 * forgotten. 248 */ 249 cmn_err(CE_WARN, 250 "Couldn't restore PCI config regs for %s(%p)", 251 ddi_node_name(dip), (void *) dip); 252 } 253 #ifdef DEBUG 254 /* Bus mastering should still be enabled */ 255 if (pci_config_setup(dip, &conf_hdl) != DDI_SUCCESS) 256 return (DDI_FAILURE); 257 cmdreg = pci_config_get16(conf_hdl, PCI_CONF_COMM); 258 ASSERT((cmdreg & PCI_COMM_ME) != 0); 259 pci_config_teardown(&conf_hdl); 260 #endif 261 return (DDI_SUCCESS); 262 } 263 264 return (DDI_FAILURE); 265 } 266 267 /*ARGSUSED*/ 268 int 269 pciide_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 270 { 271 switch (cmd) { 272 case DDI_DETACH: 273 return (DDI_SUCCESS); 274 case DDI_SUSPEND: 275 /* Save our PCI configuration header */ 276 if (pci_save_config_regs(dip) != DDI_SUCCESS) { 277 /* Don't suspend if we cannot save config regs */ 278 return (DDI_FAILURE); 279 } 280 return (DDI_SUCCESS); 281 } 282 return (DDI_FAILURE); 283 } 284 285 /*ARGSUSED*/ 286 static int 287 pciide_ddi_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop, 288 void *arg, void *result) 289 { 290 dev_info_t *cdip; 291 int controller; 292 void *pdptr; 293 int rnumber; 294 off_t tmp; 295 int rc; 296 297 PDBG(("pciide_bus_ctl\n")); 298 299 switch (ctlop) { 300 case DDI_CTLOPS_INITCHILD: 301 cdip = (dev_info_t *)arg; 302 return (pciide_initchild(dip, cdip)); 303 304 case DDI_CTLOPS_UNINITCHILD: 305 cdip = (dev_info_t *)arg; 306 pdptr = ddi_get_parent_data(cdip); 307 ddi_set_parent_data(cdip, NULL); 308 ddi_set_name_addr(cdip, NULL); 309 kmem_free(pdptr, PCIIDE_PDSIZE); 310 return (DDI_SUCCESS); 311 312 case DDI_CTLOPS_NREGS: 313 *(int *)result = 3; 314 return (DDI_SUCCESS); 315 316 case DDI_CTLOPS_REGSIZE: 317 /* 318 * Adjust the rnumbers based on which controller instance 319 * is requested; adjust for the 2 tuples per controller. 320 */ 321 if (strcmp("0", ddi_get_name_addr(rdip)) == 0) 322 controller = 0; 323 else 324 controller = 1; 325 326 327 switch (rnumber = *(int *)arg) { 328 case 0: 329 case 1: 330 rnumber += (2 * controller); 331 break; 332 case 2: 333 rnumber = 4; 334 break; 335 default: 336 PDBG(("pciide_ctlops invalid rnumber\n")); 337 return (DDI_FAILURE); 338 } 339 340 341 if (PCIIDE_PRE26(dip)) { 342 int old_rnumber; 343 int new_rnumber; 344 345 old_rnumber = rnumber; 346 new_rnumber 347 = pciide_pre26_rnumber_map(dip, old_rnumber); 348 PDBG(("pciide rnumber old %d new %d\n", 349 old_rnumber, new_rnumber)); 350 rnumber = new_rnumber; 351 } 352 353 /* 354 * Add 1 to skip over the PCI config space tuple 355 */ 356 rnumber++; 357 358 /* 359 * If it's not tuple #2 pass the adjusted request to my parent 360 */ 361 if (*(int *)arg != 2) { 362 return (ddi_ctlops(dip, dip, ctlop, &rnumber, result)); 363 } 364 365 /* 366 * Handle my child's reg-tuple #2 here by splitting my 16 byte 367 * reg-tuple #4 into two 8 byte ranges based on the 368 * the child's controller #. 369 */ 370 371 tmp = 8; 372 rc = ddi_ctlops(dip, dip, ctlop, &rnumber, &tmp); 373 374 /* 375 * Allow for the possibility of less than 16 bytes by 376 * by checking what's actually returned for my reg-tuple #4. 377 */ 378 if (controller == 1) { 379 if (tmp < 8) 380 tmp = 0; 381 else 382 tmp -= 8; 383 } 384 if (tmp > 8) 385 tmp = 8; 386 *(off_t *)result = tmp; 387 388 return (rc); 389 390 case DDI_CTLOPS_ATTACH: 391 case DDI_CTLOPS_DETACH: 392 /* 393 * Don't pass child ide ATTACH/DETACH to parent 394 */ 395 return (DDI_SUCCESS); 396 397 default: 398 return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 399 } 400 } 401 402 /* 403 * IEEE 1275 Working Group Proposal #414 says that the Primary 404 * controller is "ata@0" and the Secondary controller "ata@1". 405 * 406 * By the time we get here, boot Bootconf (2.6+) has created devinfo 407 * nodes with the appropriate "reg", "assigned-addresses" and "interrupts" 408 * properites on the pci-ide node and both ide child nodes. 409 * 410 * In compatibility mode the "reg" and "assigned-addresses" properties 411 * of the pci-ide node are set up like this: 412 * 413 * 1. PCI-IDE Nexus 414 * 415 * interrupts=0 416 * (addr-hi addr-mid addr-low size-hi size-low) 417 * reg= assigned-addresses=00000000.00000000.00000000.00000000.00000000 418 * 81000000.00000000.000001f0.00000000.00000008 419 * 81000000.00000000.000003f4.00000000.00000004 420 * 81000000.00000000,00000170.00000000.00000008 421 * 81000000.00000000,00000374.00000000.00000004 422 * 01000020.00000000,-[BAR4]-.00000000.00000010 423 * 424 * In native PCI mode the "reg" and "assigned-addresses" properties 425 * would be set up like this: 426 * 427 * 2. PCI-IDE Nexus 428 * 429 * interrupts=0 430 * reg= assigned-addresses=00000000.00000000.00000000.00000000.00000000 431 * 01000010.00000000.-[BAR0]-.00000000.00000008 432 * 01000014,00000000.-[BAR1]-.00000000.00000004 433 * 01000018.00000000.-[BAR2]-.00000000.00000008 434 * 0100001c.00000000.-[BAR3]-.00000000.00000004 435 * 01000020.00000000.-[BAR4]-.00000000.00000010 436 * 437 * 438 * In both modes the child nodes simply have the following: 439 * 440 * 2. primary controller (compatibility mode) 441 * 442 * interrupts=14 443 * reg=00000000 444 * 445 * 3. secondary controller 446 * 447 * interrupts=15 448 * reg=00000001 449 * 450 * The pciide_bus_map() function is responsible for turning requests 451 * to map primary or secondary controller rnumbers into mapping requests 452 * of the appropriate regspec on the pci-ide node. 453 * 454 */ 455 456 static int 457 pciide_initchild(dev_info_t *mydip, dev_info_t *cdip) 458 { 459 struct ddi_parent_private_data *pdptr; 460 struct intrspec *ispecp; 461 int vec; 462 int *rp; 463 uint_t proplen; 464 char name[80]; 465 int dev; 466 467 PDBG(("pciide_initchild\n")); 468 469 /* 470 * Set the address portion of the node name based on 471 * the controller number (0 or 1) from the 'reg' property. 472 */ 473 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, 474 "reg", &rp, (uint_t *)&proplen) != DDI_PROP_SUCCESS) { 475 PDBG(("pciide_intchild prop error\n")); 476 return (DDI_NOT_WELL_FORMED); 477 } 478 479 /* 480 * copy the controller number and 481 * free the memory allocated by ddi_prop_lookup_int_array 482 */ 483 dev = *rp; 484 ddi_prop_free(rp); 485 486 /* 487 * I only support two controllers per device, determine 488 * which this one is and set its unit address. 489 */ 490 if (dev > 1) { 491 PDBG(("pciide_initchild bad dev\n")); 492 return (DDI_NOT_WELL_FORMED); 493 } 494 (void) sprintf(name, "%d", dev); 495 ddi_set_name_addr(cdip, name); 496 497 /* 498 * determine if this instance is running in native or compat mode 499 */ 500 pciide_compat_setup(mydip, cdip, dev); 501 502 /* interrupts property is required */ 503 if (PCIIDE_NATIVE_MODE(cdip)) { 504 vec = 1; 505 } else { 506 /* 507 * In compatibility mode, dev 0 should always be 508 * IRQ 14 and dev 1 is IRQ 15. If for some reason 509 * this needs to be changed, do it via the interrupts 510 * property in the ata.conf file. 511 */ 512 vec = ddi_prop_get_int(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, 513 "interrupts", -1); 514 if (vec == -1) { 515 /* setup compatibility mode interrupts */ 516 if (dev == 0) { 517 vec = 14; 518 } else if (dev == 1) { 519 vec = 15; 520 } else { 521 PDBG(("pciide_initchild bad intr\n")); 522 return (DDI_NOT_WELL_FORMED); 523 } 524 } 525 } 526 527 pdptr = kmem_zalloc(PCIIDE_PDSIZE, KM_SLEEP); 528 ispecp = (struct intrspec *)(pdptr + 1); 529 pdptr->par_nintr = 1; 530 pdptr->par_intr = ispecp; 531 ispecp->intrspec_vec = vec; 532 ddi_set_parent_data(cdip, pdptr); 533 534 PDBG(("pciide_initchild okay\n")); 535 return (DDI_SUCCESS); 536 } 537 538 static int 539 pciide_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 540 off_t offset, off_t len, caddr_t *vaddrp) 541 { 542 dev_info_t *pdip; 543 int rnumber = mp->map_obj.rnumber; 544 int controller; 545 int rc; 546 547 PDBG(("pciide_bus_map\n")); 548 549 if (strcmp("0", ddi_get_name_addr(rdip)) == 0) 550 controller = 0; 551 else 552 controller = 1; 553 554 /* 555 * Adjust the rnumbers based on which controller instance 556 * is being mapped; adjust for the 2 tuples per controller. 557 */ 558 559 switch (rnumber) { 560 case 0: 561 case 1: 562 mp->map_obj.rnumber += (controller * 2); 563 break; 564 case 2: 565 /* 566 * split the 16 I/O ports into two 8 port ranges 567 */ 568 mp->map_obj.rnumber = 4; 569 if (offset + len > 8) { 570 PDBG(("pciide_bus_map offset\n")); 571 return (DDI_FAILURE); 572 } 573 if (len == 0) 574 len = 8 - offset; 575 offset += 8 * controller; 576 break; 577 default: 578 PDBG(("pciide_bus_map default\n")); 579 return (DDI_FAILURE); 580 } 581 582 if (PCIIDE_PRE26(dip)) { 583 int old_rnumber; 584 int new_rnumber; 585 586 old_rnumber = mp->map_obj.rnumber; 587 new_rnumber = pciide_pre26_rnumber_map(dip, old_rnumber); 588 PDBG(("pciide rnumber old %d new %d\n", 589 old_rnumber, new_rnumber)); 590 mp->map_obj.rnumber = new_rnumber; 591 } 592 593 /* 594 * Add 1 to skip over the PCI config space tuple 595 */ 596 mp->map_obj.rnumber++; 597 598 599 /* 600 * pass the adjusted request to my parent 601 */ 602 pdip = ddi_get_parent(dip); 603 rc = ((*(DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)) 604 (pdip, dip, mp, offset, len, vaddrp)); 605 606 PDBG(("pciide_bus_map %s\n", rc == DDI_SUCCESS ? "okay" : "!ok")); 607 608 return (rc); 609 } 610 611 612 static struct intrspec * 613 pciide_get_ispec(dev_info_t *dip, dev_info_t *rdip, int inumber) 614 { 615 struct ddi_parent_private_data *ppdptr; 616 617 PDBG(("pciide_get_ispec\n")); 618 619 /* 620 * Native mode PCI-IDE controllers share the parent's 621 * PCI interrupt line. 622 * 623 * Compatibility mode PCI-IDE controllers have their 624 * own intrspec which specifies ISA IRQ 14 or 15. 625 * 626 */ 627 if (PCIIDE_NATIVE_MODE(rdip)) { 628 ddi_intrspec_t is; 629 630 is = pci_intx_get_ispec(dip, dip, inumber); 631 PDBG(("pciide_get_ispec okay\n")); 632 return ((struct intrspec *)is); 633 } 634 635 /* Else compatibility mode, use the ISA IRQ */ 636 if ((ppdptr = ddi_get_parent_data(rdip)) == NULL) { 637 PDBG(("pciide_get_ispec null\n")); 638 return (NULL); 639 } 640 641 /* validate the interrupt number */ 642 if (inumber >= ppdptr->par_nintr) { 643 PDBG(("pciide_get_inum\n")); 644 return (NULL); 645 } 646 647 PDBG(("pciide_get_ispec ok\n")); 648 649 return ((struct intrspec *)&ppdptr->par_intr[inumber]); 650 } 651 652 static int 653 pciide_get_pri(dev_info_t *dip, dev_info_t *rdip, 654 ddi_intr_handle_impl_t *hdlp, int *pri) 655 { 656 struct intrspec *ispecp; 657 int *intpriorities; 658 uint_t num_intpriorities; 659 660 PDBG(("pciide_get_pri\n")); 661 662 if ((ispecp = pciide_get_ispec(dip, rdip, hdlp->ih_inum)) == NULL) { 663 PDBG(("pciide_get_pri null\n")); 664 return (DDI_FAILURE); 665 } 666 667 if (PCIIDE_NATIVE_MODE(rdip)) { 668 *pri = ispecp->intrspec_pri; 669 PDBG(("pciide_get_pri ok\n")); 670 return (DDI_SUCCESS); 671 } 672 673 /* check if the intrspec has been initialized */ 674 if (ispecp->intrspec_pri != 0) { 675 *pri = ispecp->intrspec_pri; 676 PDBG(("pciide_get_pri ok2\n")); 677 return (DDI_SUCCESS); 678 } 679 680 /* Use a default of level 5 */ 681 ispecp->intrspec_pri = 5; 682 683 /* 684 * If there's an interrupt-priorities property, use it to 685 * over-ride the default interrupt priority. 686 */ 687 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS, 688 "interrupt-priorities", &intpriorities, &num_intpriorities) == 689 DDI_PROP_SUCCESS) { 690 if (hdlp->ih_inum < num_intpriorities) 691 ispecp->intrspec_pri = intpriorities[hdlp->ih_inum]; 692 ddi_prop_free(intpriorities); 693 } 694 *pri = ispecp->intrspec_pri; 695 696 PDBG(("pciide_get_pri ok3\n")); 697 698 return (DDI_SUCCESS); 699 } 700 701 static int 702 pciide_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, 703 ddi_intr_handle_impl_t *hdlp, void *result) 704 { 705 struct intrspec *ispecp; 706 int rc; 707 int pri = 0; 708 709 PDBG(("pciide_intr_ops: dip %p rdip %p op %x hdlp %p\n", 710 (void *)dip, (void *)rdip, intr_op, (void *)hdlp)); 711 712 switch (intr_op) { 713 case DDI_INTROP_SUPPORTED_TYPES: 714 *(int *)result = DDI_INTR_TYPE_FIXED; 715 break; 716 case DDI_INTROP_GETCAP: 717 *(int *)result = DDI_INTR_FLAG_LEVEL; 718 break; 719 case DDI_INTROP_NINTRS: 720 case DDI_INTROP_NAVAIL: 721 *(int *)result = (!PCIIDE_NATIVE_MODE(rdip)) ? 722 i_ddi_get_intx_nintrs(rdip) : 1; 723 break; 724 case DDI_INTROP_ALLOC: 725 return (pciide_alloc_intr(dip, rdip, hdlp, result)); 726 case DDI_INTROP_FREE: 727 return (pciide_free_intr(dip, rdip, hdlp)); 728 case DDI_INTROP_GETPRI: 729 if (pciide_get_pri(dip, rdip, hdlp, &pri) != DDI_SUCCESS) { 730 *(int *)result = 0; 731 return (DDI_FAILURE); 732 } 733 *(int *)result = pri; 734 break; 735 case DDI_INTROP_ADDISR: 736 if ((ispecp = pciide_get_ispec(dip, rdip, hdlp->ih_inum)) == 737 NULL) 738 return (DDI_FAILURE); 739 ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispecp; 740 ispecp->intrspec_func = hdlp->ih_cb_func; 741 break; 742 case DDI_INTROP_REMISR: 743 if ((ispecp = pciide_get_ispec(dip, rdip, hdlp->ih_inum)) == 744 NULL) 745 return (DDI_FAILURE); 746 ispecp->intrspec_func = (uint_t (*)()) 0; 747 break; 748 case DDI_INTROP_ENABLE: 749 /* FALLTHRU */ 750 case DDI_INTROP_DISABLE: 751 if (PCIIDE_NATIVE_MODE(rdip)) { 752 rdip = dip; 753 dip = ddi_get_parent(dip); 754 } else { /* get ptr to the root node */ 755 dip = ddi_root_node(); 756 } 757 758 rc = (*(DEVI(dip)->devi_ops->devo_bus_ops->bus_intr_op))(dip, 759 rdip, intr_op, hdlp, result); 760 761 #ifdef DEBUG 762 if (intr_op == DDI_INTROP_ENABLE) { 763 PDBG(("pciide_enable rc=%d", rc)); 764 } else 765 PDBG(("pciide_disable rc=%d", rc)); 766 #endif /* DEBUG */ 767 return (rc); 768 default: 769 return (DDI_FAILURE); 770 } 771 772 return (DDI_SUCCESS); 773 } 774 775 int 776 pciide_alloc_intr(dev_info_t *dip, dev_info_t *rdip, 777 ddi_intr_handle_impl_t *hdlp, void *result) 778 { 779 struct intrspec *ispec; 780 ddi_intr_handle_impl_t info_hdl; 781 int ret; 782 int free_phdl = 0; 783 apic_get_type_t type_info; 784 785 if (psm_intr_ops == NULL) 786 return (DDI_FAILURE); 787 788 if ((ispec = pciide_get_ispec(dip, rdip, hdlp->ih_inum)) == NULL) 789 return (DDI_FAILURE); 790 791 /* 792 * If the PSM module is "APIX" then pass the request for it 793 * to allocate the vector now. 794 */ 795 bzero(&info_hdl, sizeof (ddi_intr_handle_impl_t)); 796 info_hdl.ih_private = &type_info; 797 if ((*psm_intr_ops)(NULL, &info_hdl, PSM_INTR_OP_APIC_TYPE, NULL) == 798 PSM_SUCCESS && strcmp(type_info.avgi_type, APIC_APIX_NAME) == 0) { 799 if (hdlp->ih_private == NULL) { /* allocate phdl structure */ 800 free_phdl = 1; 801 i_ddi_alloc_intr_phdl(hdlp); 802 } 803 ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec; 804 if (PCIIDE_NATIVE_MODE(rdip)) { 805 rdip = dip; 806 dip = ddi_get_parent(dip); 807 } else { /* get ptr to the root node */ 808 dip = ddi_root_node(); 809 } 810 ret = (*psm_intr_ops)(rdip, hdlp, 811 PSM_INTR_OP_ALLOC_VECTORS, result); 812 if (free_phdl) { /* free up the phdl structure */ 813 free_phdl = 0; 814 i_ddi_free_intr_phdl(hdlp); 815 } 816 } else { 817 /* 818 * No APIX module; fall back to the old scheme where the 819 * interrupt vector is allocated during ddi_enable_intr() call. 820 */ 821 *(int *)result = hdlp->ih_scratch1; 822 ret = DDI_SUCCESS; 823 } 824 825 return (ret); 826 } 827 828 int 829 pciide_free_intr(dev_info_t *dip, dev_info_t *rdip, 830 ddi_intr_handle_impl_t *hdlp) 831 { 832 struct intrspec *ispec; 833 ddi_intr_handle_impl_t info_hdl; 834 apic_get_type_t type_info; 835 836 if (psm_intr_ops == NULL) 837 return (DDI_FAILURE); 838 839 /* 840 * If the PSM module is "APIX" then pass the request for it 841 * to free up the vector now. 842 */ 843 bzero(&info_hdl, sizeof (ddi_intr_handle_impl_t)); 844 info_hdl.ih_private = &type_info; 845 if ((*psm_intr_ops)(NULL, &info_hdl, PSM_INTR_OP_APIC_TYPE, NULL) == 846 PSM_SUCCESS && strcmp(type_info.avgi_type, APIC_APIX_NAME) == 0) { 847 if ((ispec = pciide_get_ispec(dip, rdip, hdlp->ih_inum)) == 848 NULL) 849 return (DDI_FAILURE); 850 ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec; 851 if (PCIIDE_NATIVE_MODE(rdip)) { 852 rdip = dip; 853 dip = ddi_get_parent(dip); 854 } else { /* get ptr to the root node */ 855 dip = ddi_root_node(); 856 } 857 return ((*psm_intr_ops)(rdip, hdlp, 858 PSM_INTR_OP_FREE_VECTORS, NULL)); 859 } 860 861 /* 862 * No APIX module; fall back to the old scheme where 863 * the interrupt vector was already freed during 864 * ddi_disable_intr() call. 865 */ 866 return (DDI_SUCCESS); 867 } 868 869 /* 870 * This is one of the places where controller specific setup needs to be 871 * considered. 872 * At this point the controller was already pre-qualified as a known and 873 * supported pciide controller. 874 * Some controllers do not provide PCI_MASS_IDE sub-class code and IDE 875 * programming interface code but rather PCI_MASS_OTHER sub-class code 876 * without any additional data. 877 * For those controllers IDE programming interface cannot be extracted 878 * from PCI class - we assume that they are pci-native type and we fix 879 * the programming interface used by other functions. 880 * The programming interface byte is set to indicate pci-native mode 881 * for both controllers and the Bus Master DMA capabilitiy of the controller. 882 */ 883 static void 884 pciide_compat_setup(dev_info_t *mydip, dev_info_t *cdip, int dev) 885 { 886 int class_code; 887 int rc = DDI_PROP_SUCCESS; 888 889 class_code = ddi_prop_get_int(DDI_DEV_T_ANY, mydip, 890 DDI_PROP_DONTPASS, "class-code", 0); 891 892 if (((class_code & 0x00FF00) >> 8) == PCI_MASS_IDE) { 893 /* 894 * Controller provides PCI_MASS_IDE sub-class code first 895 * (implied IDE programming interface) 896 */ 897 if ((dev == 0 && !(class_code & PCI_IDE_IF_NATIVE_PRI)) || 898 (dev == 1 && !(class_code & PCI_IDE_IF_NATIVE_SEC))) { 899 rc = ndi_prop_update_int(DDI_DEV_T_NONE, cdip, 900 "compatibility-mode", 1); 901 if (rc != DDI_PROP_SUCCESS) 902 cmn_err(CE_WARN, 903 "pciide prop error %d compat-mode", rc); 904 } 905 } else { 906 /* 907 * Pci-ide controllers not providing PCI_MASS_IDE sub-class are 908 * assumed to be of pci-native type and bus master DMA capable. 909 * Programming interface part of the class-code property is 910 * fixed here. 911 */ 912 class_code &= 0x00ffff00; 913 class_code |= PCI_IDE_IF_BM_CAP_MASK | 914 PCI_IDE_IF_NATIVE_PRI | PCI_IDE_IF_NATIVE_SEC; 915 rc = ddi_prop_update_int(DDI_DEV_T_NONE, mydip, 916 "class-code", class_code); 917 if (rc != DDI_PROP_SUCCESS) 918 cmn_err(CE_WARN, 919 "pciide prop error %d class-code", rc); 920 } 921 } 922 923 924 static int 925 pciide_pre26_rnumber_map(dev_info_t *mydip, int rnumber) 926 { 927 int pri_native; 928 int sec_native; 929 int class_code; 930 931 class_code = ddi_prop_get_int(DDI_DEV_T_ANY, mydip, DDI_PROP_DONTPASS, 932 "class-code", 0); 933 934 pri_native = (class_code & PCI_IDE_IF_NATIVE_PRI) ? TRUE : FALSE; 935 sec_native = (class_code & PCI_IDE_IF_NATIVE_SEC) ? TRUE : FALSE; 936 937 return (pciide_map_rnumber(rnumber, pri_native, sec_native)); 938 939 } 940 941 /* 942 * The canonical order of the reg property tuples for the 943 * Base Address Registers is supposed to be: 944 * 945 * primary controller (BAR 0) 946 * primary controller (BAR 1) 947 * secondary controller (BAR 2) 948 * secondary controller (BAR 3) 949 * bus mastering regs (BAR 4) 950 * 951 * For 2.6, bootconf has been fixed to always generate the 952 * reg property (and assigned-addresses property) tuples 953 * in the above order. 954 * 955 * But in releases prior to 2.6 the order varies depending 956 * on whether compatibility or native mode is being used for 957 * each controller. There ends up being four possible 958 * orders: 959 * 960 * BM, P0, P1, S0, S1 primary compatible, secondary compatible 961 * S0, S1, BM, P0, P1 primary compatible, secondary native 962 * P0, P1, BM, S0, S1 primary native, secondary compatible 963 * P0, P1, S0, S1, BM primary native, secondary native 964 * 965 * where: Px is the primary tuples, Sx the secondary tuples, and 966 * B the Bus Master tuple. 967 * 968 * Here's the results for each of the four states: 969 * 970 * 0, 1, 2, 3, 4 971 * 972 * CC 1, 2, 3, 4, 0 973 * CN 3, 4, 0, 1, 2 974 * NC 0, 1, 3, 4, 2 975 * NN 0, 1, 2, 3, 4 976 * 977 * C = compatible(!native) == 0 978 * N = native == 1 979 * 980 * Here's the transformation matrix: 981 */ 982 983 static int pciide_transform[2][2][5] = { 984 /* P S */ 985 /* [C][C] */ +1, +1, +1, +1, -4, 986 /* [C][N] */ +3, +3, -2, -2, -2, 987 /* [N][C] */ +0, +0, +1, +1, -2, 988 /* [N][N] */ +0, +0, +0, +0, +0 989 }; 990 991 992 static int 993 pciide_map_rnumber(int rnumber, int pri_native, int sec_native) 994 { 995 /* transform flags into indexes */ 996 pri_native = pri_native ? 1 : 0; 997 sec_native = sec_native ? 1 : 0; 998 999 rnumber += pciide_transform[pri_native][sec_native][rnumber]; 1000 return (rnumber); 1001 } 1002