Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / io / 1394 / adapters / hci1394_detach.c
blob37c9a4bfbaf437a2bab36fda1647d4ae624a02fd
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 * hci1394_detach.c
29 * HBA detach() routine with associated funtions.
32 #include <sys/types.h>
33 #include <sys/kmem.h>
34 #include <sys/conf.h>
35 #include <sys/ddi.h>
36 #include <sys/modctl.h>
37 #include <sys/stat.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>
46 int
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) {
53 return (DDI_FAILURE);
56 switch (cmd) {
57 case DDI_DETACH:
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,
72 0xFFFFFFFF);
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,
79 HCI1394_SHUTDOWN);
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,
91 DDI_DETACH);
93 /* remove the minor node */
94 ddi_remove_minor_node(dip, "devctl");
96 /* cleanup */
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);
111 case DDI_SUSPEND:
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,
126 0xFFFFFFFF);
128 /* don't accept anymore commands from services layer */
129 (void) hci1394_state_set(&soft_state->drvinfo,
130 HCI1394_SHUTDOWN);
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,
142 DDI_SUSPEND);
144 return (DDI_SUCCESS);
146 default:
147 break;
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
158 * blocked.
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);
198 void
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);
224 * hci1394_pci_fini()
225 * Cleanup after a PCI init.
227 void
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.
239 void
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);