4 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
34 #include <dev/isci/isci.h>
36 #include <cam/cam_periph.h>
37 #include <cam/cam_xpt_periph.h>
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>
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
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
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.
66 scif_cb_domain_change_notification(SCI_CONTROLLER_HANDLE_T controller,
67 SCI_DOMAIN_HANDLE_T domain)
69 struct ISCI_CONTROLLER *isci_controller =
70 (struct ISCI_CONTROLLER *)sci_object_get_association(controller);
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
78 if (isci_controller->is_started == TRUE)
79 scif_domain_discover(domain,
80 scif_domain_get_suggested_discover_timeout(domain),
85 * @brief This callback method informs the framework user that a previously
86 * requested discovery operation on the domain has completed.
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.
98 scif_cb_domain_discovery_complete(SCI_CONTROLLER_HANDLE_T controller,
99 SCI_DOMAIN_HANDLE_T domain, SCI_STATUS completion_status)
102 if(completion_status != SCI_SUCCESS)
103 isci_log_message(0, "ISCI",
104 "scif_cb_domain_discovery_complete status = 0x%x\n",
107 isci_controller_domain_discovery_complete(
108 (struct ISCI_CONTROLLER *)sci_object_get_association(controller),
109 (struct ISCI_DOMAIN *) sci_object_get_association(domain));
113 * @brief This callback method informs the framework user that a previously
114 * requested reset operation on the domain has completed.
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
126 scif_cb_domain_reset_complete(SCI_CONTROLLER_HANDLE_T controller,
127 SCI_DOMAIN_HANDLE_T domain, SCI_STATUS completion_status)
133 * @brief This callback method informs the framework user that the domain
134 * is ready and capable of processing IO requests for devices found
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.
145 scif_cb_domain_ready(SCI_CONTROLLER_HANDLE_T controller,
146 SCI_DOMAIN_HANDLE_T domain)
149 struct ISCI_DOMAIN *isci_domain = sci_object_get_association(domain);
150 struct ISCI_CONTROLLER *isci_controller =
151 sci_object_get_association(controller);
153 for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) {
154 struct ISCI_REMOTE_DEVICE *remote_device =
155 isci_controller->remote_device[i];
157 if (remote_device != NULL &&
158 remote_device->domain == isci_domain)
159 isci_remote_device_release_device_queue(remote_device);
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.
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.
176 scif_cb_domain_not_ready(SCI_CONTROLLER_HANDLE_T controller,
177 SCI_DOMAIN_HANDLE_T domain)
183 * @brief This callback method informs the framework user that a new
184 * direct attached device was found in the domain.
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
192 * @param[in] protocols This parameter specifies the protocols
193 * supported by the newly discovered device.
198 scif_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)
202 struct ISCI_REMOTE_DEVICE *remote_device;
203 struct ISCI_DOMAIN *isci_domain =
204 (struct ISCI_DOMAIN *)sci_object_get_association(domain);
207 * For direct-attached devices, do not pull the device object from
208 * the pool. Rather, use the one stored in the domain object which
209 * will ensure that we always get consistent target ids for direct
212 remote_device = isci_domain->da_remote_device;
214 scif_remote_device_construct(domain,
215 (uint8_t*)remote_device + sizeof(struct ISCI_REMOTE_DEVICE),
216 &(remote_device->sci_object));
218 sci_object_set_association(remote_device->sci_object, remote_device);
220 scif_remote_device_da_construct(remote_device->sci_object, sas_address,
223 /* We do not put the device in the ISCI_CONTROLLER's device array yet.
224 * That will happen once the device becomes ready (see
225 * scif_cb_remote_device_ready).
228 remote_device->domain = isci_domain;
232 * @brief This callback method informs the framework user that a new
233 * expander attached device was found in the domain.
235 * @param[in] controller This parameter specifies the controller object
236 * with which this callback is associated.
237 * @param[in] domain This parameter specifies the domain object with
238 * which this callback is associated.
239 * @param[in] containing_device This parameter specifies the remote
240 * device that contains the device that was added.
241 * @param[in] smp_response This parameter specifies the SMP response
242 * data associated with the newly discovered device.
247 scif_cb_domain_ea_device_added(SCI_CONTROLLER_HANDLE_T controller,
248 SCI_DOMAIN_HANDLE_T domain, SCI_REMOTE_DEVICE_HANDLE_T containing_device,
249 SMP_RESPONSE_DISCOVER_T *smp_response)
251 struct ISCI_REMOTE_DEVICE *remote_device;
252 struct ISCI_DOMAIN *isci_domain =
253 (struct ISCI_DOMAIN *)sci_object_get_association(domain);
254 struct ISCI_CONTROLLER *isci_controller =
255 (struct ISCI_CONTROLLER *)sci_object_get_association(controller);
257 sci_pool_get(isci_controller->remote_device_pool, remote_device);
259 scif_remote_device_construct( domain,
260 (uint8_t*)remote_device + sizeof(struct ISCI_REMOTE_DEVICE),
261 &(remote_device->sci_object));
263 sci_object_set_association(remote_device->sci_object, remote_device);
265 scif_remote_device_ea_construct(remote_device->sci_object,
266 containing_device, smp_response);
268 /* We do not put the device in the ISCI_CONTROLLER's device array yet.
269 * That will happen once the device becomes ready (see
270 * scif_cb_remote_device_ready).
272 remote_device->domain = isci_domain;
276 * @brief This callback method informs the framework user that a device
277 * has been removed from the domain.
279 * @param[in] controller This parameter specifies the controller object
280 * with which this callback is associated.
281 * @param[in] domain This parameter specifies the domain object with
282 * which this callback is associated.
283 * @param[in] remote_device This parameter specifies the device object with
284 * which this callback is associated.
289 scif_cb_domain_device_removed(SCI_CONTROLLER_HANDLE_T controller,
290 SCI_DOMAIN_HANDLE_T domain, SCI_REMOTE_DEVICE_HANDLE_T remote_device)
292 struct ISCI_REMOTE_DEVICE *isci_remote_device =
293 (struct ISCI_REMOTE_DEVICE *)sci_object_get_association(remote_device);
294 struct ISCI_DOMAIN *isci_domain =
295 (struct ISCI_DOMAIN *)sci_object_get_association(domain);
296 struct ISCI_CONTROLLER *isci_controller =
297 (struct ISCI_CONTROLLER *)sci_object_get_association(controller);
298 uint32_t path = cam_sim_path(isci_controller->sim);
299 union ccb *ccb = xpt_alloc_ccb_nowait();
301 isci_controller->remote_device[isci_remote_device->index] = NULL;
303 xpt_create_path(&ccb->ccb_h.path, NULL, path,
304 isci_remote_device->index, CAM_LUN_WILDCARD);
308 scif_remote_device_destruct(remote_device);
311 * Only put the remote device back into the pool if it was an
312 * expander-attached device.
314 if (isci_remote_device != isci_domain->da_remote_device)
315 sci_pool_put(isci_controller->remote_device_pool,
320 isci_domain_construct(struct ISCI_DOMAIN *domain, uint32_t domain_index,
321 struct ISCI_CONTROLLER *controller)
324 scif_controller_get_domain_handle( controller->scif_controller_handle,
325 domain_index, &domain->sci_object);
327 domain->index = domain_index;
328 domain->controller = controller;
329 sci_object_set_association(domain->sci_object, (void *)domain);