pci-ide.c revision 42f87ea29774769e90a36caa2a9075c07dacac50
1N/A * The contents of this file are subject to the terms of the 1N/A * Common Development and Distribution License (the "License"). 1N/A * You may not use this file except in compliance with the License. 1N/A * See the License for the specific language governing permissions 1N/A * and limitations under the License. 1N/A * When distributing Covered Code, include this CDDL HEADER in each 1N/A * If applicable, add the following below this CDDL HEADER, with the 1N/A * fields enclosed by brackets "[]" replaced with your own identifying 1N/A * information: Portions Copyright [yyyy] [name of copyright owner] 1N/A * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 1N/A * Use is subject to license terms. 1N/A * PCI-IDE bus nexus driver 1N/A "compatibility-mode"))
1N/A * Config information 1N/A 0,
/* (*bus_get_eventcookie)(); */ 1N/A 0,
/* (*bus_add_eventcall)(); */ 1N/A 0,
/* (*bus_remove_eventcall)(); */ 1N/A 0,
/* (*bus_post_event)(); */ 1N/A * Module linkage information for the kernel. 1N/A "pciide nexus driver for 'PCI-IDE' 1.26",
1N/A * Make sure bus-mastering is enabled, even if 1N/A * In case of error, return SUCCESS. This is because 1N/A * bus-mastering could be already enabled by BIOS. 1N/A /* Restore our PCI configuration header */ 1N/A * This is a pretty bad thing. However, for some 1N/A * reason it always happens. To further complicate 1N/A * things, it appears if we just ignore this, we 1N/A * properly resume. For now, all I want to do is 1N/A * to generate this message so that it doesn't get 1N/A "Couldn't restore PCI config regs for %s(%p)",
1N/A /* Bus mastering should still be enabled */ 1N/A /* Save our PCI configuration header */ 1N/A /* Don't suspend if we cannot save config regs */ 1N/A * Adjust the rnumbers based on which controller instance 1N/A * is requested; adjust for the 2 tuples per controller. 1N/A PDBG((
"pciide_ctlops invalid rnumber\n"));
PDBG((
"pciide rnumber old %d new %d\n",
* Add 1 to skip over the PCI config space tuple * If it's not tuple #2 pass the adjusted request to my parent * Handle my child's reg-tuple #2 here by splitting my 16 byte * reg-tuple #4 into two 8 byte ranges based on the * the child's controller #. * Allow for the possibility of less than 16 bytes by * by checking what's actually returned for my reg-tuple #4. * IEEE 1275 Working Group Proposal #414 says that the Primary * controller is "ata@0" and the Secondary controller "ata@1". * By the time we get here, boot Bootconf (2.6+) has created devinfo * nodes with the appropriate "reg", "assigned-addresses" and "interrupts" * properites on the pci-ide node and both ide child nodes. * In compatibility mode the "reg" and "assigned-addresses" properties * of the pci-ide node are set up like this: * (addr-hi addr-mid addr-low size-hi size-low) * reg= assigned-addresses=00000000.00000000.00000000.00000000.00000000 * 81000000.00000000.000001f0.00000000.00000008 * 81000000.00000000.000003f4.00000000.00000004 * 81000000.00000000,00000170.00000000.00000008 * 81000000.00000000,00000374.00000000.00000004 * 01000020.00000000,-[BAR4]-.00000000.00000010 * In native PCI mode the "reg" and "assigned-addresses" properties * would be set up like this: * reg= assigned-addresses=00000000.00000000.00000000.00000000.00000000 * 01000010.00000000.-[BAR0]-.00000000.00000008 * 01000014,00000000.-[BAR1]-.00000000.00000004 * 01000018.00000000.-[BAR2]-.00000000.00000008 * 0100001c.00000000.-[BAR3]-.00000000.00000004 * 01000020.00000000.-[BAR4]-.00000000.00000010 * In both modes the child nodes simply have the following: * 2. primary controller (compatibility mode) * 3. secondary controller * The pciide_bus_map() function is responsible for turning requests * to map primary or secondary controller rnumbers into mapping requests * of the appropriate regspec on the pci-ide node. PDBG((
"pciide_initchild\n"));
* Set the address portion of the node name based on * the controller number (0 or 1) from the 'reg' property. PDBG((
"pciide_intchild prop error\n"));
* copy the controller number and * free the memory allocated by ddi_prop_lookup_int_array * I only support two controllers per device, determine * which this one is and set its unit address. PDBG((
"pciide_initchild bad dev\n"));
* determine if this instance is running in native or compat mode /* interrupts property is required */ * In compatibility mode, dev 0 should always be * IRQ 14 and dev 1 is IRQ 15. If for some reason * this needs to be changed, do it via the interrupts /* setup compatibility mode interrupts */ PDBG((
"pciide_initchild bad intr\n"));
PDBG((
"pciide_initchild okay\n"));
PDBG((
"pciide_bus_map\n"));
* Adjust the rnumbers based on which controller instance * is being mapped; adjust for the 2 tuples per controller. * split the 16 I/O ports into two 8 port ranges PDBG((
"pciide_bus_map offset\n"));
PDBG((
"pciide_bus_map default\n"));
PDBG((
"pciide rnumber old %d new %d\n",
* Add 1 to skip over the PCI config space tuple * pass the adjusted request to my parent PDBG((
"pciide_get_ispec\n"));
* Native mode PCI-IDE controllers share the parent's * Compatibility mode PCI-IDE controllers have their * own intrspec which specifies ISA IRQ 14 or 15. PDBG((
"pciide_get_ispec okay\n"));
/* Else compatibility mode, use the ISA IRQ */ PDBG((
"pciide_get_ispec null\n"));
/* validate the interrupt number */ PDBG((
"pciide_get_inum\n"));
PDBG((
"pciide_get_ispec ok\n"));
PDBG((
"pciide_get_pri\n"));
PDBG((
"pciide_get_pri null\n"));
PDBG((
"pciide_get_pri ok\n"));
/* check if the intrspec has been initialized */ PDBG((
"pciide_get_pri ok2\n"));
/* Use a default of level 5 */ * If there's an interrupt-priorities property, use it to * over-ride the default interrupt priority. PDBG((
"pciide_get_pri ok3\n"));
PDBG((
"pciide_intr_ops: dip %p rdip %p op %x hdlp %p\n",
}
else {
/* get ptr to the root node */ PDBG((
"pciide_enable rc=%d",
rc));
PDBG((
"pciide_disable rc=%d",
rc));
* This is one of the places where controller specific setup needs to be * At this point the controller was already pre-qualified as a known and * supported pciide controller. * Some controllers do not provide PCI_MASS_IDE sub-class code and IDE * programming interface code but rather PCI_MASS_OTHER sub-class code * without any additional data. * For those controllers IDE programming interface cannot be extracted * from PCI class - we assume that they are pci-native type and we fix * the programming interface used by other functions. * The programming interface byte is set to indicate pci-native mode * for both controllers and the Bus Master DMA capabilitiy of the controller. * Controller provides PCI_MASS_IDE sub-class code first * (implied IDE programming interface) "compatibility-mode",
1);
"pciide prop error %d compat-mode",
rc);
* Pci-ide controllers not providing PCI_MASS_IDE sub-class are * assumed to be of pci-native type and bus master DMA capable. * Programming interface part of the class-code property is "pciide prop error %d class-code",
rc);
* The canonical order of the reg property tuples for the * Base Address Registers is supposed to be: * primary controller (BAR 0) * primary controller (BAR 1) * secondary controller (BAR 2) * secondary controller (BAR 3) * bus mastering regs (BAR 4) * For 2.6, bootconf has been fixed to always generate the * reg property (and assigned-addresses property) tuples * But in releases prior to 2.6 the order varies depending * on whether compatibility or native mode is being used for * each controller. There ends up being four possible * BM, P0, P1, S0, S1 primary compatible, secondary compatible * S0, S1, BM, P0, P1 primary compatible, secondary native * P0, P1, BM, S0, S1 primary native, secondary compatible * P0, P1, S0, S1, BM primary native, secondary native * where: Px is the primary tuples, Sx the secondary tuples, and * B the Bus Master tuple. * Here's the results for each of the four states: * C = compatible(!native) == 0 * Here's the transformation matrix: /* [C][C] */ +
1, +
1, +
1, +
1, -
4,
/* [C][N] */ +
3, +
3, -
2, -
2, -
2,
/* [N][C] */ +0, +0, +
1, +
1, -
2,
/* [N][N] */ +0, +0, +0, +0, +0
/* transform flags into indexes */