isci_domain.c revision 230557
1/*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include <sys/cdefs.h> 32__FBSDID("$FreeBSD$"); 33 34#include <dev/isci/isci.h> 35 36#include <cam/cam_periph.h> 37#include <cam/cam_xpt_periph.h> 38 39#include <dev/isci/scil/scif_domain.h> 40#include <dev/isci/scil/scif_remote_device.h> 41#include <dev/isci/scil/scif_controller.h> 42#include <dev/isci/scil/scif_user_callback.h> 43 44/** 45 * @brief This callback method informs the framework user that something 46 * in the supplied domain has changed (e.g. a device was added or 47 * removed). 48 * 49 * This callback is called by the framework outside of discovery or 50 * target reset processes. Specifically, domain changes occurring 51 * during these processes are handled by the framework. For example, 52 * in the case of Serial Attached SCSI, reception of a BROADCAST (CHANGE) 53 * during discovery will cause discovery to restart. Thus, discovery 54 * does not complete until all BCNs are processed. Note, during controller 55 * stopping/reset process, the framework user should not expect this call 56 * back. 57 * 58 * @param[in] controller This parameter specifies the controller object 59 * with which this callback is associated. 60 * @param[in] domain This parameter specifies the domain object with 61 * which this callback is associated. 62 * 63 * @return none 64 */ 65void 66scif_cb_domain_change_notification(SCI_CONTROLLER_HANDLE_T controller, 67 SCI_DOMAIN_HANDLE_T domain) 68{ 69 struct ISCI_CONTROLLER *isci_controller = 70 (struct ISCI_CONTROLLER *)sci_object_get_association(controller); 71 72 /* When the controller start is complete, we will explicitly discover 73 * all of the domains then. This is because SCIF will not allow 74 * any I/O to start until the controller is ready, meaning internal SMP 75 * requests triggered by domain discovery won't work until the controller 76 * is ready. 77 */ 78 if (isci_controller->is_started == TRUE) 79 scif_domain_discover(domain, 80 scif_domain_get_suggested_discover_timeout(domain), 81 DEVICE_TIMEOUT); 82} 83 84/** 85 * @brief This callback method informs the framework user that a previously 86 * requested discovery operation on the domain has completed. 87 * 88 * @param[in] controller This parameter specifies the controller object 89 * with which this callback is associated. 90 * @param[in] domain This parameter specifies the domain object with 91 * which this callback is associated. 92 * @param[in] completion_status This parameter indicates the results of the 93 * discovery operation. 94 * 95 * @return none 96 */ 97void 98scif_cb_domain_discovery_complete(SCI_CONTROLLER_HANDLE_T controller, 99 SCI_DOMAIN_HANDLE_T domain, SCI_STATUS completion_status) 100{ 101 102 if(completion_status != SCI_SUCCESS) 103 isci_log_message(0, "ISCI", 104 "scif_cb_domain_discovery_complete status = 0x%x\n", 105 completion_status); 106 107 isci_controller_domain_discovery_complete( 108 (struct ISCI_CONTROLLER *)sci_object_get_association(controller), 109 (struct ISCI_DOMAIN *) sci_object_get_association(domain)); 110} 111 112/** 113 * @brief This callback method informs the framework user that a previously 114 * requested reset operation on the domain has completed. 115 * 116 * @param[in] controller This parameter specifies the controller object 117 * with which this callback is associated. 118 * @param[in] domain This parameter specifies the domain object with 119 * which this callback is associated. 120 * @param[in] completion_status This parameter indicates the results of the 121 * reset operation. 122 * 123 * @return none 124 */ 125void 126scif_cb_domain_reset_complete(SCI_CONTROLLER_HANDLE_T controller, 127 SCI_DOMAIN_HANDLE_T domain, SCI_STATUS completion_status) 128{ 129 130} 131 132/** 133 * @brief This callback method informs the framework user that the domain 134 * is ready and capable of processing IO requests for devices found 135 * inside it. 136 * 137 * @param[in] controller This parameter specifies the controller object 138 * with which this callback is associated. 139 * @param[in] domain This parameter specifies the domain object with 140 * which this callback is associated. 141 * 142 * @return none 143 */ 144void 145scif_cb_domain_ready(SCI_CONTROLLER_HANDLE_T controller, 146 SCI_DOMAIN_HANDLE_T domain) 147{ 148 uint32_t i; 149 struct ISCI_DOMAIN *isci_domain = sci_object_get_association(domain); 150 struct ISCI_CONTROLLER *isci_controller = 151 sci_object_get_association(controller); 152 153 for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) { 154 struct ISCI_REMOTE_DEVICE *remote_device = 155 isci_controller->remote_device[i]; 156 157 if (remote_device != NULL && 158 remote_device->domain == isci_domain) 159 isci_remote_device_release_device_queue(remote_device); 160 } 161} 162 163/** 164 * @brief This callback method informs the framework user that the domain 165 * is no longer ready. Thus, it is incapable of processing IO 166 * requests for devices found inside it. 167 * 168 * @param[in] controller This parameter specifies the controller object 169 * with which this callback is associated. 170 * @param[in] domain This parameter specifies the domain object with 171 * which this callback is associated. 172 * 173 * @return none 174 */ 175void 176scif_cb_domain_not_ready(SCI_CONTROLLER_HANDLE_T controller, 177 SCI_DOMAIN_HANDLE_T domain) 178{ 179 180} 181 182/** 183 * @brief This callback method informs the framework user that a new 184 * direct attached device was found in the domain. 185 * 186 * @param[in] controller This parameter specifies the controller object 187 * with which this callback is associated. 188 * @param[in] domain This parameter specifies the domain object with 189 * which this callback is associated. 190 * @param[in] sas_address This parameter specifies the SAS address of 191 * the new device. 192 * @param[in] protocols This parameter specifies the protocols 193 * supported by the newly discovered device. 194 * 195 * @return none 196 */ 197void 198scif_cb_domain_da_device_added(SCI_CONTROLLER_HANDLE_T controller, 199 SCI_DOMAIN_HANDLE_T domain, SCI_SAS_ADDRESS_T *sas_address, 200 SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T *protocols) 201{ 202 struct ISCI_REMOTE_DEVICE *remote_device; 203 struct ISCI_DOMAIN *isci_domain = 204 (struct ISCI_DOMAIN *)sci_object_get_association(domain); 205 struct ISCI_CONTROLLER *isci_controller = 206 (struct ISCI_CONTROLLER *)sci_object_get_association(controller); 207 208 sci_pool_get(isci_controller->remote_device_pool, remote_device); 209 210 scif_remote_device_construct(domain, 211 (uint8_t*)remote_device + sizeof(struct ISCI_REMOTE_DEVICE), 212 &(remote_device->sci_object)); 213 214 sci_object_set_association(remote_device->sci_object, remote_device); 215 216 scif_remote_device_da_construct(remote_device->sci_object, sas_address, 217 protocols); 218 219 /* We do not put the device in the ISCI_CONTROLLER's device array yet. 220 * That will happen once the device becomes ready (see 221 * scif_cb_remote_device_ready). 222 */ 223 224 remote_device->domain = isci_domain; 225} 226 227/** 228 * @brief This callback method informs the framework user that a new 229 * expander attached device was found in the domain. 230 * 231 * @param[in] controller This parameter specifies the controller object 232 * with which this callback is associated. 233 * @param[in] domain This parameter specifies the domain object with 234 * which this callback is associated. 235 * @param[in] containing_device This parameter specifies the remote 236 * device that contains the device that was added. 237 * @param[in] smp_response This parameter specifies the SMP response 238 * data associated with the newly discovered device. 239 * 240 * @return none 241 */ 242void 243scif_cb_domain_ea_device_added(SCI_CONTROLLER_HANDLE_T controller, 244 SCI_DOMAIN_HANDLE_T domain, SCI_REMOTE_DEVICE_HANDLE_T containing_device, 245 SMP_RESPONSE_DISCOVER_T *smp_response) 246{ 247 struct ISCI_REMOTE_DEVICE *remote_device; 248 struct ISCI_DOMAIN *isci_domain = 249 (struct ISCI_DOMAIN *)sci_object_get_association(domain); 250 struct ISCI_CONTROLLER *isci_controller = 251 (struct ISCI_CONTROLLER *)sci_object_get_association(controller); 252 253 sci_pool_get(isci_controller->remote_device_pool, remote_device); 254 255 scif_remote_device_construct( domain, 256 (uint8_t*)remote_device + sizeof(struct ISCI_REMOTE_DEVICE), 257 &(remote_device->sci_object)); 258 259 sci_object_set_association(remote_device->sci_object, remote_device); 260 261 scif_remote_device_ea_construct(remote_device->sci_object, 262 containing_device, smp_response); 263 264 /* We do not put the device in the ISCI_CONTROLLER's device array yet. 265 * That will happen once the device becomes ready (see 266 * scif_cb_remote_device_ready). 267 */ 268 remote_device->domain = isci_domain; 269} 270 271/** 272 * @brief This callback method informs the framework user that a device 273 * has been removed from the domain. 274 * 275 * @param[in] controller This parameter specifies the controller object 276 * with which this callback is associated. 277 * @param[in] domain This parameter specifies the domain object with 278 * which this callback is associated. 279 * @param[in] remote_device This parameter specifies the device object with 280 * which this callback is associated. 281 * 282 * @return none 283 */ 284void 285scif_cb_domain_device_removed(SCI_CONTROLLER_HANDLE_T controller, 286 SCI_DOMAIN_HANDLE_T domain, SCI_REMOTE_DEVICE_HANDLE_T remote_device) 287{ 288 struct ISCI_REMOTE_DEVICE *isci_remote_device = 289 (struct ISCI_REMOTE_DEVICE *)sci_object_get_association(remote_device); 290 struct ISCI_CONTROLLER *isci_controller = 291 (struct ISCI_CONTROLLER *)sci_object_get_association(controller); 292 uint32_t path = cam_sim_path(isci_controller->sim); 293 union ccb *ccb = xpt_alloc_ccb_nowait(); 294 295 isci_controller->remote_device[isci_remote_device->index] = NULL; 296 297 xpt_create_path(&ccb->ccb_h.path, xpt_periph, path, 298 isci_remote_device->index, CAM_LUN_WILDCARD); 299 300 xpt_rescan(ccb); 301 302 scif_remote_device_destruct(remote_device); 303 304 sci_pool_put(isci_controller->remote_device_pool, isci_remote_device); 305} 306 307void 308isci_domain_construct(struct ISCI_DOMAIN *domain, uint32_t domain_index, 309 struct ISCI_CONTROLLER *controller) 310{ 311 312 scif_controller_get_domain_handle( controller->scif_controller_handle, 313 domain_index, &domain->sci_object); 314 315 domain->index = domain_index; 316 domain->controller = controller; 317 sci_object_set_association(domain->sci_object, (void *)domain); 318} 319