1 /*- 2 * This file is provided under a dual BSD/GPLv2 license. When using or 3 * redistributing this file, you may do so under either license. 4 * 5 * GPL LICENSE SUMMARY 6 * 7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of version 2 of the GNU General Public License as 11 * published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 21 * The full GNU General Public License is included in this distribution 22 * in the file called LICENSE.GPL. 23 * 24 * BSD LICENSE 25 * 26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 27 * All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 33 * * Redistributions of source code must retain the above copyright 34 * notice, this list of conditions and the following disclaimer. 35 * * Redistributions in binary form must reproduce the above copyright 36 * notice, this list of conditions and the following disclaimer in 37 * the documentation and/or other materials provided with the 38 * distribution. 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51 */ 52 53 #include <sys/cdefs.h> 54 __FBSDID("$FreeBSD$"); 55 56 /** 57 * @file 58 * 59 * @brief This file contains This file contains the SMP remote device 60 * object methods and it's state machines. 61 */ 62 63 #include <dev/isci/scil/scic_user_callback.h> 64 #include <dev/isci/scil/scic_sds_logger.h> 65 #include <dev/isci/scil/scic_sds_remote_device.h> 66 #include <dev/isci/scil/scic_sds_controller.h> 67 #include <dev/isci/scil/scic_sds_port.h> 68 #include <dev/isci/scil/scic_sds_request.h> 69 #include <dev/isci/scil/scu_event_codes.h> 70 #include <dev/isci/scil/scu_task_context.h> 71 #include <dev/isci/scil/scic_remote_device.h> 72 73 //***************************************************************************** 74 //* SMP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS 75 //***************************************************************************** 76 77 /** 78 * This method will handle the start io operation for a SMP device that is in 79 * the idle state. 80 * 81 * @param [in] device The device the io is sent to. 82 * @param [in] request The io to start. 83 * 84 * @return SCI_STATUS 85 */ 86 static 87 SCI_STATUS scic_sds_smp_remote_device_ready_idle_substate_start_io_handler( 88 SCI_BASE_REMOTE_DEVICE_T * device, 89 SCI_BASE_REQUEST_T * request 90 ) 91 { 92 SCI_STATUS status; 93 SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 94 SCIC_SDS_REQUEST_T * io_request = (SCIC_SDS_REQUEST_T *)request; 95 96 // Will the port allow the io request to start? 97 status = this_device->owning_port->state_handlers->start_io_handler( 98 this_device->owning_port, 99 this_device, 100 io_request 101 ); 102 103 if (status == SCI_SUCCESS) 104 { 105 status = 106 scic_sds_remote_node_context_start_io(this_device->rnc, io_request); 107 108 if (status == SCI_SUCCESS) 109 { 110 status = scic_sds_request_start(io_request); 111 } 112 113 if (status == SCI_SUCCESS) 114 { 115 this_device->working_request = io_request; 116 117 sci_base_state_machine_change_state( 118 &this_device->ready_substate_machine, 119 SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD 120 ); 121 } 122 123 scic_sds_remote_device_start_request(this_device, io_request, status); 124 } 125 126 return status; 127 } 128 129 130 //****************************************************************************** 131 //* SMP REMOTE DEVICE READY SUBSTATE CMD HANDLERS 132 //****************************************************************************** 133 /** 134 * This device is already handling a command it can not accept new commands 135 * until this one is complete. 136 * 137 * @param[in] device This is the device object that is receiving the IO. 138 * 139 * @param[in] request The io to start. 140 * 141 * @return SCI_STATUS 142 */ 143 static 144 SCI_STATUS scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler( 145 SCI_BASE_REMOTE_DEVICE_T * device, 146 SCI_BASE_REQUEST_T * request 147 ) 148 { 149 return SCI_FAILURE_INVALID_STATE; 150 } 151 152 153 /** 154 * @brief this is the complete_io_handler for smp device at ready cmd substate. 155 * 156 * @param[in] device This is the device object that is receiving the IO. 157 * @param[in] request The io to start. 158 * 159 * @return SCI_STATUS 160 */ 161 static 162 SCI_STATUS scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler( 163 SCI_BASE_REMOTE_DEVICE_T * device, 164 SCI_BASE_REQUEST_T * request 165 ) 166 { 167 SCI_STATUS status; 168 SCIC_SDS_REMOTE_DEVICE_T * this_device; 169 SCIC_SDS_REQUEST_T * the_request; 170 171 this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device; 172 the_request = (SCIC_SDS_REQUEST_T *)request; 173 174 status = scic_sds_io_request_complete(the_request); 175 176 if (status == SCI_SUCCESS) 177 { 178 status = scic_sds_port_complete_io( 179 this_device->owning_port, this_device, the_request); 180 181 if (status == SCI_SUCCESS) 182 { 183 scic_sds_remote_device_decrement_request_count(this_device); 184 sci_base_state_machine_change_state( 185 &this_device->ready_substate_machine, 186 SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE 187 ); 188 } 189 else 190 { 191 SCIC_LOG_ERROR(( 192 sci_base_object_get_logger(this_device), 193 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET, 194 "SCIC SDS Remote Device 0x%x io request 0x%x could not be completd on the port 0x%x failed with status %d.\n", 195 this_device, the_request, this_device->owning_port, status 196 )); 197 } 198 } 199 200 return status; 201 } 202 203 /** 204 * @brief This is frame handler for smp device ready cmd substate. 205 * 206 * @param[in] this_device This is the device object that is receiving the frame. 207 * @param[in] frame_index The index for the frame received. 208 * 209 * @return SCI_STATUS 210 */ 211 static 212 SCI_STATUS scic_sds_smp_remote_device_ready_cmd_substate_frame_handler( 213 SCIC_SDS_REMOTE_DEVICE_T * this_device, 214 U32 frame_index 215 ) 216 { 217 SCI_STATUS status; 218 219 /// The device does not process any UF received from the hardware while 220 /// in this state. All unsolicited frames are forwarded to the io request 221 /// object. 222 status = scic_sds_io_request_frame_handler( 223 this_device->working_request, 224 frame_index 225 ); 226 227 return status; 228 } 229 230 // --------------------------------------------------------------------------- 231 232 SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER_T 233 scic_sds_smp_remote_device_ready_substate_handler_table[ 234 SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES] = 235 { 236 // SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE 237 { 238 { 239 scic_sds_remote_device_default_start_handler, 240 scic_sds_remote_device_ready_state_stop_handler, 241 scic_sds_remote_device_default_fail_handler, 242 scic_sds_remote_device_default_destruct_handler, 243 scic_sds_remote_device_default_reset_handler, 244 scic_sds_remote_device_default_reset_complete_handler, 245 scic_sds_smp_remote_device_ready_idle_substate_start_io_handler, 246 scic_sds_remote_device_default_complete_request_handler, 247 scic_sds_remote_device_default_continue_request_handler, 248 scic_sds_remote_device_default_start_request_handler, 249 scic_sds_remote_device_default_complete_request_handler 250 }, 251 scic_sds_remote_device_default_suspend_handler, 252 scic_sds_remote_device_default_resume_handler, 253 scic_sds_remote_device_general_event_handler, 254 scic_sds_remote_device_default_frame_handler 255 }, 256 // SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD 257 { 258 { 259 scic_sds_remote_device_default_start_handler, 260 scic_sds_remote_device_ready_state_stop_handler, 261 scic_sds_remote_device_default_fail_handler, 262 scic_sds_remote_device_default_destruct_handler, 263 scic_sds_remote_device_default_reset_handler, 264 scic_sds_remote_device_default_reset_complete_handler, 265 scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler, 266 scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler, 267 scic_sds_remote_device_default_continue_request_handler, 268 scic_sds_remote_device_default_start_request_handler, 269 scic_sds_remote_device_default_complete_request_handler 270 }, 271 scic_sds_remote_device_default_suspend_handler, 272 scic_sds_remote_device_default_resume_handler, 273 scic_sds_remote_device_general_event_handler, 274 scic_sds_smp_remote_device_ready_cmd_substate_frame_handler 275 } 276 }; 277 278 /** 279 * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE enter method. This 280 * method sets the ready cmd substate handlers and reports the device as ready. 281 * 282 * @param[in] object This is the SCI_BASE_OBJECT which is cast into a 283 * SCIC_SDS_REMOTE_DEVICE. 284 * 285 * @return none 286 */ 287 static 288 void scic_sds_smp_remote_device_ready_idle_substate_enter( 289 SCI_BASE_OBJECT_T *object 290 ) 291 { 292 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object; 293 294 SET_STATE_HANDLER( 295 this_device, 296 scic_sds_smp_remote_device_ready_substate_handler_table, 297 SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE 298 ); 299 300 scic_cb_remote_device_ready( 301 scic_sds_remote_device_get_controller(this_device), this_device); 302 } 303 304 /** 305 * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD enter method. This 306 * method sets the remote device objects ready cmd substate handlers, and notify 307 * core user that the device is not ready. 308 * 309 * @param[in] object This is the SCI_BASE_OBJECT which is cast into a 310 * SCIC_SDS_REMOTE_DEVICE. 311 * 312 * @return none 313 */ 314 static 315 void scic_sds_smp_remote_device_ready_cmd_substate_enter( 316 SCI_BASE_OBJECT_T *object 317 ) 318 { 319 SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object; 320 321 ASSERT(this_device->working_request != NULL); 322 323 SET_STATE_HANDLER( 324 this_device, 325 scic_sds_smp_remote_device_ready_substate_handler_table, 326 SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD 327 ); 328 329 scic_cb_remote_device_not_ready( 330 scic_sds_remote_device_get_controller(this_device), 331 this_device, 332 SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED 333 ); 334 } 335 336 /** 337 * This is the SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_CMD exit method. 338 * 339 * @param[in] object This is the SCI_BASE_OBJECT which is cast into a 340 * SCIC_SDS_REMOTE_DEVICE. 341 * 342 * @return none 343 */ 344 static 345 void scic_sds_smp_remote_device_ready_cmd_substate_exit( 346 SCI_BASE_OBJECT_T *object 347 ) 348 { 349 SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object; 350 351 this_device->working_request = NULL; 352 } 353 354 // --------------------------------------------------------------------------- 355 356 SCI_BASE_STATE_T 357 scic_sds_smp_remote_device_ready_substate_table[ 358 SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES] = 359 { 360 { 361 SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE, 362 scic_sds_smp_remote_device_ready_idle_substate_enter, 363 NULL 364 }, 365 { 366 SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD, 367 scic_sds_smp_remote_device_ready_cmd_substate_enter, 368 scic_sds_smp_remote_device_ready_cmd_substate_exit 369 } 370 }; 371 372