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