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