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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
29 * HBA detach() routine with associated funtions.
32 #include <sys/types.h>
36 #include <sys/modctl.h>
38 #include <sys/sunddi.h>
40 #include <sys/1394/h1394.h>
41 #include <sys/1394/adapters/hci1394.h>
42 #include <sys/1394/adapters/hci1394_extern.h>
47 hci1394_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
49 hci1394_state_t
*soft_state
;
51 soft_state
= ddi_get_soft_state(hci1394_statep
, ddi_get_instance(dip
));
52 if (soft_state
== NULL
) {
58 /* Don't allow the HW to generate any more interrupts */
59 hci1394_ohci_intr_master_disable(soft_state
->ohci
);
60 hci1394_ohci_it_intr_disable(soft_state
->ohci
, 0xFFFFFFFF);
61 hci1394_ohci_ir_intr_disable(soft_state
->ohci
, 0xFFFFFFFF);
63 /* Clear any pending interrupts - no longer valid */
64 hci1394_ohci_intr_clear(soft_state
->ohci
, 0xFFFFFFFF);
65 hci1394_ohci_it_intr_clear(soft_state
->ohci
, 0xFFFFFFFF);
66 hci1394_ohci_ir_intr_clear(soft_state
->ohci
, 0xFFFFFFFF);
68 /* Make sure we tell others on the bus we are dropping out */
69 (void) hci1394_ohci_phy_clr(soft_state
->ohci
, 4, 0xc0);
70 ddi_put32(soft_state
->ohci
->ohci_reg_handle
,
71 &soft_state
->ohci
->ohci_regs
->link_ctrl_clr
,
74 /* unregister interrupt handler */
75 hci1394_isr_handler_fini(soft_state
);
77 /* don't accept anymore commands from services layer */
78 (void) hci1394_state_set(&soft_state
->drvinfo
,
81 /* Do a long reset on the bus so every one knows we are gone */
82 (void) hci1394_ohci_bus_reset_nroot(soft_state
->ohci
);
84 /* Reset the OHCI HW */
85 (void) hci1394_ohci_soft_reset(soft_state
->ohci
);
87 /* Flush out async DMA Q's (cancels pendingQ timeouts too) */
88 hci1394_async_flush(soft_state
->async
);
90 (void) h1394_detach(&soft_state
->drvinfo
.di_sl_private
,
93 /* remove the minor node */
94 ddi_remove_minor_node(dip
, "devctl");
97 hci1394_detach_hardware(soft_state
);
99 /* cleanup Solaris interrupt stuff */
100 hci1394_isr_fini(soft_state
);
102 /* cleanup soft state stuff */
103 hci1394_soft_state_fini(soft_state
);
105 /* free soft state */
106 ddi_soft_state_free(hci1394_statep
,
107 soft_state
->drvinfo
.di_instance
);
109 return (DDI_SUCCESS
);
112 /* Don't allow the HW to generate any more interrupts */
113 hci1394_ohci_intr_master_disable(soft_state
->ohci
);
114 hci1394_ohci_it_intr_disable(soft_state
->ohci
, 0xFFFFFFFF);
115 hci1394_ohci_ir_intr_disable(soft_state
->ohci
, 0xFFFFFFFF);
117 /* Clear any pending interrupts - no longer valid */
118 hci1394_ohci_intr_clear(soft_state
->ohci
, 0xFFFFFFFF);
119 hci1394_ohci_it_intr_clear(soft_state
->ohci
, 0xFFFFFFFF);
120 hci1394_ohci_ir_intr_clear(soft_state
->ohci
, 0xFFFFFFFF);
122 /* Make sure we tell others on the bus we are dropping out */
123 (void) hci1394_ohci_phy_clr(soft_state
->ohci
, 4, 0xc0);
124 ddi_put32(soft_state
->ohci
->ohci_reg_handle
,
125 &soft_state
->ohci
->ohci_regs
->link_ctrl_clr
,
128 /* don't accept anymore commands from services layer */
129 (void) hci1394_state_set(&soft_state
->drvinfo
,
132 /* Do a long reset on the bus so every one knows we are gone */
133 (void) hci1394_ohci_bus_reset_nroot(soft_state
->ohci
);
135 /* Reset the OHCI HW */
136 (void) hci1394_ohci_soft_reset(soft_state
->ohci
);
138 /* Make sure async engine is ready to suspend */
139 hci1394_async_suspend(soft_state
->async
);
141 (void) h1394_detach(&soft_state
->drvinfo
.di_sl_private
,
144 return (DDI_SUCCESS
);
150 return (DDI_FAILURE
);
154 * quiesce(9E) entry point.
156 * This function is called when the system is single-threaded at high
157 * PIL with preemption disabled. Therefore, this function must not be
160 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
161 * DDI_FAILURE indicates an error condition and should almost never happen.
164 hci1394_quiesce(dev_info_t
*dip
)
166 hci1394_state_t
*soft_state
;
168 soft_state
= ddi_get_soft_state(hci1394_statep
, ddi_get_instance(dip
));
170 if (soft_state
== NULL
) {
171 return (DDI_FAILURE
);
174 /* Don't allow the HW to generate any more interrupts */
175 hci1394_ohci_intr_master_disable(soft_state
->ohci
);
176 hci1394_ohci_it_intr_disable(soft_state
->ohci
, 0xFFFFFFFF);
177 hci1394_ohci_ir_intr_disable(soft_state
->ohci
, 0xFFFFFFFF);
179 /* Clear any pending interrupts - no longer valid */
180 hci1394_ohci_intr_clear(soft_state
->ohci
, 0xFFFFFFFF);
181 hci1394_ohci_it_intr_clear(soft_state
->ohci
, 0xFFFFFFFF);
182 hci1394_ohci_ir_intr_clear(soft_state
->ohci
, 0xFFFFFFFF);
184 /* Make sure we tell others on the bus we are dropping out */
185 (void) hci1394_ohci_phy_clr(soft_state
->ohci
, 4, 0xc0);
186 ddi_put32(soft_state
->ohci
->ohci_reg_handle
,
187 &soft_state
->ohci
->ohci_regs
->link_ctrl_clr
, 0xFFFFFFFF);
189 /* Do a long reset on the bus so every one knows we are gone */
190 (void) hci1394_ohci_bus_reset_nroot(soft_state
->ohci
);
192 /* Reset the OHCI HW */
193 (void) hci1394_ohci_soft_reset(soft_state
->ohci
);
195 return (DDI_SUCCESS
);
199 hci1394_detach_hardware(hci1394_state_t
*soft_state
)
201 ASSERT(soft_state
!= NULL
);
203 /* free up vendor specific registers */
204 hci1394_vendor_fini(&soft_state
->vendor
);
206 /* cleanup isoch layer */
207 hci1394_isoch_fini(&soft_state
->isoch
);
209 /* cleanup async layer */
210 hci1394_async_fini(&soft_state
->async
);
212 /* Free up csr register space */
213 hci1394_csr_fini(&soft_state
->csr
);
215 /* free up OpenHCI registers */
216 hci1394_ohci_fini(&soft_state
->ohci
);
218 /* free up PCI config space */
219 hci1394_pci_fini(soft_state
);
225 * Cleanup after a PCI init.
228 hci1394_pci_fini(hci1394_state_t
*soft_state
)
230 ASSERT(soft_state
!= NULL
);
231 pci_config_teardown(&soft_state
->pci_config
);
236 * hci1394_soft_state_fini()
237 * Cleanup any mutex's, etc. in soft_state.
240 hci1394_soft_state_fini(hci1394_state_t
*soft_state
)
242 ASSERT(soft_state
!= NULL
);
243 mutex_destroy(&soft_state
->drvinfo
.di_drvstate
.ds_mutex
);