/** * * * @param[in] this_device * @param[in] frame_index * * @return SCI_STATUS */ static SCI_STATUS scic_sds_stp_remote_device_ready_ncq_substate_frame_handler( SCIC_SDS_REMOTE_DEVICE_T * this_device, U32 frame_index ) { SCI_STATUS status; SATA_FIS_HEADER_T * frame_header; status = scic_sds_unsolicited_frame_control_get_header( &(scic_sds_remote_device_get_controller(this_device)->uf_control), frame_index, (void **)&frame_header ); if (status == SCI_SUCCESS) { if ( (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS) && (frame_header->status & ATA_STATUS_REG_ERROR_BIT) ) { this_device->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; /** @todo Check sactive and complete associated IO if any. */ sci_base_state_machine_change_state( &this_device->ready_substate_machine, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR ); } else if ( (frame_header->fis_type == SATA_FIS_TYPE_REGD2H) && (frame_header->status & ATA_STATUS_REG_ERROR_BIT) ) { // Some devices return D2H FIS when an NCQ error is detected. // Treat this like an SDB error FIS ready reason. this_device->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; sci_base_state_machine_change_state( &this_device->ready_substate_machine, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR ); } else { status = SCI_FAILURE; } scic_sds_controller_release_frame( scic_sds_remote_device_get_controller(this_device), frame_index ); } return status; }
/** * @brief This method processes an unsolicited frame while the SMP request is * waiting for a response frame. It will copy the response data, release * the unsolicited frame, and transition the request to the * SCI_BASE_REQUEST_STATE_COMPLETED state. * * @param[in] this_request This parameter specifies the request for which * the unsolicited frame was received. * @param[in] frame_index This parameter indicates the unsolicited frame * index that should contain the response. * * @return This method returns an indication of whether the response * frame was handled successfully or not. * @retval SCI_SUCCESS Currently this value is always returned and indicates * successful processing of the TC response. */ static SCI_STATUS scic_sds_smp_request_await_response_frame_handler( SCIC_SDS_REQUEST_T * this_request, U32 frame_index ) { SCI_STATUS status; void * frame_header; SMP_RESPONSE_HEADER_T * this_frame_header; U8 * user_smp_buffer = this_request->response_buffer; // Save off the controller, so that we do not touch the request after it // is completed. SCIC_SDS_CONTROLLER_T * controller = scic_sds_request_get_controller(this_request); SCIC_LOG_TRACE(( sci_base_object_get_logger(this_request), SCIC_LOG_OBJECT_SMP_IO_REQUEST, "scic_sds_smp_request_await_response_frame_handler(0x%x, 0x%x) enter\n", this_request, frame_index )); status = scic_sds_unsolicited_frame_control_get_header( &(controller->uf_control), frame_index, &frame_header ); //byte swap the header. scic_word_copy_with_swap( (U32*) user_smp_buffer, frame_header, sizeof(SMP_RESPONSE_HEADER_T)/sizeof(U32) ); this_frame_header = (SMP_RESPONSE_HEADER_T*) user_smp_buffer; if (this_frame_header->smp_frame_type == SMP_FRAME_TYPE_RESPONSE) { void * smp_response_buffer; status = scic_sds_unsolicited_frame_control_get_buffer( &(controller->uf_control), frame_index, &smp_response_buffer ); scic_word_copy_with_swap( (U32*) (user_smp_buffer + sizeof(SMP_RESPONSE_HEADER_T)), smp_response_buffer, sizeof(SMP_RESPONSE_BODY_T)/sizeof(U32) ); if (this_frame_header->function == SMP_FUNCTION_DISCOVER) { SMP_RESPONSE_T * this_smp_response; this_smp_response = (SMP_RESPONSE_T *)user_smp_buffer; // Some expanders only report an attached SATA device, and // not an STP target. Since the core depends on the STP // target attribute to correctly build I/O, set the bit now // if necessary. if (this_smp_response->response.discover.protocols.u.bits.attached_sata_device && !this_smp_response->response.discover.protocols.u.bits.attached_stp_target) { this_smp_response->response.discover.protocols.u.bits.attached_stp_target = 1; SCIC_LOG_TRACE(( sci_base_object_get_logger(this_request), SCIC_LOG_OBJECT_SMP_IO_REQUEST, "scic_sds_smp_request_await_response_frame_handler(0x%x) Found SATA dev, setting STP bit.\n", this_request )); } } //Don't need to copy to user space. User instead will refer to //core request's response buffer. //copy the smp response to framework smp request's response buffer. //scic_sds_smp_request_copy_response(this_request); scic_sds_request_set_status( this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS ); sci_base_state_machine_change_state( &this_request->started_substate_machine, SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION ); } else { // This was not a response frame why did it get forwarded? SCIC_LOG_ERROR(( sci_base_object_get_logger(this_request), SCIC_LOG_OBJECT_SMP_IO_REQUEST, "SCIC SMP Request 0x%08x received unexpected frame %d type 0x%02x\n", this_request, frame_index, this_frame_header->smp_frame_type )); scic_sds_request_set_status( this_request, SCU_TASK_DONE_SMP_FRM_TYPE_ERR, SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR ); sci_base_state_machine_change_state( &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED ); } scic_sds_controller_release_frame( controller, frame_index ); return SCI_SUCCESS; }