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