1230557Sjimharris/*- 2230557Sjimharris * BSD LICENSE 3230557Sjimharris * 4230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 5230557Sjimharris * All rights reserved. 6230557Sjimharris * 7230557Sjimharris * Redistribution and use in source and binary forms, with or without 8230557Sjimharris * modification, are permitted provided that the following conditions 9230557Sjimharris * are met: 10230557Sjimharris * 11230557Sjimharris * * Redistributions of source code must retain the above copyright 12230557Sjimharris * notice, this list of conditions and the following disclaimer. 13230557Sjimharris * * Redistributions in binary form must reproduce the above copyright 14230557Sjimharris * notice, this list of conditions and the following disclaimer in 15230557Sjimharris * the documentation and/or other materials provided with the 16230557Sjimharris * distribution. 17230557Sjimharris * 18230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19230557Sjimharris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20230557Sjimharris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21230557Sjimharris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22230557Sjimharris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23230557Sjimharris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24230557Sjimharris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25230557Sjimharris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26230557Sjimharris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27230557Sjimharris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28230557Sjimharris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29230557Sjimharris */ 30230557Sjimharris 31230557Sjimharris#include <sys/cdefs.h> 32230557Sjimharris__FBSDID("$FreeBSD: releng/11.0/sys/dev/isci/isci_domain.c 249468 2013-04-14 09:55:48Z mav $"); 33230557Sjimharris 34230557Sjimharris#include <dev/isci/isci.h> 35230557Sjimharris 36230557Sjimharris#include <cam/cam_periph.h> 37230557Sjimharris#include <cam/cam_xpt_periph.h> 38230557Sjimharris 39230557Sjimharris#include <dev/isci/scil/scif_domain.h> 40230557Sjimharris#include <dev/isci/scil/scif_remote_device.h> 41230557Sjimharris#include <dev/isci/scil/scif_controller.h> 42230557Sjimharris#include <dev/isci/scil/scif_user_callback.h> 43230557Sjimharris 44230557Sjimharris/** 45230557Sjimharris * @brief This callback method informs the framework user that something 46230557Sjimharris * in the supplied domain has changed (e.g. a device was added or 47230557Sjimharris * removed). 48230557Sjimharris * 49230557Sjimharris * This callback is called by the framework outside of discovery or 50230557Sjimharris * target reset processes. Specifically, domain changes occurring 51230557Sjimharris * during these processes are handled by the framework. For example, 52230557Sjimharris * in the case of Serial Attached SCSI, reception of a BROADCAST (CHANGE) 53230557Sjimharris * during discovery will cause discovery to restart. Thus, discovery 54230557Sjimharris * does not complete until all BCNs are processed. Note, during controller 55230557Sjimharris * stopping/reset process, the framework user should not expect this call 56230557Sjimharris * back. 57230557Sjimharris * 58230557Sjimharris * @param[in] controller This parameter specifies the controller object 59230557Sjimharris * with which this callback is associated. 60230557Sjimharris * @param[in] domain This parameter specifies the domain object with 61230557Sjimharris * which this callback is associated. 62230557Sjimharris * 63230557Sjimharris * @return none 64230557Sjimharris */ 65230557Sjimharrisvoid 66230557Sjimharrisscif_cb_domain_change_notification(SCI_CONTROLLER_HANDLE_T controller, 67230557Sjimharris SCI_DOMAIN_HANDLE_T domain) 68230557Sjimharris{ 69230557Sjimharris struct ISCI_CONTROLLER *isci_controller = 70230557Sjimharris (struct ISCI_CONTROLLER *)sci_object_get_association(controller); 71230557Sjimharris 72230557Sjimharris /* When the controller start is complete, we will explicitly discover 73230557Sjimharris * all of the domains then. This is because SCIF will not allow 74230557Sjimharris * any I/O to start until the controller is ready, meaning internal SMP 75230557Sjimharris * requests triggered by domain discovery won't work until the controller 76230557Sjimharris * is ready. 77230557Sjimharris */ 78230557Sjimharris if (isci_controller->is_started == TRUE) 79230557Sjimharris scif_domain_discover(domain, 80230557Sjimharris scif_domain_get_suggested_discover_timeout(domain), 81230557Sjimharris DEVICE_TIMEOUT); 82230557Sjimharris} 83230557Sjimharris 84230557Sjimharris/** 85230557Sjimharris * @brief This callback method informs the framework user that a previously 86230557Sjimharris * requested discovery operation on the domain has completed. 87230557Sjimharris * 88230557Sjimharris * @param[in] controller This parameter specifies the controller object 89230557Sjimharris * with which this callback is associated. 90230557Sjimharris * @param[in] domain This parameter specifies the domain object with 91230557Sjimharris * which this callback is associated. 92230557Sjimharris * @param[in] completion_status This parameter indicates the results of the 93230557Sjimharris * discovery operation. 94230557Sjimharris * 95230557Sjimharris * @return none 96230557Sjimharris */ 97230557Sjimharrisvoid 98230557Sjimharrisscif_cb_domain_discovery_complete(SCI_CONTROLLER_HANDLE_T controller, 99230557Sjimharris SCI_DOMAIN_HANDLE_T domain, SCI_STATUS completion_status) 100230557Sjimharris{ 101230557Sjimharris 102230557Sjimharris if(completion_status != SCI_SUCCESS) 103230557Sjimharris isci_log_message(0, "ISCI", 104230557Sjimharris "scif_cb_domain_discovery_complete status = 0x%x\n", 105230557Sjimharris completion_status); 106230557Sjimharris 107230557Sjimharris isci_controller_domain_discovery_complete( 108230557Sjimharris (struct ISCI_CONTROLLER *)sci_object_get_association(controller), 109230557Sjimharris (struct ISCI_DOMAIN *) sci_object_get_association(domain)); 110230557Sjimharris} 111230557Sjimharris 112230557Sjimharris/** 113230557Sjimharris * @brief This callback method informs the framework user that a previously 114230557Sjimharris * requested reset operation on the domain has completed. 115230557Sjimharris * 116230557Sjimharris * @param[in] controller This parameter specifies the controller object 117230557Sjimharris * with which this callback is associated. 118230557Sjimharris * @param[in] domain This parameter specifies the domain object with 119230557Sjimharris * which this callback is associated. 120230557Sjimharris * @param[in] completion_status This parameter indicates the results of the 121230557Sjimharris * reset operation. 122230557Sjimharris * 123230557Sjimharris * @return none 124230557Sjimharris */ 125230557Sjimharrisvoid 126230557Sjimharrisscif_cb_domain_reset_complete(SCI_CONTROLLER_HANDLE_T controller, 127230557Sjimharris SCI_DOMAIN_HANDLE_T domain, SCI_STATUS completion_status) 128230557Sjimharris{ 129230557Sjimharris 130230557Sjimharris} 131230557Sjimharris 132230557Sjimharris/** 133230557Sjimharris * @brief This callback method informs the framework user that the domain 134230557Sjimharris * is ready and capable of processing IO requests for devices found 135230557Sjimharris * inside it. 136230557Sjimharris * 137230557Sjimharris * @param[in] controller This parameter specifies the controller object 138230557Sjimharris * with which this callback is associated. 139230557Sjimharris * @param[in] domain This parameter specifies the domain object with 140230557Sjimharris * which this callback is associated. 141230557Sjimharris * 142230557Sjimharris * @return none 143230557Sjimharris */ 144230557Sjimharrisvoid 145230557Sjimharrisscif_cb_domain_ready(SCI_CONTROLLER_HANDLE_T controller, 146230557Sjimharris SCI_DOMAIN_HANDLE_T domain) 147230557Sjimharris{ 148230557Sjimharris uint32_t i; 149230557Sjimharris struct ISCI_DOMAIN *isci_domain = sci_object_get_association(domain); 150230557Sjimharris struct ISCI_CONTROLLER *isci_controller = 151230557Sjimharris sci_object_get_association(controller); 152230557Sjimharris 153230557Sjimharris for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) { 154230557Sjimharris struct ISCI_REMOTE_DEVICE *remote_device = 155230557Sjimharris isci_controller->remote_device[i]; 156230557Sjimharris 157230557Sjimharris if (remote_device != NULL && 158230557Sjimharris remote_device->domain == isci_domain) 159230557Sjimharris isci_remote_device_release_device_queue(remote_device); 160230557Sjimharris } 161230557Sjimharris} 162230557Sjimharris 163230557Sjimharris/** 164230557Sjimharris * @brief This callback method informs the framework user that the domain 165230557Sjimharris * is no longer ready. Thus, it is incapable of processing IO 166230557Sjimharris * requests for devices found inside it. 167230557Sjimharris * 168230557Sjimharris * @param[in] controller This parameter specifies the controller object 169230557Sjimharris * with which this callback is associated. 170230557Sjimharris * @param[in] domain This parameter specifies the domain object with 171230557Sjimharris * which this callback is associated. 172230557Sjimharris * 173230557Sjimharris * @return none 174230557Sjimharris */ 175230557Sjimharrisvoid 176230557Sjimharrisscif_cb_domain_not_ready(SCI_CONTROLLER_HANDLE_T controller, 177230557Sjimharris SCI_DOMAIN_HANDLE_T domain) 178230557Sjimharris{ 179230557Sjimharris 180230557Sjimharris} 181230557Sjimharris 182230557Sjimharris/** 183230557Sjimharris * @brief This callback method informs the framework user that a new 184230557Sjimharris * direct attached device was found in the domain. 185230557Sjimharris * 186230557Sjimharris * @param[in] controller This parameter specifies the controller object 187230557Sjimharris * with which this callback is associated. 188230557Sjimharris * @param[in] domain This parameter specifies the domain object with 189230557Sjimharris * which this callback is associated. 190230557Sjimharris * @param[in] sas_address This parameter specifies the SAS address of 191230557Sjimharris * the new device. 192230557Sjimharris * @param[in] protocols This parameter specifies the protocols 193230557Sjimharris * supported by the newly discovered device. 194230557Sjimharris * 195230557Sjimharris * @return none 196230557Sjimharris */ 197230557Sjimharrisvoid 198230557Sjimharrisscif_cb_domain_da_device_added(SCI_CONTROLLER_HANDLE_T controller, 199230557Sjimharris SCI_DOMAIN_HANDLE_T domain, SCI_SAS_ADDRESS_T *sas_address, 200230557Sjimharris SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T *protocols) 201230557Sjimharris{ 202230557Sjimharris struct ISCI_REMOTE_DEVICE *remote_device; 203230557Sjimharris struct ISCI_DOMAIN *isci_domain = 204230557Sjimharris (struct ISCI_DOMAIN *)sci_object_get_association(domain); 205230557Sjimharris 206233622Sjimharris /* 207233622Sjimharris * For direct-attached devices, do not pull the device object from 208233622Sjimharris * the pool. Rather, use the one stored in the domain object which 209233622Sjimharris * will ensure that we always get consistent target ids for direct 210233622Sjimharris * attached devices. 211233622Sjimharris */ 212233622Sjimharris remote_device = isci_domain->da_remote_device; 213230557Sjimharris 214230557Sjimharris scif_remote_device_construct(domain, 215230557Sjimharris (uint8_t*)remote_device + sizeof(struct ISCI_REMOTE_DEVICE), 216230557Sjimharris &(remote_device->sci_object)); 217230557Sjimharris 218230557Sjimharris sci_object_set_association(remote_device->sci_object, remote_device); 219230557Sjimharris 220230557Sjimharris scif_remote_device_da_construct(remote_device->sci_object, sas_address, 221230557Sjimharris protocols); 222230557Sjimharris 223230557Sjimharris /* We do not put the device in the ISCI_CONTROLLER's device array yet. 224230557Sjimharris * That will happen once the device becomes ready (see 225230557Sjimharris * scif_cb_remote_device_ready). 226230557Sjimharris */ 227230557Sjimharris 228230557Sjimharris remote_device->domain = isci_domain; 229230557Sjimharris} 230230557Sjimharris 231230557Sjimharris/** 232230557Sjimharris * @brief This callback method informs the framework user that a new 233230557Sjimharris * expander attached device was found in the domain. 234230557Sjimharris * 235230557Sjimharris * @param[in] controller This parameter specifies the controller object 236230557Sjimharris * with which this callback is associated. 237230557Sjimharris * @param[in] domain This parameter specifies the domain object with 238230557Sjimharris * which this callback is associated. 239230557Sjimharris * @param[in] containing_device This parameter specifies the remote 240230557Sjimharris * device that contains the device that was added. 241230557Sjimharris * @param[in] smp_response This parameter specifies the SMP response 242230557Sjimharris * data associated with the newly discovered device. 243230557Sjimharris * 244230557Sjimharris * @return none 245230557Sjimharris */ 246230557Sjimharrisvoid 247230557Sjimharrisscif_cb_domain_ea_device_added(SCI_CONTROLLER_HANDLE_T controller, 248230557Sjimharris SCI_DOMAIN_HANDLE_T domain, SCI_REMOTE_DEVICE_HANDLE_T containing_device, 249230557Sjimharris SMP_RESPONSE_DISCOVER_T *smp_response) 250230557Sjimharris{ 251230557Sjimharris struct ISCI_REMOTE_DEVICE *remote_device; 252230557Sjimharris struct ISCI_DOMAIN *isci_domain = 253230557Sjimharris (struct ISCI_DOMAIN *)sci_object_get_association(domain); 254230557Sjimharris struct ISCI_CONTROLLER *isci_controller = 255230557Sjimharris (struct ISCI_CONTROLLER *)sci_object_get_association(controller); 256230557Sjimharris 257230557Sjimharris sci_pool_get(isci_controller->remote_device_pool, remote_device); 258230557Sjimharris 259230557Sjimharris scif_remote_device_construct( domain, 260230557Sjimharris (uint8_t*)remote_device + sizeof(struct ISCI_REMOTE_DEVICE), 261230557Sjimharris &(remote_device->sci_object)); 262230557Sjimharris 263230557Sjimharris sci_object_set_association(remote_device->sci_object, remote_device); 264230557Sjimharris 265230557Sjimharris scif_remote_device_ea_construct(remote_device->sci_object, 266230557Sjimharris containing_device, smp_response); 267230557Sjimharris 268230557Sjimharris /* We do not put the device in the ISCI_CONTROLLER's device array yet. 269230557Sjimharris * That will happen once the device becomes ready (see 270230557Sjimharris * scif_cb_remote_device_ready). 271230557Sjimharris */ 272230557Sjimharris remote_device->domain = isci_domain; 273230557Sjimharris} 274230557Sjimharris 275230557Sjimharris/** 276230557Sjimharris * @brief This callback method informs the framework user that a device 277230557Sjimharris * has been removed from the domain. 278230557Sjimharris * 279230557Sjimharris * @param[in] controller This parameter specifies the controller object 280230557Sjimharris * with which this callback is associated. 281230557Sjimharris * @param[in] domain This parameter specifies the domain object with 282230557Sjimharris * which this callback is associated. 283230557Sjimharris * @param[in] remote_device This parameter specifies the device object with 284230557Sjimharris * which this callback is associated. 285230557Sjimharris * 286230557Sjimharris * @return none 287230557Sjimharris */ 288230557Sjimharrisvoid 289230557Sjimharrisscif_cb_domain_device_removed(SCI_CONTROLLER_HANDLE_T controller, 290230557Sjimharris SCI_DOMAIN_HANDLE_T domain, SCI_REMOTE_DEVICE_HANDLE_T remote_device) 291230557Sjimharris{ 292230557Sjimharris struct ISCI_REMOTE_DEVICE *isci_remote_device = 293230557Sjimharris (struct ISCI_REMOTE_DEVICE *)sci_object_get_association(remote_device); 294233622Sjimharris struct ISCI_DOMAIN *isci_domain = 295233622Sjimharris (struct ISCI_DOMAIN *)sci_object_get_association(domain); 296230557Sjimharris struct ISCI_CONTROLLER *isci_controller = 297230557Sjimharris (struct ISCI_CONTROLLER *)sci_object_get_association(controller); 298230557Sjimharris uint32_t path = cam_sim_path(isci_controller->sim); 299230557Sjimharris union ccb *ccb = xpt_alloc_ccb_nowait(); 300230557Sjimharris 301230557Sjimharris isci_controller->remote_device[isci_remote_device->index] = NULL; 302230557Sjimharris 303249468Smav xpt_create_path(&ccb->ccb_h.path, NULL, path, 304230557Sjimharris isci_remote_device->index, CAM_LUN_WILDCARD); 305230557Sjimharris 306230557Sjimharris xpt_rescan(ccb); 307230557Sjimharris 308230557Sjimharris scif_remote_device_destruct(remote_device); 309230557Sjimharris 310233622Sjimharris /* 311233622Sjimharris * Only put the remote device back into the pool if it was an 312233622Sjimharris * expander-attached device. 313233622Sjimharris */ 314233622Sjimharris if (isci_remote_device != isci_domain->da_remote_device) 315233622Sjimharris sci_pool_put(isci_controller->remote_device_pool, 316233622Sjimharris isci_remote_device); 317230557Sjimharris} 318230557Sjimharris 319230557Sjimharrisvoid 320230557Sjimharrisisci_domain_construct(struct ISCI_DOMAIN *domain, uint32_t domain_index, 321230557Sjimharris struct ISCI_CONTROLLER *controller) 322230557Sjimharris{ 323230557Sjimharris 324230557Sjimharris scif_controller_get_domain_handle( controller->scif_controller_handle, 325230557Sjimharris domain_index, &domain->sci_object); 326230557Sjimharris 327230557Sjimharris domain->index = domain_index; 328230557Sjimharris domain->controller = controller; 329230557Sjimharris sci_object_set_association(domain->sci_object, (void *)domain); 330230557Sjimharris} 331