17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5a54f81fbSanish * Common Development and Distribution License (the "License"). 6a54f81fbSanish * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 225cd376e8SJimmy Vetayases * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 24*cd21e7c5SGarrett D'Amore /* 25*cd21e7c5SGarrett D'Amore * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved. 26*cd21e7c5SGarrett D'Amore */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * PCI-IDE bus nexus driver 307c478bd9Sstevel@tonic-gate */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <sys/types.h> 337c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 347c478bd9Sstevel@tonic-gate #include <sys/conf.h> 357c478bd9Sstevel@tonic-gate #include <sys/errno.h> 367c478bd9Sstevel@tonic-gate #include <sys/debug.h> 377c478bd9Sstevel@tonic-gate #include <sys/ddidmareq.h> 387c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 397c478bd9Sstevel@tonic-gate #include <sys/dma_engine.h> 407c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 417c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 427c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 4342f87ea2SGuoli Shu #include <sys/sunndi.h> 447a364d25Sschwartz #include <sys/mach_intr.h> 457c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 467c478bd9Sstevel@tonic-gate #include <sys/pci.h> 477c478bd9Sstevel@tonic-gate #include <sys/promif.h> 487c478bd9Sstevel@tonic-gate #include <sys/pci_intr_lib.h> 497ff178cdSJimmy Vetayases #include <sys/apic.h> 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate int pciide_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 522df1fe9cSrandyf int pciide_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate #define PCIIDE_NATIVE_MODE(dip) \ 557c478bd9Sstevel@tonic-gate (!ddi_prop_exists(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \ 567c478bd9Sstevel@tonic-gate "compatibility-mode")) 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate #define PCIIDE_PRE26(dip) \ 597c478bd9Sstevel@tonic-gate ddi_prop_exists(DDI_DEV_T_ANY, (dip), 0, "ignore-hardware-nodes") 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate #define PCI_IDE_IF_BM_CAP_MASK 0x80 627c478bd9Sstevel@tonic-gate 63192f7333Smrj #define PCIIDE_PDSIZE (sizeof (struct ddi_parent_private_data) + \ 64192f7333Smrj sizeof (struct intrspec)) 65192f7333Smrj 667c478bd9Sstevel@tonic-gate #ifdef DEBUG 677c478bd9Sstevel@tonic-gate static int pci_ide_debug = 0; 687c478bd9Sstevel@tonic-gate #define PDBG(fmt) \ 697c478bd9Sstevel@tonic-gate if (pci_ide_debug) { \ 707c478bd9Sstevel@tonic-gate prom_printf fmt; \ 717c478bd9Sstevel@tonic-gate } 727c478bd9Sstevel@tonic-gate #else 737c478bd9Sstevel@tonic-gate #define PDBG(fmt) 747c478bd9Sstevel@tonic-gate #endif 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate #ifndef TRUE 777c478bd9Sstevel@tonic-gate #define TRUE 1 787c478bd9Sstevel@tonic-gate #endif 797c478bd9Sstevel@tonic-gate #ifndef FALSE 807c478bd9Sstevel@tonic-gate #define FALSE 0 817c478bd9Sstevel@tonic-gate #endif 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate /* 847c478bd9Sstevel@tonic-gate * bus_ops functions 857c478bd9Sstevel@tonic-gate */ 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate static int pciide_bus_map(dev_info_t *dip, dev_info_t *rdip, 887c478bd9Sstevel@tonic-gate ddi_map_req_t *mp, off_t offset, off_t len, 897c478bd9Sstevel@tonic-gate caddr_t *vaddrp); 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate static int pciide_ddi_ctlops(dev_info_t *dip, dev_info_t *rdip, 927c478bd9Sstevel@tonic-gate ddi_ctl_enum_t ctlop, void *arg, 937c478bd9Sstevel@tonic-gate void *result); 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate static int pciide_get_pri(dev_info_t *dip, dev_info_t *rdip, 967c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp, int *pri); 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate static int pciide_intr_ops(dev_info_t *dip, dev_info_t *rdip, 997c478bd9Sstevel@tonic-gate ddi_intr_op_t intr_op, 1007c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp, void *result); 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate static struct intrspec *pciide_get_ispec(dev_info_t *dip, dev_info_t *rdip, 1037c478bd9Sstevel@tonic-gate int inum); 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /* 1067c478bd9Sstevel@tonic-gate * Local Functions 1077c478bd9Sstevel@tonic-gate */ 1087c478bd9Sstevel@tonic-gate static int pciide_initchild(dev_info_t *mydip, dev_info_t *cdip); 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate static void pciide_compat_setup(dev_info_t *mydip, dev_info_t *cdip, 1117c478bd9Sstevel@tonic-gate int dev); 1127c478bd9Sstevel@tonic-gate static int pciide_pre26_rnumber_map(dev_info_t *mydip, int rnumber); 1137c478bd9Sstevel@tonic-gate static int pciide_map_rnumber(int canonical_rnumber, int pri_native, 1147c478bd9Sstevel@tonic-gate int sec_native); 1157ff178cdSJimmy Vetayases static int pciide_alloc_intr(dev_info_t *, dev_info_t *, 1167ff178cdSJimmy Vetayases ddi_intr_handle_impl_t *, void *); 1177ff178cdSJimmy Vetayases static int pciide_free_intr(dev_info_t *, dev_info_t *, 1187ff178cdSJimmy Vetayases ddi_intr_handle_impl_t *); 1197c478bd9Sstevel@tonic-gate 1207ff178cdSJimmy Vetayases extern int (*psm_intr_ops)(dev_info_t *, ddi_intr_handle_impl_t *, 1217ff178cdSJimmy Vetayases psm_intr_op_t, int *); 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate /* 1247c478bd9Sstevel@tonic-gate * Config information 1257c478bd9Sstevel@tonic-gate */ 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate struct bus_ops pciide_bus_ops = { 1287c478bd9Sstevel@tonic-gate BUSO_REV, 1297c478bd9Sstevel@tonic-gate pciide_bus_map, 1307c478bd9Sstevel@tonic-gate 0, 1317c478bd9Sstevel@tonic-gate 0, 1327c478bd9Sstevel@tonic-gate 0, 1337c478bd9Sstevel@tonic-gate i_ddi_map_fault, 134*cd21e7c5SGarrett D'Amore 0, 1357c478bd9Sstevel@tonic-gate ddi_dma_allochdl, 1367c478bd9Sstevel@tonic-gate ddi_dma_freehdl, 1377c478bd9Sstevel@tonic-gate ddi_dma_bindhdl, 1387c478bd9Sstevel@tonic-gate ddi_dma_unbindhdl, 1397c478bd9Sstevel@tonic-gate ddi_dma_flush, 1407c478bd9Sstevel@tonic-gate ddi_dma_win, 1417c478bd9Sstevel@tonic-gate ddi_dma_mctl, 1427c478bd9Sstevel@tonic-gate pciide_ddi_ctlops, 1437c478bd9Sstevel@tonic-gate ddi_bus_prop_op, 1447c478bd9Sstevel@tonic-gate 0, /* (*bus_get_eventcookie)(); */ 1457c478bd9Sstevel@tonic-gate 0, /* (*bus_add_eventcall)(); */ 1467c478bd9Sstevel@tonic-gate 0, /* (*bus_remove_eventcall)(); */ 1477c478bd9Sstevel@tonic-gate 0, /* (*bus_post_event)(); */ 1487c478bd9Sstevel@tonic-gate 0, 1497c478bd9Sstevel@tonic-gate 0, 1507c478bd9Sstevel@tonic-gate 0, 1517c478bd9Sstevel@tonic-gate 0, 1527c478bd9Sstevel@tonic-gate 0, 1537c478bd9Sstevel@tonic-gate 0, 1547c478bd9Sstevel@tonic-gate 0, 1557c478bd9Sstevel@tonic-gate 0, 1567c478bd9Sstevel@tonic-gate pciide_intr_ops 1577c478bd9Sstevel@tonic-gate }; 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate struct dev_ops pciide_ops = { 1607c478bd9Sstevel@tonic-gate DEVO_REV, /* devo_rev, */ 1617c478bd9Sstevel@tonic-gate 0, /* refcnt */ 1627c478bd9Sstevel@tonic-gate ddi_no_info, /* info */ 1637c478bd9Sstevel@tonic-gate nulldev, /* identify */ 1647c478bd9Sstevel@tonic-gate nulldev, /* probe */ 1657c478bd9Sstevel@tonic-gate pciide_attach, /* attach */ 1662df1fe9cSrandyf pciide_detach, /* detach */ 1677c478bd9Sstevel@tonic-gate nodev, /* reset */ 1687c478bd9Sstevel@tonic-gate (struct cb_ops *)0, /* driver operations */ 16919397407SSherry Moore &pciide_bus_ops, /* bus operations */ 17019397407SSherry Moore NULL, /* power */ 17119397407SSherry Moore ddi_quiesce_not_needed, /* quiesce */ 1727c478bd9Sstevel@tonic-gate }; 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate /* 1757c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 1767c478bd9Sstevel@tonic-gate */ 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 1797c478bd9Sstevel@tonic-gate &mod_driverops, /* Type of module. This is PCI-IDE bus driver */ 18019397407SSherry Moore "pciide nexus driver for 'PCI-IDE' 1.26", 1817c478bd9Sstevel@tonic-gate &pciide_ops, /* driver ops */ 1827c478bd9Sstevel@tonic-gate }; 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 1857c478bd9Sstevel@tonic-gate MODREV_1, 1867c478bd9Sstevel@tonic-gate &modldrv, 1877c478bd9Sstevel@tonic-gate NULL 1887c478bd9Sstevel@tonic-gate }; 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate int 1927c478bd9Sstevel@tonic-gate _init(void) 1937c478bd9Sstevel@tonic-gate { 1947c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate int 1987c478bd9Sstevel@tonic-gate _fini(void) 1997c478bd9Sstevel@tonic-gate { 2007c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate int 2047c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 2057c478bd9Sstevel@tonic-gate { 2067c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate int 2107c478bd9Sstevel@tonic-gate pciide_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2117c478bd9Sstevel@tonic-gate { 2127c478bd9Sstevel@tonic-gate uint16_t cmdreg; 2137c478bd9Sstevel@tonic-gate ddi_acc_handle_t conf_hdl = NULL; 2147c478bd9Sstevel@tonic-gate int rc; 2157c478bd9Sstevel@tonic-gate 2162df1fe9cSrandyf switch (cmd) { 2172df1fe9cSrandyf case DDI_ATTACH: 2187c478bd9Sstevel@tonic-gate /* 2197c478bd9Sstevel@tonic-gate * Make sure bus-mastering is enabled, even if 2207c478bd9Sstevel@tonic-gate * BIOS didn't. 2217c478bd9Sstevel@tonic-gate */ 222ae0b9099Smrj rc = pci_config_setup(dip, &conf_hdl); 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate /* 2257c478bd9Sstevel@tonic-gate * In case of error, return SUCCESS. This is because 2267c478bd9Sstevel@tonic-gate * bus-mastering could be already enabled by BIOS. 2277c478bd9Sstevel@tonic-gate */ 2287c478bd9Sstevel@tonic-gate if (rc != DDI_SUCCESS) 2297c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 2307c478bd9Sstevel@tonic-gate 231ae0b9099Smrj cmdreg = pci_config_get16(conf_hdl, PCI_CONF_COMM); 2327c478bd9Sstevel@tonic-gate if ((cmdreg & PCI_COMM_ME) == 0) { 233ae0b9099Smrj pci_config_put16(conf_hdl, PCI_CONF_COMM, 2347c478bd9Sstevel@tonic-gate cmdreg | PCI_COMM_ME); 2357c478bd9Sstevel@tonic-gate } 236ae0b9099Smrj pci_config_teardown(&conf_hdl); 2377c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 2382df1fe9cSrandyf 2392df1fe9cSrandyf case DDI_RESUME: 2402df1fe9cSrandyf /* Restore our PCI configuration header */ 2412df1fe9cSrandyf if (pci_restore_config_regs(dip) != DDI_SUCCESS) { 2422df1fe9cSrandyf /* 2432df1fe9cSrandyf * XXXX 2442df1fe9cSrandyf * This is a pretty bad thing. However, for some 2452df1fe9cSrandyf * reason it always happens. To further complicate 2462df1fe9cSrandyf * things, it appears if we just ignore this, we 2472df1fe9cSrandyf * properly resume. For now, all I want to do is 2482df1fe9cSrandyf * to generate this message so that it doesn't get 2492df1fe9cSrandyf * forgotten. 2502df1fe9cSrandyf */ 2512df1fe9cSrandyf cmn_err(CE_WARN, 2522df1fe9cSrandyf "Couldn't restore PCI config regs for %s(%p)", 2532df1fe9cSrandyf ddi_node_name(dip), (void *) dip); 2542df1fe9cSrandyf } 2552df1fe9cSrandyf #ifdef DEBUG 2562df1fe9cSrandyf /* Bus mastering should still be enabled */ 2572df1fe9cSrandyf if (pci_config_setup(dip, &conf_hdl) != DDI_SUCCESS) 2582df1fe9cSrandyf return (DDI_FAILURE); 2592df1fe9cSrandyf cmdreg = pci_config_get16(conf_hdl, PCI_CONF_COMM); 2602df1fe9cSrandyf ASSERT((cmdreg & PCI_COMM_ME) != 0); 2612df1fe9cSrandyf pci_config_teardown(&conf_hdl); 2622df1fe9cSrandyf #endif 2632df1fe9cSrandyf return (DDI_SUCCESS); 2642df1fe9cSrandyf } 2652df1fe9cSrandyf 2667c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate 2692df1fe9cSrandyf /*ARGSUSED*/ 2702df1fe9cSrandyf int 2712df1fe9cSrandyf pciide_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2722df1fe9cSrandyf { 2732df1fe9cSrandyf switch (cmd) { 2742df1fe9cSrandyf case DDI_DETACH: 2752df1fe9cSrandyf return (DDI_SUCCESS); 2762df1fe9cSrandyf case DDI_SUSPEND: 2772df1fe9cSrandyf /* Save our PCI configuration header */ 2782df1fe9cSrandyf if (pci_save_config_regs(dip) != DDI_SUCCESS) { 2792df1fe9cSrandyf /* Don't suspend if we cannot save config regs */ 2802df1fe9cSrandyf return (DDI_FAILURE); 2812df1fe9cSrandyf } 2822df1fe9cSrandyf return (DDI_SUCCESS); 2832df1fe9cSrandyf } 2842df1fe9cSrandyf return (DDI_FAILURE); 2852df1fe9cSrandyf } 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2887c478bd9Sstevel@tonic-gate static int 2897c478bd9Sstevel@tonic-gate pciide_ddi_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop, 2907c478bd9Sstevel@tonic-gate void *arg, void *result) 2917c478bd9Sstevel@tonic-gate { 292192f7333Smrj dev_info_t *cdip; 293192f7333Smrj int controller; 294192f7333Smrj void *pdptr; 295192f7333Smrj int rnumber; 2967c478bd9Sstevel@tonic-gate off_t tmp; 297192f7333Smrj int rc; 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate PDBG(("pciide_bus_ctl\n")); 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate switch (ctlop) { 3027c478bd9Sstevel@tonic-gate case DDI_CTLOPS_INITCHILD: 303192f7333Smrj cdip = (dev_info_t *)arg; 304192f7333Smrj return (pciide_initchild(dip, cdip)); 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate case DDI_CTLOPS_UNINITCHILD: 307192f7333Smrj cdip = (dev_info_t *)arg; 308192f7333Smrj pdptr = ddi_get_parent_data(cdip); 309192f7333Smrj ddi_set_parent_data(cdip, NULL); 310192f7333Smrj ddi_set_name_addr(cdip, NULL); 311192f7333Smrj kmem_free(pdptr, PCIIDE_PDSIZE); 312192f7333Smrj return (DDI_SUCCESS); 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate case DDI_CTLOPS_NREGS: 3157c478bd9Sstevel@tonic-gate *(int *)result = 3; 3167c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate case DDI_CTLOPS_REGSIZE: 3197c478bd9Sstevel@tonic-gate /* 3207c478bd9Sstevel@tonic-gate * Adjust the rnumbers based on which controller instance 3217c478bd9Sstevel@tonic-gate * is requested; adjust for the 2 tuples per controller. 3227c478bd9Sstevel@tonic-gate */ 3237c478bd9Sstevel@tonic-gate if (strcmp("0", ddi_get_name_addr(rdip)) == 0) 3247c478bd9Sstevel@tonic-gate controller = 0; 3257c478bd9Sstevel@tonic-gate else 3267c478bd9Sstevel@tonic-gate controller = 1; 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate switch (rnumber = *(int *)arg) { 3307c478bd9Sstevel@tonic-gate case 0: 3317c478bd9Sstevel@tonic-gate case 1: 3327c478bd9Sstevel@tonic-gate rnumber += (2 * controller); 3337c478bd9Sstevel@tonic-gate break; 3347c478bd9Sstevel@tonic-gate case 2: 3357c478bd9Sstevel@tonic-gate rnumber = 4; 3367c478bd9Sstevel@tonic-gate break; 3377c478bd9Sstevel@tonic-gate default: 3387c478bd9Sstevel@tonic-gate PDBG(("pciide_ctlops invalid rnumber\n")); 3397c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate if (PCIIDE_PRE26(dip)) { 3447c478bd9Sstevel@tonic-gate int old_rnumber; 3457c478bd9Sstevel@tonic-gate int new_rnumber; 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate old_rnumber = rnumber; 3487c478bd9Sstevel@tonic-gate new_rnumber 3497c478bd9Sstevel@tonic-gate = pciide_pre26_rnumber_map(dip, old_rnumber); 3507c478bd9Sstevel@tonic-gate PDBG(("pciide rnumber old %d new %d\n", 3517c478bd9Sstevel@tonic-gate old_rnumber, new_rnumber)); 3527c478bd9Sstevel@tonic-gate rnumber = new_rnumber; 3537c478bd9Sstevel@tonic-gate } 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate /* 3567c478bd9Sstevel@tonic-gate * Add 1 to skip over the PCI config space tuple 3577c478bd9Sstevel@tonic-gate */ 3587c478bd9Sstevel@tonic-gate rnumber++; 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate /* 3617c478bd9Sstevel@tonic-gate * If it's not tuple #2 pass the adjusted request to my parent 3627c478bd9Sstevel@tonic-gate */ 3637c478bd9Sstevel@tonic-gate if (*(int *)arg != 2) { 3647c478bd9Sstevel@tonic-gate return (ddi_ctlops(dip, dip, ctlop, &rnumber, result)); 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate /* 3687c478bd9Sstevel@tonic-gate * Handle my child's reg-tuple #2 here by splitting my 16 byte 3697c478bd9Sstevel@tonic-gate * reg-tuple #4 into two 8 byte ranges based on the 3707c478bd9Sstevel@tonic-gate * the child's controller #. 3717c478bd9Sstevel@tonic-gate */ 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate tmp = 8; 3747c478bd9Sstevel@tonic-gate rc = ddi_ctlops(dip, dip, ctlop, &rnumber, &tmp); 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate /* 3777c478bd9Sstevel@tonic-gate * Allow for the possibility of less than 16 bytes by 3787c478bd9Sstevel@tonic-gate * by checking what's actually returned for my reg-tuple #4. 3797c478bd9Sstevel@tonic-gate */ 3807c478bd9Sstevel@tonic-gate if (controller == 1) { 3817c478bd9Sstevel@tonic-gate if (tmp < 8) 3827c478bd9Sstevel@tonic-gate tmp = 0; 3837c478bd9Sstevel@tonic-gate else 3847c478bd9Sstevel@tonic-gate tmp -= 8; 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate if (tmp > 8) 3877c478bd9Sstevel@tonic-gate tmp = 8; 3887c478bd9Sstevel@tonic-gate *(off_t *)result = tmp; 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate return (rc); 3917c478bd9Sstevel@tonic-gate 3920f1b305eSSeth Goldberg case DDI_CTLOPS_ATTACH: 3930f1b305eSSeth Goldberg case DDI_CTLOPS_DETACH: 3940f1b305eSSeth Goldberg /* 3950f1b305eSSeth Goldberg * Don't pass child ide ATTACH/DETACH to parent 3960f1b305eSSeth Goldberg */ 3970f1b305eSSeth Goldberg return (DDI_SUCCESS); 3980f1b305eSSeth Goldberg 3997c478bd9Sstevel@tonic-gate default: 4007c478bd9Sstevel@tonic-gate return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate } 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate /* 4057c478bd9Sstevel@tonic-gate * IEEE 1275 Working Group Proposal #414 says that the Primary 4067c478bd9Sstevel@tonic-gate * controller is "ata@0" and the Secondary controller "ata@1". 4077c478bd9Sstevel@tonic-gate * 4087c478bd9Sstevel@tonic-gate * By the time we get here, boot Bootconf (2.6+) has created devinfo 4097c478bd9Sstevel@tonic-gate * nodes with the appropriate "reg", "assigned-addresses" and "interrupts" 4107c478bd9Sstevel@tonic-gate * properites on the pci-ide node and both ide child nodes. 4117c478bd9Sstevel@tonic-gate * 4127c478bd9Sstevel@tonic-gate * In compatibility mode the "reg" and "assigned-addresses" properties 4137c478bd9Sstevel@tonic-gate * of the pci-ide node are set up like this: 4147c478bd9Sstevel@tonic-gate * 4157c478bd9Sstevel@tonic-gate * 1. PCI-IDE Nexus 4167c478bd9Sstevel@tonic-gate * 4177c478bd9Sstevel@tonic-gate * interrupts=0 4187c478bd9Sstevel@tonic-gate * (addr-hi addr-mid addr-low size-hi size-low) 4197c478bd9Sstevel@tonic-gate * reg= assigned-addresses=00000000.00000000.00000000.00000000.00000000 4207c478bd9Sstevel@tonic-gate * 81000000.00000000.000001f0.00000000.00000008 4217c478bd9Sstevel@tonic-gate * 81000000.00000000.000003f4.00000000.00000004 4227c478bd9Sstevel@tonic-gate * 81000000.00000000,00000170.00000000.00000008 4237c478bd9Sstevel@tonic-gate * 81000000.00000000,00000374.00000000.00000004 4247c478bd9Sstevel@tonic-gate * 01000020.00000000,-[BAR4]-.00000000.00000010 4257c478bd9Sstevel@tonic-gate * 4267c478bd9Sstevel@tonic-gate * In native PCI mode the "reg" and "assigned-addresses" properties 4277c478bd9Sstevel@tonic-gate * would be set up like this: 4287c478bd9Sstevel@tonic-gate * 4297c478bd9Sstevel@tonic-gate * 2. PCI-IDE Nexus 4307c478bd9Sstevel@tonic-gate * 4317c478bd9Sstevel@tonic-gate * interrupts=0 4327c478bd9Sstevel@tonic-gate * reg= assigned-addresses=00000000.00000000.00000000.00000000.00000000 4337c478bd9Sstevel@tonic-gate * 01000010.00000000.-[BAR0]-.00000000.00000008 4347c478bd9Sstevel@tonic-gate * 01000014,00000000.-[BAR1]-.00000000.00000004 4357c478bd9Sstevel@tonic-gate * 01000018.00000000.-[BAR2]-.00000000.00000008 4367c478bd9Sstevel@tonic-gate * 0100001c.00000000.-[BAR3]-.00000000.00000004 4377c478bd9Sstevel@tonic-gate * 01000020.00000000.-[BAR4]-.00000000.00000010 4387c478bd9Sstevel@tonic-gate * 4397c478bd9Sstevel@tonic-gate * 4407c478bd9Sstevel@tonic-gate * In both modes the child nodes simply have the following: 4417c478bd9Sstevel@tonic-gate * 4427c478bd9Sstevel@tonic-gate * 2. primary controller (compatibility mode) 4437c478bd9Sstevel@tonic-gate * 4447c478bd9Sstevel@tonic-gate * interrupts=14 4457c478bd9Sstevel@tonic-gate * reg=00000000 4467c478bd9Sstevel@tonic-gate * 4477c478bd9Sstevel@tonic-gate * 3. secondary controller 4487c478bd9Sstevel@tonic-gate * 4497c478bd9Sstevel@tonic-gate * interrupts=15 4507c478bd9Sstevel@tonic-gate * reg=00000001 4517c478bd9Sstevel@tonic-gate * 4527c478bd9Sstevel@tonic-gate * The pciide_bus_map() function is responsible for turning requests 4537c478bd9Sstevel@tonic-gate * to map primary or secondary controller rnumbers into mapping requests 4547c478bd9Sstevel@tonic-gate * of the appropriate regspec on the pci-ide node. 4557c478bd9Sstevel@tonic-gate * 4567c478bd9Sstevel@tonic-gate */ 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate static int 4597c478bd9Sstevel@tonic-gate pciide_initchild(dev_info_t *mydip, dev_info_t *cdip) 4607c478bd9Sstevel@tonic-gate { 4617c478bd9Sstevel@tonic-gate struct ddi_parent_private_data *pdptr; 4627c478bd9Sstevel@tonic-gate struct intrspec *ispecp; 4637c478bd9Sstevel@tonic-gate int vec; 4647c478bd9Sstevel@tonic-gate int *rp; 4657c478bd9Sstevel@tonic-gate uint_t proplen; 4667c478bd9Sstevel@tonic-gate char name[80]; 4677c478bd9Sstevel@tonic-gate int dev; 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate PDBG(("pciide_initchild\n")); 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate /* 4727c478bd9Sstevel@tonic-gate * Set the address portion of the node name based on 4737c478bd9Sstevel@tonic-gate * the controller number (0 or 1) from the 'reg' property. 4747c478bd9Sstevel@tonic-gate */ 4757c478bd9Sstevel@tonic-gate if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, 4767c478bd9Sstevel@tonic-gate "reg", &rp, (uint_t *)&proplen) != DDI_PROP_SUCCESS) { 4777c478bd9Sstevel@tonic-gate PDBG(("pciide_intchild prop error\n")); 4787c478bd9Sstevel@tonic-gate return (DDI_NOT_WELL_FORMED); 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate /* 4827c478bd9Sstevel@tonic-gate * copy the controller number and 4837c478bd9Sstevel@tonic-gate * free the memory allocated by ddi_prop_lookup_int_array 4847c478bd9Sstevel@tonic-gate */ 4857c478bd9Sstevel@tonic-gate dev = *rp; 4867c478bd9Sstevel@tonic-gate ddi_prop_free(rp); 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate /* 4897c478bd9Sstevel@tonic-gate * I only support two controllers per device, determine 4907c478bd9Sstevel@tonic-gate * which this one is and set its unit address. 4917c478bd9Sstevel@tonic-gate */ 4927c478bd9Sstevel@tonic-gate if (dev > 1) { 4937c478bd9Sstevel@tonic-gate PDBG(("pciide_initchild bad dev\n")); 4947c478bd9Sstevel@tonic-gate return (DDI_NOT_WELL_FORMED); 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate (void) sprintf(name, "%d", dev); 4977c478bd9Sstevel@tonic-gate ddi_set_name_addr(cdip, name); 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate /* 5007c478bd9Sstevel@tonic-gate * determine if this instance is running in native or compat mode 5017c478bd9Sstevel@tonic-gate */ 5027c478bd9Sstevel@tonic-gate pciide_compat_setup(mydip, cdip, dev); 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate /* interrupts property is required */ 5057c478bd9Sstevel@tonic-gate if (PCIIDE_NATIVE_MODE(cdip)) { 5067c478bd9Sstevel@tonic-gate vec = 1; 5077c478bd9Sstevel@tonic-gate } else { 5087c478bd9Sstevel@tonic-gate /* 5097c478bd9Sstevel@tonic-gate * In compatibility mode, dev 0 should always be 5107c478bd9Sstevel@tonic-gate * IRQ 14 and dev 1 is IRQ 15. If for some reason 5117c478bd9Sstevel@tonic-gate * this needs to be changed, do it via the interrupts 5127c478bd9Sstevel@tonic-gate * property in the ata.conf file. 5137c478bd9Sstevel@tonic-gate */ 5147c478bd9Sstevel@tonic-gate vec = ddi_prop_get_int(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, 5157c478bd9Sstevel@tonic-gate "interrupts", -1); 5167c478bd9Sstevel@tonic-gate if (vec == -1) { 5177c478bd9Sstevel@tonic-gate /* setup compatibility mode interrupts */ 5187c478bd9Sstevel@tonic-gate if (dev == 0) { 5197c478bd9Sstevel@tonic-gate vec = 14; 5207c478bd9Sstevel@tonic-gate } else if (dev == 1) { 5217c478bd9Sstevel@tonic-gate vec = 15; 5227c478bd9Sstevel@tonic-gate } else { 5237c478bd9Sstevel@tonic-gate PDBG(("pciide_initchild bad intr\n")); 5247c478bd9Sstevel@tonic-gate return (DDI_NOT_WELL_FORMED); 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate 529192f7333Smrj pdptr = kmem_zalloc(PCIIDE_PDSIZE, KM_SLEEP); 5307c478bd9Sstevel@tonic-gate ispecp = (struct intrspec *)(pdptr + 1); 5317c478bd9Sstevel@tonic-gate pdptr->par_nintr = 1; 5327c478bd9Sstevel@tonic-gate pdptr->par_intr = ispecp; 5337c478bd9Sstevel@tonic-gate ispecp->intrspec_vec = vec; 5347c478bd9Sstevel@tonic-gate ddi_set_parent_data(cdip, pdptr); 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate PDBG(("pciide_initchild okay\n")); 5377c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate static int 5417c478bd9Sstevel@tonic-gate pciide_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 5427c478bd9Sstevel@tonic-gate off_t offset, off_t len, caddr_t *vaddrp) 5437c478bd9Sstevel@tonic-gate { 5447c478bd9Sstevel@tonic-gate dev_info_t *pdip; 5457c478bd9Sstevel@tonic-gate int rnumber = mp->map_obj.rnumber; 5467c478bd9Sstevel@tonic-gate int controller; 5477c478bd9Sstevel@tonic-gate int rc; 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate PDBG(("pciide_bus_map\n")); 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate if (strcmp("0", ddi_get_name_addr(rdip)) == 0) 5527c478bd9Sstevel@tonic-gate controller = 0; 5537c478bd9Sstevel@tonic-gate else 5547c478bd9Sstevel@tonic-gate controller = 1; 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate /* 5577c478bd9Sstevel@tonic-gate * Adjust the rnumbers based on which controller instance 5587c478bd9Sstevel@tonic-gate * is being mapped; adjust for the 2 tuples per controller. 5597c478bd9Sstevel@tonic-gate */ 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate switch (rnumber) { 5627c478bd9Sstevel@tonic-gate case 0: 5637c478bd9Sstevel@tonic-gate case 1: 5647c478bd9Sstevel@tonic-gate mp->map_obj.rnumber += (controller * 2); 5657c478bd9Sstevel@tonic-gate break; 5667c478bd9Sstevel@tonic-gate case 2: 5677c478bd9Sstevel@tonic-gate /* 5687c478bd9Sstevel@tonic-gate * split the 16 I/O ports into two 8 port ranges 5697c478bd9Sstevel@tonic-gate */ 5707c478bd9Sstevel@tonic-gate mp->map_obj.rnumber = 4; 5717c478bd9Sstevel@tonic-gate if (offset + len > 8) { 5727c478bd9Sstevel@tonic-gate PDBG(("pciide_bus_map offset\n")); 5737c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate if (len == 0) 5767c478bd9Sstevel@tonic-gate len = 8 - offset; 5777c478bd9Sstevel@tonic-gate offset += 8 * controller; 5787c478bd9Sstevel@tonic-gate break; 5797c478bd9Sstevel@tonic-gate default: 5807c478bd9Sstevel@tonic-gate PDBG(("pciide_bus_map default\n")); 5817c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate if (PCIIDE_PRE26(dip)) { 5857c478bd9Sstevel@tonic-gate int old_rnumber; 5867c478bd9Sstevel@tonic-gate int new_rnumber; 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate old_rnumber = mp->map_obj.rnumber; 5897c478bd9Sstevel@tonic-gate new_rnumber = pciide_pre26_rnumber_map(dip, old_rnumber); 5907c478bd9Sstevel@tonic-gate PDBG(("pciide rnumber old %d new %d\n", 5917c478bd9Sstevel@tonic-gate old_rnumber, new_rnumber)); 5927c478bd9Sstevel@tonic-gate mp->map_obj.rnumber = new_rnumber; 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate /* 5967c478bd9Sstevel@tonic-gate * Add 1 to skip over the PCI config space tuple 5977c478bd9Sstevel@tonic-gate */ 5987c478bd9Sstevel@tonic-gate mp->map_obj.rnumber++; 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate /* 6027c478bd9Sstevel@tonic-gate * pass the adjusted request to my parent 6037c478bd9Sstevel@tonic-gate */ 6047c478bd9Sstevel@tonic-gate pdip = ddi_get_parent(dip); 6057c478bd9Sstevel@tonic-gate rc = ((*(DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)) 6067c478bd9Sstevel@tonic-gate (pdip, dip, mp, offset, len, vaddrp)); 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate PDBG(("pciide_bus_map %s\n", rc == DDI_SUCCESS ? "okay" : "!ok")); 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate return (rc); 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate static struct intrspec * 6157c478bd9Sstevel@tonic-gate pciide_get_ispec(dev_info_t *dip, dev_info_t *rdip, int inumber) 6167c478bd9Sstevel@tonic-gate { 6177c478bd9Sstevel@tonic-gate struct ddi_parent_private_data *ppdptr; 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate PDBG(("pciide_get_ispec\n")); 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate /* 6227c478bd9Sstevel@tonic-gate * Native mode PCI-IDE controllers share the parent's 6237c478bd9Sstevel@tonic-gate * PCI interrupt line. 6247c478bd9Sstevel@tonic-gate * 6257c478bd9Sstevel@tonic-gate * Compatibility mode PCI-IDE controllers have their 6267c478bd9Sstevel@tonic-gate * own intrspec which specifies ISA IRQ 14 or 15. 6277c478bd9Sstevel@tonic-gate * 6287c478bd9Sstevel@tonic-gate */ 6297c478bd9Sstevel@tonic-gate if (PCIIDE_NATIVE_MODE(rdip)) { 6307c478bd9Sstevel@tonic-gate ddi_intrspec_t is; 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate is = pci_intx_get_ispec(dip, dip, inumber); 6337c478bd9Sstevel@tonic-gate PDBG(("pciide_get_ispec okay\n")); 6347c478bd9Sstevel@tonic-gate return ((struct intrspec *)is); 6357c478bd9Sstevel@tonic-gate } 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate /* Else compatibility mode, use the ISA IRQ */ 6387c478bd9Sstevel@tonic-gate if ((ppdptr = ddi_get_parent_data(rdip)) == NULL) { 6397c478bd9Sstevel@tonic-gate PDBG(("pciide_get_ispec null\n")); 6407c478bd9Sstevel@tonic-gate return (NULL); 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate 6437c478bd9Sstevel@tonic-gate /* validate the interrupt number */ 6447c478bd9Sstevel@tonic-gate if (inumber >= ppdptr->par_nintr) { 6457c478bd9Sstevel@tonic-gate PDBG(("pciide_get_inum\n")); 6467c478bd9Sstevel@tonic-gate return (NULL); 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate PDBG(("pciide_get_ispec ok\n")); 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate return ((struct intrspec *)&ppdptr->par_intr[inumber]); 6527c478bd9Sstevel@tonic-gate } 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate static int 6557c478bd9Sstevel@tonic-gate pciide_get_pri(dev_info_t *dip, dev_info_t *rdip, 6567c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp, int *pri) 6577c478bd9Sstevel@tonic-gate { 6587c478bd9Sstevel@tonic-gate struct intrspec *ispecp; 6597c478bd9Sstevel@tonic-gate int *intpriorities; 6607c478bd9Sstevel@tonic-gate uint_t num_intpriorities; 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate PDBG(("pciide_get_pri\n")); 6637c478bd9Sstevel@tonic-gate 6647c478bd9Sstevel@tonic-gate if ((ispecp = pciide_get_ispec(dip, rdip, hdlp->ih_inum)) == NULL) { 6657c478bd9Sstevel@tonic-gate PDBG(("pciide_get_pri null\n")); 6667c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 6677c478bd9Sstevel@tonic-gate } 6687c478bd9Sstevel@tonic-gate 6697c478bd9Sstevel@tonic-gate if (PCIIDE_NATIVE_MODE(rdip)) { 6707c478bd9Sstevel@tonic-gate *pri = ispecp->intrspec_pri; 6717c478bd9Sstevel@tonic-gate PDBG(("pciide_get_pri ok\n")); 6727c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 6737c478bd9Sstevel@tonic-gate } 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate /* check if the intrspec has been initialized */ 6767c478bd9Sstevel@tonic-gate if (ispecp->intrspec_pri != 0) { 6777c478bd9Sstevel@tonic-gate *pri = ispecp->intrspec_pri; 6787c478bd9Sstevel@tonic-gate PDBG(("pciide_get_pri ok2\n")); 6797c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 6807c478bd9Sstevel@tonic-gate } 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate /* Use a default of level 5 */ 6837c478bd9Sstevel@tonic-gate ispecp->intrspec_pri = 5; 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate /* 6867c478bd9Sstevel@tonic-gate * If there's an interrupt-priorities property, use it to 6877c478bd9Sstevel@tonic-gate * over-ride the default interrupt priority. 6887c478bd9Sstevel@tonic-gate */ 6897c478bd9Sstevel@tonic-gate if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS, 6907c478bd9Sstevel@tonic-gate "interrupt-priorities", &intpriorities, &num_intpriorities) == 6917c478bd9Sstevel@tonic-gate DDI_PROP_SUCCESS) { 6927c478bd9Sstevel@tonic-gate if (hdlp->ih_inum < num_intpriorities) 6937c478bd9Sstevel@tonic-gate ispecp->intrspec_pri = intpriorities[hdlp->ih_inum]; 6947c478bd9Sstevel@tonic-gate ddi_prop_free(intpriorities); 6957c478bd9Sstevel@tonic-gate } 6967c478bd9Sstevel@tonic-gate *pri = ispecp->intrspec_pri; 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate PDBG(("pciide_get_pri ok3\n")); 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate static int 7047c478bd9Sstevel@tonic-gate pciide_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, 7057c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp, void *result) 7067c478bd9Sstevel@tonic-gate { 7077c478bd9Sstevel@tonic-gate struct intrspec *ispecp; 7087c478bd9Sstevel@tonic-gate int rc; 7097c478bd9Sstevel@tonic-gate int pri = 0; 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate PDBG(("pciide_intr_ops: dip %p rdip %p op %x hdlp %p\n", 7127c478bd9Sstevel@tonic-gate (void *)dip, (void *)rdip, intr_op, (void *)hdlp)); 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate switch (intr_op) { 7157c478bd9Sstevel@tonic-gate case DDI_INTROP_SUPPORTED_TYPES: 7167c478bd9Sstevel@tonic-gate *(int *)result = DDI_INTR_TYPE_FIXED; 7177c478bd9Sstevel@tonic-gate break; 7187c478bd9Sstevel@tonic-gate case DDI_INTROP_GETCAP: 7190dc36b40Sanish *(int *)result = DDI_INTR_FLAG_LEVEL; 7207c478bd9Sstevel@tonic-gate break; 7217c478bd9Sstevel@tonic-gate case DDI_INTROP_NINTRS: 722a54f81fbSanish case DDI_INTROP_NAVAIL: 723a54f81fbSanish *(int *)result = (!PCIIDE_NATIVE_MODE(rdip)) ? 724a54f81fbSanish i_ddi_get_intx_nintrs(rdip) : 1; 7257c478bd9Sstevel@tonic-gate break; 7267c478bd9Sstevel@tonic-gate case DDI_INTROP_ALLOC: 7277ff178cdSJimmy Vetayases return (pciide_alloc_intr(dip, rdip, hdlp, result)); 7287c478bd9Sstevel@tonic-gate case DDI_INTROP_FREE: 7297ff178cdSJimmy Vetayases return (pciide_free_intr(dip, rdip, hdlp)); 7307c478bd9Sstevel@tonic-gate case DDI_INTROP_GETPRI: 7317c478bd9Sstevel@tonic-gate if (pciide_get_pri(dip, rdip, hdlp, &pri) != DDI_SUCCESS) { 7327c478bd9Sstevel@tonic-gate *(int *)result = 0; 7337c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 7347c478bd9Sstevel@tonic-gate } 7357c478bd9Sstevel@tonic-gate *(int *)result = pri; 7367c478bd9Sstevel@tonic-gate break; 7377c478bd9Sstevel@tonic-gate case DDI_INTROP_ADDISR: 7387c478bd9Sstevel@tonic-gate if ((ispecp = pciide_get_ispec(dip, rdip, hdlp->ih_inum)) == 7397c478bd9Sstevel@tonic-gate NULL) 7407c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 7417a364d25Sschwartz ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispecp; 7427c478bd9Sstevel@tonic-gate ispecp->intrspec_func = hdlp->ih_cb_func; 7437c478bd9Sstevel@tonic-gate break; 7447c478bd9Sstevel@tonic-gate case DDI_INTROP_REMISR: 7457c478bd9Sstevel@tonic-gate if ((ispecp = pciide_get_ispec(dip, rdip, hdlp->ih_inum)) == 7467c478bd9Sstevel@tonic-gate NULL) 7477c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 7487c478bd9Sstevel@tonic-gate ispecp->intrspec_func = (uint_t (*)()) 0; 7497c478bd9Sstevel@tonic-gate break; 7507c478bd9Sstevel@tonic-gate case DDI_INTROP_ENABLE: 7517c478bd9Sstevel@tonic-gate /* FALLTHRU */ 7527c478bd9Sstevel@tonic-gate case DDI_INTROP_DISABLE: 7537c478bd9Sstevel@tonic-gate if (PCIIDE_NATIVE_MODE(rdip)) { 7547c478bd9Sstevel@tonic-gate rdip = dip; 7557c478bd9Sstevel@tonic-gate dip = ddi_get_parent(dip); 7567c478bd9Sstevel@tonic-gate } else { /* get ptr to the root node */ 7577c478bd9Sstevel@tonic-gate dip = ddi_root_node(); 7587c478bd9Sstevel@tonic-gate } 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate rc = (*(DEVI(dip)->devi_ops->devo_bus_ops->bus_intr_op))(dip, 7617c478bd9Sstevel@tonic-gate rdip, intr_op, hdlp, result); 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate #ifdef DEBUG 7647c478bd9Sstevel@tonic-gate if (intr_op == DDI_INTROP_ENABLE) { 7657c478bd9Sstevel@tonic-gate PDBG(("pciide_enable rc=%d", rc)); 7667c478bd9Sstevel@tonic-gate } else 7677c478bd9Sstevel@tonic-gate PDBG(("pciide_disable rc=%d", rc)); 7687c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 7697c478bd9Sstevel@tonic-gate return (rc); 7707c478bd9Sstevel@tonic-gate default: 7717c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 7727c478bd9Sstevel@tonic-gate } 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 7757c478bd9Sstevel@tonic-gate } 7767c478bd9Sstevel@tonic-gate 7777ff178cdSJimmy Vetayases int 7787ff178cdSJimmy Vetayases pciide_alloc_intr(dev_info_t *dip, dev_info_t *rdip, 7797ff178cdSJimmy Vetayases ddi_intr_handle_impl_t *hdlp, void *result) 7807ff178cdSJimmy Vetayases { 7817ff178cdSJimmy Vetayases struct intrspec *ispec; 7827ff178cdSJimmy Vetayases ddi_intr_handle_impl_t info_hdl; 7837ff178cdSJimmy Vetayases int ret; 7847ff178cdSJimmy Vetayases int free_phdl = 0; 7857ff178cdSJimmy Vetayases apic_get_type_t type_info; 7867ff178cdSJimmy Vetayases 7877ff178cdSJimmy Vetayases if (psm_intr_ops == NULL) 7887ff178cdSJimmy Vetayases return (DDI_FAILURE); 7897ff178cdSJimmy Vetayases 7907ff178cdSJimmy Vetayases if ((ispec = pciide_get_ispec(dip, rdip, hdlp->ih_inum)) == NULL) 7917ff178cdSJimmy Vetayases return (DDI_FAILURE); 7927ff178cdSJimmy Vetayases 7937ff178cdSJimmy Vetayases /* 7947ff178cdSJimmy Vetayases * If the PSM module is "APIX" then pass the request for it 7957ff178cdSJimmy Vetayases * to allocate the vector now. 7967ff178cdSJimmy Vetayases */ 7977ff178cdSJimmy Vetayases bzero(&info_hdl, sizeof (ddi_intr_handle_impl_t)); 7987ff178cdSJimmy Vetayases info_hdl.ih_private = &type_info; 7997ff178cdSJimmy Vetayases if ((*psm_intr_ops)(NULL, &info_hdl, PSM_INTR_OP_APIC_TYPE, NULL) == 8007ff178cdSJimmy Vetayases PSM_SUCCESS && strcmp(type_info.avgi_type, APIC_APIX_NAME) == 0) { 8017ff178cdSJimmy Vetayases if (hdlp->ih_private == NULL) { /* allocate phdl structure */ 8027ff178cdSJimmy Vetayases free_phdl = 1; 8037ff178cdSJimmy Vetayases i_ddi_alloc_intr_phdl(hdlp); 8047ff178cdSJimmy Vetayases } 8057ff178cdSJimmy Vetayases ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec; 8067ff178cdSJimmy Vetayases if (PCIIDE_NATIVE_MODE(rdip)) { 8077ff178cdSJimmy Vetayases rdip = dip; 8087ff178cdSJimmy Vetayases dip = ddi_get_parent(dip); 8097ff178cdSJimmy Vetayases } else { /* get ptr to the root node */ 8107ff178cdSJimmy Vetayases dip = ddi_root_node(); 8117ff178cdSJimmy Vetayases } 8127ff178cdSJimmy Vetayases ret = (*psm_intr_ops)(rdip, hdlp, 8137ff178cdSJimmy Vetayases PSM_INTR_OP_ALLOC_VECTORS, result); 8147ff178cdSJimmy Vetayases if (free_phdl) { /* free up the phdl structure */ 8157ff178cdSJimmy Vetayases free_phdl = 0; 8167ff178cdSJimmy Vetayases i_ddi_free_intr_phdl(hdlp); 8177ff178cdSJimmy Vetayases } 8187ff178cdSJimmy Vetayases } else { 8197ff178cdSJimmy Vetayases /* 8207ff178cdSJimmy Vetayases * No APIX module; fall back to the old scheme where the 8217ff178cdSJimmy Vetayases * interrupt vector is allocated during ddi_enable_intr() call. 8227ff178cdSJimmy Vetayases */ 8237ff178cdSJimmy Vetayases *(int *)result = hdlp->ih_scratch1; 8247ff178cdSJimmy Vetayases ret = DDI_SUCCESS; 8257ff178cdSJimmy Vetayases } 8267ff178cdSJimmy Vetayases 8277ff178cdSJimmy Vetayases return (ret); 8287ff178cdSJimmy Vetayases } 8297ff178cdSJimmy Vetayases 8307ff178cdSJimmy Vetayases int 8317ff178cdSJimmy Vetayases pciide_free_intr(dev_info_t *dip, dev_info_t *rdip, 8327ff178cdSJimmy Vetayases ddi_intr_handle_impl_t *hdlp) 8337ff178cdSJimmy Vetayases { 8347ff178cdSJimmy Vetayases struct intrspec *ispec; 8357ff178cdSJimmy Vetayases ddi_intr_handle_impl_t info_hdl; 8367ff178cdSJimmy Vetayases apic_get_type_t type_info; 8377ff178cdSJimmy Vetayases 8387ff178cdSJimmy Vetayases if (psm_intr_ops == NULL) 8397ff178cdSJimmy Vetayases return (DDI_FAILURE); 8407ff178cdSJimmy Vetayases 8417ff178cdSJimmy Vetayases /* 8427ff178cdSJimmy Vetayases * If the PSM module is "APIX" then pass the request for it 8437ff178cdSJimmy Vetayases * to free up the vector now. 8447ff178cdSJimmy Vetayases */ 8457ff178cdSJimmy Vetayases bzero(&info_hdl, sizeof (ddi_intr_handle_impl_t)); 8467ff178cdSJimmy Vetayases info_hdl.ih_private = &type_info; 8477ff178cdSJimmy Vetayases if ((*psm_intr_ops)(NULL, &info_hdl, PSM_INTR_OP_APIC_TYPE, NULL) == 8487ff178cdSJimmy Vetayases PSM_SUCCESS && strcmp(type_info.avgi_type, APIC_APIX_NAME) == 0) { 8497ff178cdSJimmy Vetayases if ((ispec = pciide_get_ispec(dip, rdip, hdlp->ih_inum)) == 8507ff178cdSJimmy Vetayases NULL) 8517ff178cdSJimmy Vetayases return (DDI_FAILURE); 8527ff178cdSJimmy Vetayases ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec; 8537ff178cdSJimmy Vetayases if (PCIIDE_NATIVE_MODE(rdip)) { 8547ff178cdSJimmy Vetayases rdip = dip; 8557ff178cdSJimmy Vetayases dip = ddi_get_parent(dip); 8567ff178cdSJimmy Vetayases } else { /* get ptr to the root node */ 8577ff178cdSJimmy Vetayases dip = ddi_root_node(); 8587ff178cdSJimmy Vetayases } 8597ff178cdSJimmy Vetayases return ((*psm_intr_ops)(rdip, hdlp, 8607ff178cdSJimmy Vetayases PSM_INTR_OP_FREE_VECTORS, NULL)); 8617ff178cdSJimmy Vetayases } 8627ff178cdSJimmy Vetayases 8637ff178cdSJimmy Vetayases /* 8647ff178cdSJimmy Vetayases * No APIX module; fall back to the old scheme where 8657ff178cdSJimmy Vetayases * the interrupt vector was already freed during 8667ff178cdSJimmy Vetayases * ddi_disable_intr() call. 8677ff178cdSJimmy Vetayases */ 8687ff178cdSJimmy Vetayases return (DDI_SUCCESS); 8697ff178cdSJimmy Vetayases } 8707ff178cdSJimmy Vetayases 8717c478bd9Sstevel@tonic-gate /* 8727c478bd9Sstevel@tonic-gate * This is one of the places where controller specific setup needs to be 8737c478bd9Sstevel@tonic-gate * considered. 8747c478bd9Sstevel@tonic-gate * At this point the controller was already pre-qualified as a known and 8757c478bd9Sstevel@tonic-gate * supported pciide controller. 8767c478bd9Sstevel@tonic-gate * Some controllers do not provide PCI_MASS_IDE sub-class code and IDE 8777c478bd9Sstevel@tonic-gate * programming interface code but rather PCI_MASS_OTHER sub-class code 8787c478bd9Sstevel@tonic-gate * without any additional data. 8797c478bd9Sstevel@tonic-gate * For those controllers IDE programming interface cannot be extracted 8807c478bd9Sstevel@tonic-gate * from PCI class - we assume that they are pci-native type and we fix 8817c478bd9Sstevel@tonic-gate * the programming interface used by other functions. 8827c478bd9Sstevel@tonic-gate * The programming interface byte is set to indicate pci-native mode 8837c478bd9Sstevel@tonic-gate * for both controllers and the Bus Master DMA capabilitiy of the controller. 8847c478bd9Sstevel@tonic-gate */ 8857c478bd9Sstevel@tonic-gate static void 8867c478bd9Sstevel@tonic-gate pciide_compat_setup(dev_info_t *mydip, dev_info_t *cdip, int dev) 8877c478bd9Sstevel@tonic-gate { 8887c478bd9Sstevel@tonic-gate int class_code; 8897c478bd9Sstevel@tonic-gate int rc = DDI_PROP_SUCCESS; 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate class_code = ddi_prop_get_int(DDI_DEV_T_ANY, mydip, 8927c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "class-code", 0); 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate if (((class_code & 0x00FF00) >> 8) == PCI_MASS_IDE) { 8957c478bd9Sstevel@tonic-gate /* 8967c478bd9Sstevel@tonic-gate * Controller provides PCI_MASS_IDE sub-class code first 8977c478bd9Sstevel@tonic-gate * (implied IDE programming interface) 8987c478bd9Sstevel@tonic-gate */ 8997c478bd9Sstevel@tonic-gate if ((dev == 0 && !(class_code & PCI_IDE_IF_NATIVE_PRI)) || 9007c478bd9Sstevel@tonic-gate (dev == 1 && !(class_code & PCI_IDE_IF_NATIVE_SEC))) { 90142f87ea2SGuoli Shu rc = ndi_prop_update_int(DDI_DEV_T_NONE, cdip, 9027c478bd9Sstevel@tonic-gate "compatibility-mode", 1); 9037c478bd9Sstevel@tonic-gate if (rc != DDI_PROP_SUCCESS) 9047c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 9057c478bd9Sstevel@tonic-gate "pciide prop error %d compat-mode", rc); 9067c478bd9Sstevel@tonic-gate } 9077c478bd9Sstevel@tonic-gate } else { 9087c478bd9Sstevel@tonic-gate /* 9097c478bd9Sstevel@tonic-gate * Pci-ide controllers not providing PCI_MASS_IDE sub-class are 9107c478bd9Sstevel@tonic-gate * assumed to be of pci-native type and bus master DMA capable. 9117c478bd9Sstevel@tonic-gate * Programming interface part of the class-code property is 9127c478bd9Sstevel@tonic-gate * fixed here. 9137c478bd9Sstevel@tonic-gate */ 9147c478bd9Sstevel@tonic-gate class_code &= 0x00ffff00; 9157c478bd9Sstevel@tonic-gate class_code |= PCI_IDE_IF_BM_CAP_MASK | 9167c478bd9Sstevel@tonic-gate PCI_IDE_IF_NATIVE_PRI | PCI_IDE_IF_NATIVE_SEC; 9177c478bd9Sstevel@tonic-gate rc = ddi_prop_update_int(DDI_DEV_T_NONE, mydip, 9187c478bd9Sstevel@tonic-gate "class-code", class_code); 9197c478bd9Sstevel@tonic-gate if (rc != DDI_PROP_SUCCESS) 9207c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 9217c478bd9Sstevel@tonic-gate "pciide prop error %d class-code", rc); 9227c478bd9Sstevel@tonic-gate } 9237c478bd9Sstevel@tonic-gate } 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate static int 9277c478bd9Sstevel@tonic-gate pciide_pre26_rnumber_map(dev_info_t *mydip, int rnumber) 9287c478bd9Sstevel@tonic-gate { 9297c478bd9Sstevel@tonic-gate int pri_native; 9307c478bd9Sstevel@tonic-gate int sec_native; 9317c478bd9Sstevel@tonic-gate int class_code; 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate class_code = ddi_prop_get_int(DDI_DEV_T_ANY, mydip, DDI_PROP_DONTPASS, 9347c478bd9Sstevel@tonic-gate "class-code", 0); 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate pri_native = (class_code & PCI_IDE_IF_NATIVE_PRI) ? TRUE : FALSE; 9377c478bd9Sstevel@tonic-gate sec_native = (class_code & PCI_IDE_IF_NATIVE_SEC) ? TRUE : FALSE; 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate return (pciide_map_rnumber(rnumber, pri_native, sec_native)); 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate } 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate /* 9447c478bd9Sstevel@tonic-gate * The canonical order of the reg property tuples for the 9457c478bd9Sstevel@tonic-gate * Base Address Registers is supposed to be: 9467c478bd9Sstevel@tonic-gate * 9477c478bd9Sstevel@tonic-gate * primary controller (BAR 0) 9487c478bd9Sstevel@tonic-gate * primary controller (BAR 1) 9497c478bd9Sstevel@tonic-gate * secondary controller (BAR 2) 9507c478bd9Sstevel@tonic-gate * secondary controller (BAR 3) 9517c478bd9Sstevel@tonic-gate * bus mastering regs (BAR 4) 9527c478bd9Sstevel@tonic-gate * 9537c478bd9Sstevel@tonic-gate * For 2.6, bootconf has been fixed to always generate the 9547c478bd9Sstevel@tonic-gate * reg property (and assigned-addresses property) tuples 9557c478bd9Sstevel@tonic-gate * in the above order. 9567c478bd9Sstevel@tonic-gate * 9577c478bd9Sstevel@tonic-gate * But in releases prior to 2.6 the order varies depending 9587c478bd9Sstevel@tonic-gate * on whether compatibility or native mode is being used for 9597c478bd9Sstevel@tonic-gate * each controller. There ends up being four possible 9607c478bd9Sstevel@tonic-gate * orders: 9617c478bd9Sstevel@tonic-gate * 9627c478bd9Sstevel@tonic-gate * BM, P0, P1, S0, S1 primary compatible, secondary compatible 9637c478bd9Sstevel@tonic-gate * S0, S1, BM, P0, P1 primary compatible, secondary native 9647c478bd9Sstevel@tonic-gate * P0, P1, BM, S0, S1 primary native, secondary compatible 9657c478bd9Sstevel@tonic-gate * P0, P1, S0, S1, BM primary native, secondary native 9667c478bd9Sstevel@tonic-gate * 9677c478bd9Sstevel@tonic-gate * where: Px is the primary tuples, Sx the secondary tuples, and 9687c478bd9Sstevel@tonic-gate * B the Bus Master tuple. 9697c478bd9Sstevel@tonic-gate * 9707c478bd9Sstevel@tonic-gate * Here's the results for each of the four states: 9717c478bd9Sstevel@tonic-gate * 9727c478bd9Sstevel@tonic-gate * 0, 1, 2, 3, 4 9737c478bd9Sstevel@tonic-gate * 9747c478bd9Sstevel@tonic-gate * CC 1, 2, 3, 4, 0 9757c478bd9Sstevel@tonic-gate * CN 3, 4, 0, 1, 2 9767c478bd9Sstevel@tonic-gate * NC 0, 1, 3, 4, 2 9777c478bd9Sstevel@tonic-gate * NN 0, 1, 2, 3, 4 9787c478bd9Sstevel@tonic-gate * 9797c478bd9Sstevel@tonic-gate * C = compatible(!native) == 0 9807c478bd9Sstevel@tonic-gate * N = native == 1 9817c478bd9Sstevel@tonic-gate * 9827c478bd9Sstevel@tonic-gate * Here's the transformation matrix: 9837c478bd9Sstevel@tonic-gate */ 9847c478bd9Sstevel@tonic-gate 9857c478bd9Sstevel@tonic-gate static int pciide_transform[2][2][5] = { 9867c478bd9Sstevel@tonic-gate /* P S */ 9877c478bd9Sstevel@tonic-gate /* [C][C] */ +1, +1, +1, +1, -4, 9887c478bd9Sstevel@tonic-gate /* [C][N] */ +3, +3, -2, -2, -2, 9897c478bd9Sstevel@tonic-gate /* [N][C] */ +0, +0, +1, +1, -2, 9907c478bd9Sstevel@tonic-gate /* [N][N] */ +0, +0, +0, +0, +0 9917c478bd9Sstevel@tonic-gate }; 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate static int 9957c478bd9Sstevel@tonic-gate pciide_map_rnumber(int rnumber, int pri_native, int sec_native) 9967c478bd9Sstevel@tonic-gate { 9977c478bd9Sstevel@tonic-gate /* transform flags into indexes */ 9987c478bd9Sstevel@tonic-gate pri_native = pri_native ? 1 : 0; 9997c478bd9Sstevel@tonic-gate sec_native = sec_native ? 1 : 0; 10007c478bd9Sstevel@tonic-gate 10017c478bd9Sstevel@tonic-gate rnumber += pciide_transform[pri_native][sec_native][rnumber]; 10027c478bd9Sstevel@tonic-gate return (rnumber); 10037c478bd9Sstevel@tonic-gate } 1004