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