4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
25 * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
29 * PCI-IDE bus nexus driver
32 #include <sys/types.h>
33 #include <sys/cmn_err.h>
35 #include <sys/errno.h>
36 #include <sys/debug.h>
37 #include <sys/ddidmareq.h>
38 #include <sys/ddi_impldefs.h>
39 #include <sys/dma_engine.h>
40 #include <sys/modctl.h>
42 #include <sys/sunddi.h>
43 #include <sys/sunndi.h>
44 #include <sys/mach_intr.h>
47 #include <sys/promif.h>
48 #include <sys/pci_intr_lib.h>
51 int pciide_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
);
52 int pciide_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
);
54 #define PCIIDE_NATIVE_MODE(dip) \
55 (!ddi_prop_exists(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \
56 "compatibility-mode"))
58 #define PCIIDE_PRE26(dip) \
59 ddi_prop_exists(DDI_DEV_T_ANY, (dip), 0, "ignore-hardware-nodes")
61 #define PCI_IDE_IF_BM_CAP_MASK 0x80
63 #define PCIIDE_PDSIZE (sizeof (struct ddi_parent_private_data) + \
64 sizeof (struct intrspec))
67 static int pci_ide_debug
= 0;
69 if (pci_ide_debug) { \
87 static int pciide_bus_map(dev_info_t
*dip
, dev_info_t
*rdip
,
88 ddi_map_req_t
*mp
, off_t offset
, off_t len
,
91 static int pciide_ddi_ctlops(dev_info_t
*dip
, dev_info_t
*rdip
,
92 ddi_ctl_enum_t ctlop
, void *arg
,
95 static int pciide_get_pri(dev_info_t
*dip
, dev_info_t
*rdip
,
96 ddi_intr_handle_impl_t
*hdlp
, int *pri
);
98 static int pciide_intr_ops(dev_info_t
*dip
, dev_info_t
*rdip
,
99 ddi_intr_op_t intr_op
,
100 ddi_intr_handle_impl_t
*hdlp
, void *result
);
102 static struct intrspec
*pciide_get_ispec(dev_info_t
*dip
, dev_info_t
*rdip
,
108 static int pciide_initchild(dev_info_t
*mydip
, dev_info_t
*cdip
);
110 static void pciide_compat_setup(dev_info_t
*mydip
, dev_info_t
*cdip
,
112 static int pciide_pre26_rnumber_map(dev_info_t
*mydip
, int rnumber
);
113 static int pciide_map_rnumber(int canonical_rnumber
, int pri_native
,
115 static int pciide_alloc_intr(dev_info_t
*, dev_info_t
*,
116 ddi_intr_handle_impl_t
*, void *);
117 static int pciide_free_intr(dev_info_t
*, dev_info_t
*,
118 ddi_intr_handle_impl_t
*);
120 extern int (*psm_intr_ops
)(dev_info_t
*, ddi_intr_handle_impl_t
*,
121 psm_intr_op_t
, int *);
127 struct bus_ops pciide_bus_ops
= {
144 0, /* (*bus_get_eventcookie)(); */
145 0, /* (*bus_add_eventcall)(); */
146 0, /* (*bus_remove_eventcall)(); */
147 0, /* (*bus_post_event)(); */
159 struct dev_ops pciide_ops
= {
160 DEVO_REV
, /* devo_rev, */
162 ddi_no_info
, /* info */
163 nulldev
, /* identify */
165 pciide_attach
, /* attach */
166 pciide_detach
, /* detach */
168 NULL
, /* driver operations */
169 &pciide_bus_ops
, /* bus operations */
171 ddi_quiesce_not_needed
, /* quiesce */
175 * Module linkage information for the kernel.
178 static struct modldrv modldrv
= {
179 &mod_driverops
, /* Type of module. This is PCI-IDE bus driver */
180 "pciide nexus driver for 'PCI-IDE' 1.26",
181 &pciide_ops
, /* driver ops */
184 static struct modlinkage modlinkage
= {
194 return (mod_install(&modlinkage
));
200 return (mod_remove(&modlinkage
));
204 _info(struct modinfo
*modinfop
)
206 return (mod_info(&modlinkage
, modinfop
));
210 pciide_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
213 ddi_acc_handle_t conf_hdl
= NULL
;
219 * Make sure bus-mastering is enabled, even if
222 rc
= pci_config_setup(dip
, &conf_hdl
);
225 * In case of error, return SUCCESS. This is because
226 * bus-mastering could be already enabled by BIOS.
228 if (rc
!= DDI_SUCCESS
)
229 return (DDI_SUCCESS
);
231 cmdreg
= pci_config_get16(conf_hdl
, PCI_CONF_COMM
);
232 if ((cmdreg
& PCI_COMM_ME
) == 0) {
233 pci_config_put16(conf_hdl
, PCI_CONF_COMM
,
234 cmdreg
| PCI_COMM_ME
);
236 pci_config_teardown(&conf_hdl
);
237 return (DDI_SUCCESS
);
240 /* Restore our PCI configuration header */
241 if (pci_restore_config_regs(dip
) != DDI_SUCCESS
) {
244 * This is a pretty bad thing. However, for some
245 * reason it always happens. To further complicate
246 * things, it appears if we just ignore this, we
247 * properly resume. For now, all I want to do is
248 * to generate this message so that it doesn't get
252 "Couldn't restore PCI config regs for %s(%p)",
253 ddi_node_name(dip
), (void *) dip
);
256 /* Bus mastering should still be enabled */
257 if (pci_config_setup(dip
, &conf_hdl
) != DDI_SUCCESS
)
258 return (DDI_FAILURE
);
259 cmdreg
= pci_config_get16(conf_hdl
, PCI_CONF_COMM
);
260 ASSERT((cmdreg
& PCI_COMM_ME
) != 0);
261 pci_config_teardown(&conf_hdl
);
263 return (DDI_SUCCESS
);
266 return (DDI_FAILURE
);
271 pciide_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
275 return (DDI_SUCCESS
);
277 /* Save our PCI configuration header */
278 if (pci_save_config_regs(dip
) != DDI_SUCCESS
) {
279 /* Don't suspend if we cannot save config regs */
280 return (DDI_FAILURE
);
282 return (DDI_SUCCESS
);
284 return (DDI_FAILURE
);
289 pciide_ddi_ctlops(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_ctl_enum_t ctlop
,
290 void *arg
, void *result
)
299 PDBG(("pciide_bus_ctl\n"));
302 case DDI_CTLOPS_INITCHILD
:
303 cdip
= (dev_info_t
*)arg
;
304 return (pciide_initchild(dip
, cdip
));
306 case DDI_CTLOPS_UNINITCHILD
:
307 cdip
= (dev_info_t
*)arg
;
308 pdptr
= ddi_get_parent_data(cdip
);
309 ddi_set_parent_data(cdip
, NULL
);
310 ddi_set_name_addr(cdip
, NULL
);
311 kmem_free(pdptr
, PCIIDE_PDSIZE
);
312 return (DDI_SUCCESS
);
314 case DDI_CTLOPS_NREGS
:
316 return (DDI_SUCCESS
);
318 case DDI_CTLOPS_REGSIZE
:
320 * Adjust the rnumbers based on which controller instance
321 * is requested; adjust for the 2 tuples per controller.
323 if (strcmp("0", ddi_get_name_addr(rdip
)) == 0)
329 switch (rnumber
= *(int *)arg
) {
332 rnumber
+= (2 * controller
);
338 PDBG(("pciide_ctlops invalid rnumber\n"));
339 return (DDI_FAILURE
);
343 if (PCIIDE_PRE26(dip
)) {
347 old_rnumber
= rnumber
;
349 = pciide_pre26_rnumber_map(dip
, old_rnumber
);
350 PDBG(("pciide rnumber old %d new %d\n",
351 old_rnumber
, new_rnumber
));
352 rnumber
= new_rnumber
;
356 * Add 1 to skip over the PCI config space tuple
361 * If it's not tuple #2 pass the adjusted request to my parent
363 if (*(int *)arg
!= 2) {
364 return (ddi_ctlops(dip
, dip
, ctlop
, &rnumber
, result
));
368 * Handle my child's reg-tuple #2 here by splitting my 16 byte
369 * reg-tuple #4 into two 8 byte ranges based on the
370 * the child's controller #.
374 rc
= ddi_ctlops(dip
, dip
, ctlop
, &rnumber
, &tmp
);
377 * Allow for the possibility of less than 16 bytes by
378 * by checking what's actually returned for my reg-tuple #4.
380 if (controller
== 1) {
388 *(off_t
*)result
= tmp
;
392 case DDI_CTLOPS_ATTACH
:
393 case DDI_CTLOPS_DETACH
:
395 * Don't pass child ide ATTACH/DETACH to parent
397 return (DDI_SUCCESS
);
400 return (ddi_ctlops(dip
, rdip
, ctlop
, arg
, result
));
405 * IEEE 1275 Working Group Proposal #414 says that the Primary
406 * controller is "ata@0" and the Secondary controller "ata@1".
408 * By the time we get here, boot Bootconf (2.6+) has created devinfo
409 * nodes with the appropriate "reg", "assigned-addresses" and "interrupts"
410 * properites on the pci-ide node and both ide child nodes.
412 * In compatibility mode the "reg" and "assigned-addresses" properties
413 * of the pci-ide node are set up like this:
418 * (addr-hi addr-mid addr-low size-hi size-low)
419 * reg= assigned-addresses=00000000.00000000.00000000.00000000.00000000
420 * 81000000.00000000.000001f0.00000000.00000008
421 * 81000000.00000000.000003f4.00000000.00000004
422 * 81000000.00000000,00000170.00000000.00000008
423 * 81000000.00000000,00000374.00000000.00000004
424 * 01000020.00000000,-[BAR4]-.00000000.00000010
426 * In native PCI mode the "reg" and "assigned-addresses" properties
427 * would be set up like this:
432 * reg= assigned-addresses=00000000.00000000.00000000.00000000.00000000
433 * 01000010.00000000.-[BAR0]-.00000000.00000008
434 * 01000014,00000000.-[BAR1]-.00000000.00000004
435 * 01000018.00000000.-[BAR2]-.00000000.00000008
436 * 0100001c.00000000.-[BAR3]-.00000000.00000004
437 * 01000020.00000000.-[BAR4]-.00000000.00000010
440 * In both modes the child nodes simply have the following:
442 * 2. primary controller (compatibility mode)
447 * 3. secondary controller
452 * The pciide_bus_map() function is responsible for turning requests
453 * to map primary or secondary controller rnumbers into mapping requests
454 * of the appropriate regspec on the pci-ide node.
459 pciide_initchild(dev_info_t
*mydip
, dev_info_t
*cdip
)
461 struct ddi_parent_private_data
*pdptr
;
462 struct intrspec
*ispecp
;
469 PDBG(("pciide_initchild\n"));
472 * Set the address portion of the node name based on
473 * the controller number (0 or 1) from the 'reg' property.
475 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, cdip
, DDI_PROP_DONTPASS
,
476 "reg", &rp
, (uint_t
*)&proplen
) != DDI_PROP_SUCCESS
) {
477 PDBG(("pciide_intchild prop error\n"));
478 return (DDI_NOT_WELL_FORMED
);
482 * copy the controller number and
483 * free the memory allocated by ddi_prop_lookup_int_array
489 * I only support two controllers per device, determine
490 * which this one is and set its unit address.
493 PDBG(("pciide_initchild bad dev\n"));
494 return (DDI_NOT_WELL_FORMED
);
496 (void) sprintf(name
, "%d", dev
);
497 ddi_set_name_addr(cdip
, name
);
500 * determine if this instance is running in native or compat mode
502 pciide_compat_setup(mydip
, cdip
, dev
);
504 /* interrupts property is required */
505 if (PCIIDE_NATIVE_MODE(cdip
)) {
509 * In compatibility mode, dev 0 should always be
510 * IRQ 14 and dev 1 is IRQ 15. If for some reason
511 * this needs to be changed, do it via the interrupts
512 * property in the ata.conf file.
514 vec
= ddi_prop_get_int(DDI_DEV_T_ANY
, cdip
, DDI_PROP_DONTPASS
,
517 /* setup compatibility mode interrupts */
520 } else if (dev
== 1) {
523 PDBG(("pciide_initchild bad intr\n"));
524 return (DDI_NOT_WELL_FORMED
);
529 pdptr
= kmem_zalloc(PCIIDE_PDSIZE
, KM_SLEEP
);
530 ispecp
= (struct intrspec
*)(pdptr
+ 1);
531 pdptr
->par_nintr
= 1;
532 pdptr
->par_intr
= ispecp
;
533 ispecp
->intrspec_vec
= vec
;
534 ddi_set_parent_data(cdip
, pdptr
);
536 PDBG(("pciide_initchild okay\n"));
537 return (DDI_SUCCESS
);
541 pciide_bus_map(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_map_req_t
*mp
,
542 off_t offset
, off_t len
, caddr_t
*vaddrp
)
545 int rnumber
= mp
->map_obj
.rnumber
;
549 PDBG(("pciide_bus_map\n"));
551 if (strcmp("0", ddi_get_name_addr(rdip
)) == 0)
557 * Adjust the rnumbers based on which controller instance
558 * is being mapped; adjust for the 2 tuples per controller.
564 mp
->map_obj
.rnumber
+= (controller
* 2);
568 * split the 16 I/O ports into two 8 port ranges
570 mp
->map_obj
.rnumber
= 4;
571 if (offset
+ len
> 8) {
572 PDBG(("pciide_bus_map offset\n"));
573 return (DDI_FAILURE
);
577 offset
+= 8 * controller
;
580 PDBG(("pciide_bus_map default\n"));
581 return (DDI_FAILURE
);
584 if (PCIIDE_PRE26(dip
)) {
588 old_rnumber
= mp
->map_obj
.rnumber
;
589 new_rnumber
= pciide_pre26_rnumber_map(dip
, old_rnumber
);
590 PDBG(("pciide rnumber old %d new %d\n",
591 old_rnumber
, new_rnumber
));
592 mp
->map_obj
.rnumber
= new_rnumber
;
596 * Add 1 to skip over the PCI config space tuple
598 mp
->map_obj
.rnumber
++;
602 * pass the adjusted request to my parent
604 pdip
= ddi_get_parent(dip
);
605 rc
= ((*(DEVI(pdip
)->devi_ops
->devo_bus_ops
->bus_map
))
606 (pdip
, dip
, mp
, offset
, len
, vaddrp
));
608 PDBG(("pciide_bus_map %s\n", rc
== DDI_SUCCESS
? "okay" : "!ok"));
614 static struct intrspec
*
615 pciide_get_ispec(dev_info_t
*dip
, dev_info_t
*rdip
, int inumber
)
617 struct ddi_parent_private_data
*ppdptr
;
619 PDBG(("pciide_get_ispec\n"));
622 * Native mode PCI-IDE controllers share the parent's
623 * PCI interrupt line.
625 * Compatibility mode PCI-IDE controllers have their
626 * own intrspec which specifies ISA IRQ 14 or 15.
629 if (PCIIDE_NATIVE_MODE(rdip
)) {
632 is
= pci_intx_get_ispec(dip
, dip
, inumber
);
633 PDBG(("pciide_get_ispec okay\n"));
634 return ((struct intrspec
*)is
);
637 /* Else compatibility mode, use the ISA IRQ */
638 if ((ppdptr
= ddi_get_parent_data(rdip
)) == NULL
) {
639 PDBG(("pciide_get_ispec null\n"));
643 /* validate the interrupt number */
644 if (inumber
>= ppdptr
->par_nintr
) {
645 PDBG(("pciide_get_inum\n"));
649 PDBG(("pciide_get_ispec ok\n"));
651 return ((struct intrspec
*)&ppdptr
->par_intr
[inumber
]);
655 pciide_get_pri(dev_info_t
*dip
, dev_info_t
*rdip
,
656 ddi_intr_handle_impl_t
*hdlp
, int *pri
)
658 struct intrspec
*ispecp
;
660 uint_t num_intpriorities
;
662 PDBG(("pciide_get_pri\n"));
664 if ((ispecp
= pciide_get_ispec(dip
, rdip
, hdlp
->ih_inum
)) == NULL
) {
665 PDBG(("pciide_get_pri null\n"));
666 return (DDI_FAILURE
);
669 if (PCIIDE_NATIVE_MODE(rdip
)) {
670 *pri
= ispecp
->intrspec_pri
;
671 PDBG(("pciide_get_pri ok\n"));
672 return (DDI_SUCCESS
);
675 /* check if the intrspec has been initialized */
676 if (ispecp
->intrspec_pri
!= 0) {
677 *pri
= ispecp
->intrspec_pri
;
678 PDBG(("pciide_get_pri ok2\n"));
679 return (DDI_SUCCESS
);
682 /* Use a default of level 5 */
683 ispecp
->intrspec_pri
= 5;
686 * If there's an interrupt-priorities property, use it to
687 * over-ride the default interrupt priority.
689 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, rdip
, DDI_PROP_DONTPASS
,
690 "interrupt-priorities", &intpriorities
, &num_intpriorities
) ==
692 if (hdlp
->ih_inum
< num_intpriorities
)
693 ispecp
->intrspec_pri
= intpriorities
[hdlp
->ih_inum
];
694 ddi_prop_free(intpriorities
);
696 *pri
= ispecp
->intrspec_pri
;
698 PDBG(("pciide_get_pri ok3\n"));
700 return (DDI_SUCCESS
);
704 pciide_intr_ops(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_intr_op_t intr_op
,
705 ddi_intr_handle_impl_t
*hdlp
, void *result
)
707 struct intrspec
*ispecp
;
711 PDBG(("pciide_intr_ops: dip %p rdip %p op %x hdlp %p\n",
712 (void *)dip
, (void *)rdip
, intr_op
, (void *)hdlp
));
715 case DDI_INTROP_SUPPORTED_TYPES
:
716 *(int *)result
= DDI_INTR_TYPE_FIXED
;
718 case DDI_INTROP_GETCAP
:
719 *(int *)result
= DDI_INTR_FLAG_LEVEL
;
721 case DDI_INTROP_NINTRS
:
722 case DDI_INTROP_NAVAIL
:
723 *(int *)result
= (!PCIIDE_NATIVE_MODE(rdip
)) ?
724 i_ddi_get_intx_nintrs(rdip
) : 1;
726 case DDI_INTROP_ALLOC
:
727 return (pciide_alloc_intr(dip
, rdip
, hdlp
, result
));
728 case DDI_INTROP_FREE
:
729 return (pciide_free_intr(dip
, rdip
, hdlp
));
730 case DDI_INTROP_GETPRI
:
731 if (pciide_get_pri(dip
, rdip
, hdlp
, &pri
) != DDI_SUCCESS
) {
733 return (DDI_FAILURE
);
735 *(int *)result
= pri
;
737 case DDI_INTROP_ADDISR
:
738 if ((ispecp
= pciide_get_ispec(dip
, rdip
, hdlp
->ih_inum
)) ==
740 return (DDI_FAILURE
);
741 ((ihdl_plat_t
*)hdlp
->ih_private
)->ip_ispecp
= ispecp
;
742 ispecp
->intrspec_func
= hdlp
->ih_cb_func
;
744 case DDI_INTROP_REMISR
:
745 if ((ispecp
= pciide_get_ispec(dip
, rdip
, hdlp
->ih_inum
)) ==
747 return (DDI_FAILURE
);
748 ispecp
->intrspec_func
= (uint_t (*)()) 0;
750 case DDI_INTROP_ENABLE
:
752 case DDI_INTROP_DISABLE
:
753 if (PCIIDE_NATIVE_MODE(rdip
)) {
755 dip
= ddi_get_parent(dip
);
756 } else { /* get ptr to the root node */
757 dip
= ddi_root_node();
760 rc
= (*(DEVI(dip
)->devi_ops
->devo_bus_ops
->bus_intr_op
))(dip
,
761 rdip
, intr_op
, hdlp
, result
);
764 if (intr_op
== DDI_INTROP_ENABLE
) {
765 PDBG(("pciide_enable rc=%d", rc
));
767 PDBG(("pciide_disable rc=%d", rc
));
771 return (DDI_FAILURE
);
774 return (DDI_SUCCESS
);
778 pciide_alloc_intr(dev_info_t
*dip
, dev_info_t
*rdip
,
779 ddi_intr_handle_impl_t
*hdlp
, void *result
)
781 struct intrspec
*ispec
;
782 ddi_intr_handle_impl_t info_hdl
;
785 apic_get_type_t type_info
;
787 if (psm_intr_ops
== NULL
)
788 return (DDI_FAILURE
);
790 if ((ispec
= pciide_get_ispec(dip
, rdip
, hdlp
->ih_inum
)) == NULL
)
791 return (DDI_FAILURE
);
794 * If the PSM module is "APIX" then pass the request for it
795 * to allocate the vector now.
797 bzero(&info_hdl
, sizeof (ddi_intr_handle_impl_t
));
798 info_hdl
.ih_private
= &type_info
;
799 if ((*psm_intr_ops
)(NULL
, &info_hdl
, PSM_INTR_OP_APIC_TYPE
, NULL
) ==
800 PSM_SUCCESS
&& strcmp(type_info
.avgi_type
, APIC_APIX_NAME
) == 0) {
801 if (hdlp
->ih_private
== NULL
) { /* allocate phdl structure */
803 i_ddi_alloc_intr_phdl(hdlp
);
805 ((ihdl_plat_t
*)hdlp
->ih_private
)->ip_ispecp
= ispec
;
806 if (PCIIDE_NATIVE_MODE(rdip
)) {
808 dip
= ddi_get_parent(dip
);
809 } else { /* get ptr to the root node */
810 dip
= ddi_root_node();
812 ret
= (*psm_intr_ops
)(rdip
, hdlp
,
813 PSM_INTR_OP_ALLOC_VECTORS
, result
);
814 if (free_phdl
) { /* free up the phdl structure */
816 i_ddi_free_intr_phdl(hdlp
);
820 * No APIX module; fall back to the old scheme where the
821 * interrupt vector is allocated during ddi_enable_intr() call.
823 *(int *)result
= hdlp
->ih_scratch1
;
831 pciide_free_intr(dev_info_t
*dip
, dev_info_t
*rdip
,
832 ddi_intr_handle_impl_t
*hdlp
)
834 struct intrspec
*ispec
;
835 ddi_intr_handle_impl_t info_hdl
;
836 apic_get_type_t type_info
;
838 if (psm_intr_ops
== NULL
)
839 return (DDI_FAILURE
);
842 * If the PSM module is "APIX" then pass the request for it
843 * to free up the vector now.
845 bzero(&info_hdl
, sizeof (ddi_intr_handle_impl_t
));
846 info_hdl
.ih_private
= &type_info
;
847 if ((*psm_intr_ops
)(NULL
, &info_hdl
, PSM_INTR_OP_APIC_TYPE
, NULL
) ==
848 PSM_SUCCESS
&& strcmp(type_info
.avgi_type
, APIC_APIX_NAME
) == 0) {
849 if ((ispec
= pciide_get_ispec(dip
, rdip
, hdlp
->ih_inum
)) ==
851 return (DDI_FAILURE
);
852 ((ihdl_plat_t
*)hdlp
->ih_private
)->ip_ispecp
= ispec
;
853 if (PCIIDE_NATIVE_MODE(rdip
)) {
855 dip
= ddi_get_parent(dip
);
856 } else { /* get ptr to the root node */
857 dip
= ddi_root_node();
859 return ((*psm_intr_ops
)(rdip
, hdlp
,
860 PSM_INTR_OP_FREE_VECTORS
, NULL
));
864 * No APIX module; fall back to the old scheme where
865 * the interrupt vector was already freed during
866 * ddi_disable_intr() call.
868 return (DDI_SUCCESS
);
872 * This is one of the places where controller specific setup needs to be
874 * At this point the controller was already pre-qualified as a known and
875 * supported pciide controller.
876 * Some controllers do not provide PCI_MASS_IDE sub-class code and IDE
877 * programming interface code but rather PCI_MASS_OTHER sub-class code
878 * without any additional data.
879 * For those controllers IDE programming interface cannot be extracted
880 * from PCI class - we assume that they are pci-native type and we fix
881 * the programming interface used by other functions.
882 * The programming interface byte is set to indicate pci-native mode
883 * for both controllers and the Bus Master DMA capabilitiy of the controller.
886 pciide_compat_setup(dev_info_t
*mydip
, dev_info_t
*cdip
, int dev
)
889 int rc
= DDI_PROP_SUCCESS
;
891 class_code
= ddi_prop_get_int(DDI_DEV_T_ANY
, mydip
,
892 DDI_PROP_DONTPASS
, "class-code", 0);
894 if (((class_code
& 0x00FF00) >> 8) == PCI_MASS_IDE
) {
896 * Controller provides PCI_MASS_IDE sub-class code first
897 * (implied IDE programming interface)
899 if ((dev
== 0 && !(class_code
& PCI_IDE_IF_NATIVE_PRI
)) ||
900 (dev
== 1 && !(class_code
& PCI_IDE_IF_NATIVE_SEC
))) {
901 rc
= ndi_prop_update_int(DDI_DEV_T_NONE
, cdip
,
902 "compatibility-mode", 1);
903 if (rc
!= DDI_PROP_SUCCESS
)
905 "pciide prop error %d compat-mode", rc
);
909 * Pci-ide controllers not providing PCI_MASS_IDE sub-class are
910 * assumed to be of pci-native type and bus master DMA capable.
911 * Programming interface part of the class-code property is
914 class_code
&= 0x00ffff00;
915 class_code
|= PCI_IDE_IF_BM_CAP_MASK
|
916 PCI_IDE_IF_NATIVE_PRI
| PCI_IDE_IF_NATIVE_SEC
;
917 rc
= ddi_prop_update_int(DDI_DEV_T_NONE
, mydip
,
918 "class-code", class_code
);
919 if (rc
!= DDI_PROP_SUCCESS
)
921 "pciide prop error %d class-code", rc
);
927 pciide_pre26_rnumber_map(dev_info_t
*mydip
, int rnumber
)
933 class_code
= ddi_prop_get_int(DDI_DEV_T_ANY
, mydip
, DDI_PROP_DONTPASS
,
936 pri_native
= (class_code
& PCI_IDE_IF_NATIVE_PRI
) ? TRUE
: FALSE
;
937 sec_native
= (class_code
& PCI_IDE_IF_NATIVE_SEC
) ? TRUE
: FALSE
;
939 return (pciide_map_rnumber(rnumber
, pri_native
, sec_native
));
944 * The canonical order of the reg property tuples for the
945 * Base Address Registers is supposed to be:
947 * primary controller (BAR 0)
948 * primary controller (BAR 1)
949 * secondary controller (BAR 2)
950 * secondary controller (BAR 3)
951 * bus mastering regs (BAR 4)
953 * For 2.6, bootconf has been fixed to always generate the
954 * reg property (and assigned-addresses property) tuples
955 * in the above order.
957 * But in releases prior to 2.6 the order varies depending
958 * on whether compatibility or native mode is being used for
959 * each controller. There ends up being four possible
962 * BM, P0, P1, S0, S1 primary compatible, secondary compatible
963 * S0, S1, BM, P0, P1 primary compatible, secondary native
964 * P0, P1, BM, S0, S1 primary native, secondary compatible
965 * P0, P1, S0, S1, BM primary native, secondary native
967 * where: Px is the primary tuples, Sx the secondary tuples, and
968 * B the Bus Master tuple.
970 * Here's the results for each of the four states:
979 * C = compatible(!native) == 0
982 * Here's the transformation matrix:
985 static int pciide_transform
[2][2][5] = {
987 /* [C][C] */ +1, +1, +1, +1, -4,
988 /* [C][N] */ +3, +3, -2, -2, -2,
989 /* [N][C] */ +0, +0, +1, +1, -2,
990 /* [N][N] */ +0, +0, +0, +0, +0
995 pciide_map_rnumber(int rnumber
, int pri_native
, int sec_native
)
997 /* transform flags into indexes */
998 pri_native
= pri_native
? 1 : 0;
999 sec_native
= sec_native
? 1 : 0;
1001 rnumber
+= pciide_transform
[pri_native
][sec_native
][rnumber
];