1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * hci1394_detach.c 31 * HBA detach() routine with associated funtions. 32 */ 33 34 #include <sys/types.h> 35 #include <sys/kmem.h> 36 #include <sys/conf.h> 37 #include <sys/ddi.h> 38 #include <sys/modctl.h> 39 #include <sys/stat.h> 40 #include <sys/sunddi.h> 41 42 #include <sys/1394/h1394.h> 43 #include <sys/1394/adapters/hci1394.h> 44 #include <sys/1394/adapters/hci1394_extern.h> 45 46 47 48 int 49 hci1394_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 50 { 51 hci1394_state_t *soft_state; 52 53 54 TNF_PROBE_0_DEBUG(hci1394_detach_enter, HCI1394_TNF_HAL_STACK, ""); 55 56 soft_state = ddi_get_soft_state(hci1394_statep, ddi_get_instance(dip)); 57 if (soft_state == NULL) { 58 TNF_PROBE_1(hci1394_detach_ssn_fail, HCI1394_TNF_HAL_ERROR, "", 59 tnf_string, errmsg, "soft_state = NULL"); 60 TNF_PROBE_0_DEBUG(hci1394_detach_exit, HCI1394_TNF_HAL_STACK, 61 ""); 62 return (DDI_FAILURE); 63 } 64 65 switch (cmd) { 66 case DDI_DETACH: 67 /* Don't allow the HW to generate any more interrupts */ 68 hci1394_ohci_intr_master_disable(soft_state->ohci); 69 70 /* don't accept anymore commands from services layer */ 71 (void) hci1394_state_set(&soft_state->drvinfo, 72 HCI1394_SHUTDOWN); 73 74 /* Reset the OHCI HW */ 75 (void) hci1394_ohci_soft_reset(soft_state->ohci); 76 77 /* Flush out async DMA Q's (cancels pendingQ timeouts too) */ 78 hci1394_async_flush(soft_state->async); 79 80 (void) h1394_detach(&soft_state->drvinfo.di_sl_private, 81 DDI_DETACH); 82 83 /* remove the minor node */ 84 ddi_remove_minor_node(dip, "devctl"); 85 86 /* cleanup */ 87 hci1394_detach_hardware(soft_state); 88 89 /* cleanup Solaris interrupt stuff */ 90 hci1394_isr_fini(soft_state); 91 92 /* cleanup soft state stuff */ 93 hci1394_soft_state_fini(soft_state); 94 95 /* free soft state */ 96 ddi_soft_state_free(hci1394_statep, 97 soft_state->drvinfo.di_instance); 98 99 TNF_PROBE_0_DEBUG(hci1394_detach_exit, HCI1394_TNF_HAL_STACK, 100 ""); 101 return (DDI_SUCCESS); 102 103 case DDI_SUSPEND: 104 /* Don't allow the HW to generate any more interrupts */ 105 hci1394_ohci_intr_master_disable(soft_state->ohci); 106 107 /* don't accept anymore commands from services layer */ 108 (void) hci1394_state_set(&soft_state->drvinfo, 109 HCI1394_SHUTDOWN); 110 111 /* Reset the OHCI HW */ 112 (void) hci1394_ohci_soft_reset(soft_state->ohci); 113 114 /* Make sure async engine is ready to suspend */ 115 hci1394_async_suspend(soft_state->async); 116 117 (void) h1394_detach(&soft_state->drvinfo.di_sl_private, 118 DDI_SUSPEND); 119 120 TNF_PROBE_0_DEBUG(hci1394_detach_exit, HCI1394_TNF_HAL_STACK, 121 ""); 122 return (DDI_SUCCESS); 123 124 default: 125 TNF_PROBE_1(hci1394_detach_fail, HCI1394_TNF_HAL_ERROR, "", 126 tnf_string, errmsg, "in detach default"); 127 break; 128 } 129 130 TNF_PROBE_0_DEBUG(hci1394_detach_exit, HCI1394_TNF_HAL_STACK, ""); 131 132 return (DDI_FAILURE); 133 } 134 135 136 void 137 hci1394_detach_hardware(hci1394_state_t *soft_state) 138 { 139 ASSERT(soft_state != NULL); 140 TNF_PROBE_0_DEBUG(hci1394_detach_hardware_enter, HCI1394_TNF_HAL_STACK, 141 ""); 142 143 /* free up vendor specific registers */ 144 hci1394_vendor_fini(&soft_state->vendor); 145 146 /* cleanup isoch layer */ 147 hci1394_isoch_fini(&soft_state->isoch); 148 149 /* cleanup async layer */ 150 hci1394_async_fini(&soft_state->async); 151 152 /* Free up csr register space */ 153 hci1394_csr_fini(&soft_state->csr); 154 155 /* free up OpenHCI registers */ 156 hci1394_ohci_fini(&soft_state->ohci); 157 158 /* free up PCI config space */ 159 hci1394_pci_fini(soft_state); 160 161 TNF_PROBE_0_DEBUG(hci1394_detach_hardware_exit, HCI1394_TNF_HAL_STACK, 162 ""); 163 } 164 165 166 /* 167 * hci1394_pci_fini() 168 * Cleanup after a PCI init. 169 */ 170 void 171 hci1394_pci_fini(hci1394_state_t *soft_state) 172 { 173 ASSERT(soft_state != NULL); 174 TNF_PROBE_0_DEBUG(hci1394_pci_fini_enter, HCI1394_TNF_HAL_STACK, ""); 175 pci_config_teardown(&soft_state->pci_config); 176 TNF_PROBE_0_DEBUG(hci1394_pci_fini_exit, HCI1394_TNF_HAL_STACK, ""); 177 } 178 179 180 /* 181 * hci1394_soft_state_fini() 182 * Cleanup any mutex's, etc. in soft_state. 183 */ 184 void 185 hci1394_soft_state_fini(hci1394_state_t *soft_state) 186 { 187 ASSERT(soft_state != NULL); 188 TNF_PROBE_0_DEBUG(hci1394_soft_state_fini_enter, HCI1394_TNF_HAL_STACK, 189 ""); 190 mutex_destroy(&soft_state->drvinfo.di_drvstate.ds_mutex); 191 TNF_PROBE_0_DEBUG(hci1394_soft_state_fini_exit, HCI1394_TNF_HAL_STACK, 192 ""); 193 } 194