sati_unmap.c revision 239545
1227569Sphilip/*- 2227569Sphilip * This file is provided under a dual BSD/GPLv2 license. When using or 3227569Sphilip * redistributing this file, you may do so under either license. 4227569Sphilip * 5227569Sphilip * GPL LICENSE SUMMARY 6227569Sphilip * 7227569Sphilip * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 8227569Sphilip * 9227569Sphilip * This program is free software; you can redistribute it and/or modify 10227569Sphilip * it under the terms of version 2 of the GNU General Public License as 11227569Sphilip * published by the Free Software Foundation. 12227569Sphilip * 13227569Sphilip * This program is distributed in the hope that it will be useful, but 14227569Sphilip * WITHOUT ANY WARRANTY; without even the implied warranty of 15227569Sphilip * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16227569Sphilip * General Public License for more details. 17227569Sphilip * 18227569Sphilip * You should have received a copy of the GNU General Public License 19227569Sphilip * along with this program; if not, write to the Free Software 20227569Sphilip * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 21227569Sphilip * The full GNU General Public License is included in this distribution 22227569Sphilip * in the file called LICENSE.GPL. 23227569Sphilip * 24227569Sphilip * BSD LICENSE 25227569Sphilip * 26227569Sphilip * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 27227569Sphilip * All rights reserved. 28227569Sphilip * 29227569Sphilip * Redistribution and use in source and binary forms, with or without 30227569Sphilip * modification, are permitted provided that the following conditions 31227569Sphilip * are met: 32227569Sphilip * 33227569Sphilip * * Redistributions of source code must retain the above copyright 34227569Sphilip * notice, this list of conditions and the following disclaimer. 35227569Sphilip * * Redistributions in binary form must reproduce the above copyright 36227569Sphilip * notice, this list of conditions and the following disclaimer in 37227569Sphilip * the documentation and/or other materials provided with the 38227569Sphilip * distribution. 39227569Sphilip * 40227569Sphilip * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41227569Sphilip * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42227569Sphilip * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43227569Sphilip * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44227569Sphilip * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45227569Sphilip * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46227569Sphilip * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47227569Sphilip * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48227569Sphilip * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49227569Sphilip * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50227569Sphilip * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51227569Sphilip */ 52227569Sphilip 53227569Sphilip#include <sys/cdefs.h> 54227569Sphilip__FBSDID("$FreeBSD: head/sys/dev/isci/scil/sati_unmap.c 239545 2012-08-21 22:28:14Z jimharris $"); 55227569Sphilip 56227569Sphilip/** 57227569Sphilip * @file 58227569Sphilip * @brief This file contains the method implementations required to 59227569Sphilip * translate the SCSI unmap command. 60227569Sphilip */ 61227569Sphilip 62227569Sphilip#if !defined(DISABLE_SATI_UNMAP) 63227569Sphilip 64227569Sphilip#include <dev/isci/scil/sati_unmap.h> 65227569Sphilip#include <dev/isci/scil/sati_callbacks.h> 66227569Sphilip#include <dev/isci/scil/sati_translator_sequence.h> 67227569Sphilip#include <dev/isci/scil/sati_util.h> 68227700Sphilip#include <dev/isci/scil/intel_ata.h> 69227569Sphilip#include <dev/isci/scil/intel_scsi.h> 70227569Sphilip#include <dev/isci/scil/intel_sat.h> 71227569Sphilip 72227569Sphilip//****************************************************************************** 73227569Sphilip//* P R I V A T E M E T H O D S 74227569Sphilip//****************************************************************************** 75227569Sphilip 76227569Sphilip/** 77227569Sphilip * @brief This method translates a given number of DSM 78227569Sphilip * requests into DSM blocks based on the devices logical block size 79227569Sphilip * 80227569Sphilip * @return Number of DSM blocks required for the DSM descriptor count 81227569Sphilip */ 82227569SphilipU32 sati_unmap_calculate_dsm_blocks( 83227569Sphilip SATI_TRANSLATOR_SEQUENCE_T * sequence, 84227569Sphilip U32 dsm_descriptor_count 85227569Sphilip) 86227569Sphilip{ 87227569Sphilip U32 blocks = (dsm_descriptor_count * sizeof(TRIM_PAIR))/sequence->device->logical_block_size; 88227569Sphilip if ((dsm_descriptor_count * sizeof(TRIM_PAIR)) % sequence->device->logical_block_size) 89227569Sphilip { 90227569Sphilip blocks++; 91227569Sphilip } 92227569Sphilip return blocks; 93227569Sphilip} 94227569Sphilip 95227569Sphilip/** 96227569Sphilip * @brief This method performs the SCSI Unmap command translation 97227569Sphilip * functionality. 98227569Sphilip * This includes: 99227569Sphilip * - setting the command register 100227569Sphilip * - setting the device head register 101227569Sphilip * - filling in fields in the SATI_TRANSLATOR_SEQUENCE object. 102227569Sphilip * For more information on the parameters passed to this method, 103227569Sphilip * please reference sati_translate_command(). 104227569Sphilip * 105227569Sphilip * @return Indicate if the method was successfully completed. 106227569Sphilip * @retval SATI_SUCCESS This is returned in all other cases. 107227569Sphilip */ 108227569SphilipSATI_STATUS sati_unmap_construct( 109227569Sphilip SATI_TRANSLATOR_SEQUENCE_T * sequence, 110227569Sphilip void * scsi_io, 111227569Sphilip void * ata_io, 112227569Sphilip U32 sector_count 113227569Sphilip) 114227569Sphilip{ 115227569Sphilip U8 * h2d_register_fis = sati_cb_get_h2d_register_fis_address(ata_io); 116227569Sphilip U8 * d2h_register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 117227569Sphilip 118227569Sphilip sati_set_ata_command(h2d_register_fis, ATA_DATA_SET_MANAGEMENT); 119227569Sphilip sati_set_ata_features(h2d_register_fis, 0x01); 120227569Sphilip sati_set_ata_sector_count(h2d_register_fis, (U8)sector_count); 121227569Sphilip sati_set_ata_device_head(h2d_register_fis, ATA_DEV_HEAD_REG_LBA_MODE_ENABLE); 122227569Sphilip 123227569Sphilip // Set the completion status since the core will not do that for 124227569Sphilip // the udma fast path. 125227569Sphilip sati_set_ata_status(d2h_register_fis, 0x00); 126227569Sphilip 127227569Sphilip // Set up the direction and protocol for SCIC 128227569Sphilip sequence->data_direction = SATI_DATA_DIRECTION_OUT; 129227569Sphilip sequence->protocol = SAT_PROTOCOL_UDMA_DATA_OUT; 130227569Sphilip // The UNMAP translation will always require a callback 131227569Sphilip // on every response so it can free memory if an error 132227569Sphilip // occurs. 133227569Sphilip sequence->is_translate_response_required = TRUE; 134227700Sphilip 135227569Sphilip ASSERT(sector_count < 0x100); 136227569Sphilip 137227569Sphilip return SATI_SUCCESS; 138227569Sphilip} 139227569Sphilip 140227569Sphilip/** 141227569Sphilip * @brief This method updates the unmap sequence state to the next 142227569Sphilip * unmap descriptor 143227569Sphilip * 144227569Sphilip * @return Indicate if the method was successfully completed. 145227569Sphilip * @retval SATI_SUCCESS This is returned in all other cases. 146227569Sphilip */ 147227569SphilipSATI_STATUS sati_unmap_load_next_descriptor( 148227569Sphilip SATI_TRANSLATOR_SEQUENCE_T * sequence, 149227569Sphilip void * scsi_io 150227569Sphilip) 151227569Sphilip{ 152227569Sphilip SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state; 153227569Sphilip U32 index; 154227569Sphilip U8 unmap_block_descriptor[16]; 155227569Sphilip 156227569Sphilip unmap_process_state = &sequence->command_specific_data.unmap_process_state; 157227569Sphilip 158227569Sphilip // Load the next descriptor 159227569Sphilip for(index = unmap_process_state->current_unmap_block_descriptor_index; 160227569Sphilip index < unmap_process_state->current_unmap_block_descriptor_index + 161227569Sphilip SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR; 162227569Sphilip index++) 163227569Sphilip { 164227569Sphilip sati_get_data_byte(sequence, 165227569Sphilip scsi_io, 166227569Sphilip index, 167227569Sphilip &unmap_block_descriptor[index-unmap_process_state->current_unmap_block_descriptor_index]); 168227569Sphilip } 169227569Sphilip 170227569Sphilip // Update the internal state for the next translation pass 171227569Sphilip unmap_process_state->current_lba_count = (unmap_block_descriptor[8] << 24) | 172227569Sphilip (unmap_block_descriptor[9] << 16) | 173227569Sphilip (unmap_block_descriptor[10] << 8) | 174227569Sphilip (unmap_block_descriptor[11]); 175227569Sphilip unmap_process_state->current_lba = ((SATI_LBA)(unmap_block_descriptor[0]) << 56) | 176227569Sphilip ((SATI_LBA)(unmap_block_descriptor[1]) << 48) | 177227569Sphilip ((SATI_LBA)(unmap_block_descriptor[2]) << 40) | 178227569Sphilip ((SATI_LBA)(unmap_block_descriptor[3]) << 32) | 179227569Sphilip ((SATI_LBA)(unmap_block_descriptor[4]) << 24) | 180227569Sphilip ((SATI_LBA)(unmap_block_descriptor[5]) << 16) | 181227569Sphilip ((SATI_LBA)(unmap_block_descriptor[6]) << 8) | 182227569Sphilip ((SATI_LBA)(unmap_block_descriptor[7])); 183227569Sphilip unmap_process_state->next_lba = 0; 184227569Sphilip 185227569Sphilip // Update the index for the next descriptor to translate 186227569Sphilip unmap_process_state->current_unmap_block_descriptor_index += SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR; 187227569Sphilip 188227569Sphilip return SATI_SUCCESS; 189227569Sphilip} 190227569Sphilip 191227569Sphilip/** 192227569Sphilip * @brief This method determines the max number of blocks of DSM data 193227569Sphilip * that can be satisfied by the device and the SW 194227569Sphilip * 195227569Sphilip * @return Number of blocks supported 196227569Sphilip * @retval Number of blocks supported 197227569Sphilip */ 198227569SphilipU32 sati_unmap_get_max_buffer_size_in_blocks( 199227569Sphilip SATI_TRANSLATOR_SEQUENCE_T * sequence 200227569Sphilip) 201227569Sphilip{ 202227569Sphilip // Currently this SATI implementation only supports a single 203227569Sphilip // 4k block of memory for the DMA write operation for simplicity 204227569Sphilip // (no need to handle more than one SG element). 205227569Sphilip // Since most run time UNMAP requests use 1K or less buffer space, 206227569Sphilip // there is no performance degradation with only supporting a 207227569Sphilip // single physical page. For best results allocate the maximum 208227569Sphilip // amount of memory the device can handle up to the maximum of 4K. 209227569Sphilip return MIN(SATI_DSM_MAX_BUFFER_SIZE/sequence->device->logical_block_size, 210227569Sphilip sequence->device->max_lba_range_entry_blocks); 211227569Sphilip} 212227569Sphilip 213227569Sphilip/** 214227569Sphilip * @brief This method will be called before starting the first unmap translation 215227569Sphilip * 216227569Sphilip * @return Indicate if the translation was successful. 217227569Sphilip * @retval SATI_SUCCESS This is returned if the command translation was 218227569Sphilip * successful and no further processing. 219227569Sphilip * @retval SATI_COMPLETE - The initial processing was completed successfully 220227569Sphilip * @retval SATI_FAILURE_CHECK_RESPONSE_DATA - Failed the initial processing 221227569Sphilip */ 222227569SphilipSATI_STATUS sati_unmap_initial_processing( 223227569Sphilip SATI_TRANSLATOR_SEQUENCE_T * sequence, 224227569Sphilip void * scsi_io, 225227569Sphilip void * ata_io 226227569Sphilip) 227227569Sphilip{ 228227569Sphilip SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state; 229227569Sphilip U8 * cdb; 230227569Sphilip U16 unmap_length; 231227569Sphilip U32 descriptor_length; 232227569Sphilip U32 index; 233227569Sphilip U32 max_dsm_blocks; 234227569Sphilip U8 unmap_param_list[8]; 235227569Sphilip 236227569Sphilip unmap_process_state = &sequence->command_specific_data.unmap_process_state; 237227569Sphilip 238227569Sphilip // Set up the sequence type for unmap translation 239227569Sphilip sequence->type = SATI_SEQUENCE_UNMAP; 240227569Sphilip 241227569Sphilip // Make sure the device is TRIM capable 242227569Sphilip if ((sequence->device->capabilities & SATI_DEVICE_CAP_DSM_TRIM_SUPPORT) 243227569Sphilip != SATI_DEVICE_CAP_DSM_TRIM_SUPPORT) 244227569Sphilip { 245227569Sphilip // Can't send TRIM request to device that does not support it 246227569Sphilip sati_scsi_sense_data_construct( 247227569Sphilip sequence, 248227569Sphilip scsi_io, 249227569Sphilip SCSI_STATUS_CHECK_CONDITION, 250227569Sphilip SCSI_SENSE_ILLEGAL_REQUEST, 251227569Sphilip SCSI_ASC_INVALID_FIELD_IN_CDB, 252227569Sphilip SCSI_ASCQ_INVALID_FIELD_IN_CDB 253227569Sphilip ); 254227569Sphilip return SATI_FAILURE_CHECK_RESPONSE_DATA; 255227569Sphilip } 256227569Sphilip 257227569Sphilip // get the amount of data being sent from the cdb 258227569Sphilip cdb = sati_cb_get_cdb_address(scsi_io); 259227569Sphilip unmap_length = (sati_get_cdb_byte(cdb, 7) << 8) | sati_get_cdb_byte(cdb, 8); 260227569Sphilip 261227569Sphilip // If nothing has been requested return success now. 262227569Sphilip if (unmap_length == 0) 263227569Sphilip { 264227569Sphilip // SAT: This is not an error 265227569Sphilip return SATI_SUCCESS; 266227569Sphilip } 267227569Sphilip if (unmap_length < SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST) 268227569Sphilip { 269227569Sphilip // Not enough length specified in the CDB 270227569Sphilip sati_scsi_sense_data_construct( 271227569Sphilip sequence, 272227569Sphilip scsi_io, 273227569Sphilip SCSI_STATUS_CHECK_CONDITION, 274227569Sphilip SCSI_SENSE_ILLEGAL_REQUEST, 275227569Sphilip SCSI_ASC_INVALID_FIELD_IN_CDB, 276227569Sphilip SCSI_ASCQ_INVALID_FIELD_IN_CDB 277227569Sphilip ); 278227569Sphilip return SATI_FAILURE_CHECK_RESPONSE_DATA; 279227569Sphilip } 280227569Sphilip 281227569Sphilip sequence->allocation_length = unmap_length; 282227569Sphilip 283227569Sphilip // Get the unmap parameter header 284227569Sphilip for(index = 0; index < SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST; index++) 285227569Sphilip { 286227569Sphilip sati_get_data_byte(sequence, scsi_io, index, &unmap_param_list[index]); 287227569Sphilip } 288227569Sphilip descriptor_length = (unmap_param_list[2] << 8) | unmap_param_list[3]; 289227569Sphilip 290227569Sphilip // Check length again 291227569Sphilip if (descriptor_length == 0) 292227569Sphilip { 293227569Sphilip // SAT: This is not an error 294227569Sphilip return SATI_SUCCESS; 295227569Sphilip } 296227569Sphilip 297227569Sphilip if ((U32)(unmap_length - SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST) < descriptor_length) 298227569Sphilip { 299227569Sphilip // Not enough length specified in the CDB 300227569Sphilip sati_scsi_sense_data_construct( 301227569Sphilip sequence, 302227569Sphilip scsi_io, 303227569Sphilip SCSI_STATUS_CHECK_CONDITION, 304227569Sphilip SCSI_SENSE_ILLEGAL_REQUEST, 305227569Sphilip SCSI_ASC_INVALID_FIELD_IN_CDB, 306227569Sphilip SCSI_ASCQ_INVALID_FIELD_IN_CDB 307227569Sphilip ); 308227569Sphilip return SATI_FAILURE_CHECK_RESPONSE_DATA; 309227569Sphilip } 310227569Sphilip 311227569Sphilip // Save the maximum unmap block descriptors in this request 312227569Sphilip unmap_process_state->max_unmap_block_descriptors = 313227569Sphilip descriptor_length/SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR; 314227569Sphilip 315227569Sphilip // Determine the maximum size of the write buffer that will be required 316227569Sphilip // for the translation in terms of number of blocks 317227569Sphilip max_dsm_blocks = sati_unmap_get_max_buffer_size_in_blocks(sequence); 318227569Sphilip 319227569Sphilip // Save the maximum number of DSM descriptors we can send during the translation 320227569Sphilip unmap_process_state->max_lba_range_entries = 321227569Sphilip (max_dsm_blocks*sequence->device->logical_block_size)/sizeof(TRIM_PAIR); 322227569Sphilip 323227569Sphilip // Get the write buffer for the translation 324227569Sphilip sati_cb_allocate_dma_buffer( 325227569Sphilip scsi_io, 326227569Sphilip max_dsm_blocks*sequence->device->logical_block_size, 327227569Sphilip &(unmap_process_state->virtual_unmap_buffer), 328227569Sphilip &(unmap_process_state->physical_unmap_buffer_low), 329227569Sphilip &(unmap_process_state->physical_unmap_buffer_high)); 330227569Sphilip 331227569Sphilip // Makes sure we have a buffer 332227569Sphilip if (unmap_process_state->virtual_unmap_buffer == NULL) 333227569Sphilip { 334227569Sphilip // Resource failure 335227569Sphilip sati_scsi_sense_data_construct( 336227569Sphilip sequence, 337227569Sphilip scsi_io, 338227569Sphilip SCSI_STATUS_BUSY, 339227569Sphilip SCSI_SENSE_NO_SENSE, 340227569Sphilip SCSI_ASC_NO_ADDITIONAL_SENSE, 341227569Sphilip SCSI_ASCQ_NO_ADDITIONAL_SENSE 342227569Sphilip ); 343227569Sphilip return SATI_FAILURE_CHECK_RESPONSE_DATA; 344227569Sphilip } 345227569Sphilip 346227569Sphilip // Get the first SGL entry. This code will only use one 4K page so will 347227569Sphilip // only utilize the first sge. 348227569Sphilip sati_cb_sgl_next_sge(scsi_io, 349227569Sphilip ata_io, 350227569Sphilip NULL, 351227569Sphilip &(unmap_process_state->unmap_buffer_sgl_pair)); 352227569Sphilip 353227569Sphilip // Load the first descriptor to start the translation loop 354227569Sphilip unmap_process_state->current_unmap_block_descriptor_index = 355227569Sphilip SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST; 356227569Sphilip sati_unmap_load_next_descriptor(sequence,scsi_io); 357227569Sphilip 358227569Sphilip // Next state will be incomplete since translation 359227569Sphilip // will require a callback and possibly more requests. 360227569Sphilip sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE; 361227569Sphilip 362227569Sphilip return SATI_COMPLETE; 363227569Sphilip} 364227569Sphilip 365227569Sphilip/** 366227569Sphilip * @brief This method will process each unmap sequence. 367227569Sphilip * 368227569Sphilip * @return Indicate if the translation was successful. 369227569Sphilip * @retval SATI_SUCCESS 370227569Sphilip */ 371227569SphilipSATI_STATUS sati_unmap_process( 372227569Sphilip SATI_TRANSLATOR_SEQUENCE_T * sequence, 373227569Sphilip void * scsi_io, 374227569Sphilip void * ata_io 375227569Sphilip) 376227569Sphilip{ 377227569Sphilip SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state; 378227569Sphilip SATI_LBA dsm_descriptor_lba_count; 379227569Sphilip U32 dsm_descriptor; 380227569Sphilip U32 dsm_bytes; 381227569Sphilip U32 dsm_remainder_bytes; 382227569Sphilip U32 dsm_blocks; 383227569Sphilip U32 max_dsm_blocks; 384227569Sphilip 385227569Sphilip unmap_process_state = &sequence->command_specific_data.unmap_process_state; 386227569Sphilip 387227569Sphilip // Set up the starting address of the buffer for this portion of the translation 388227569Sphilip unmap_process_state->current_dsm_descriptor = unmap_process_state->virtual_unmap_buffer; 389227569Sphilip dsm_descriptor = 0; 390227569Sphilip 391227569Sphilip // Translate as much as we can 392227569Sphilip while ((dsm_descriptor < unmap_process_state->max_lba_range_entries) && 393227569Sphilip (unmap_process_state->current_lba_count > 0)) { 394227569Sphilip // See if the LBA count will fit in to a single descriptor 395227569Sphilip if (unmap_process_state->current_lba_count > SATI_DSM_MAX_SECTOR_COUNT) { 396227569Sphilip // Can't fit all of the lbas for this descriptor in to 397227569Sphilip // one DSM request. Adjust the current LbaCount and total 398227569Sphilip // remaining for the next descriptor 399227569Sphilip dsm_descriptor_lba_count = SATI_DSM_MAX_SECTOR_COUNT; 400227569Sphilip unmap_process_state->current_lba_count -= SATI_DSM_MAX_SECTOR_COUNT; 401227569Sphilip unmap_process_state->next_lba = 402227569Sphilip unmap_process_state->current_lba + SATI_DSM_MAX_SECTOR_COUNT; 403227569Sphilip } else { 404227569Sphilip // It all fits in to one descriptor 405227569Sphilip dsm_descriptor_lba_count = unmap_process_state->current_lba_count; 406227569Sphilip unmap_process_state->current_lba_count = 0; 407227569Sphilip } 408227569Sphilip 409227569Sphilip // Fill in the ATA DSM descriptor 410227569Sphilip ((PTRIM_PAIR)(unmap_process_state->current_dsm_descriptor))->sector_address = 411227569Sphilip unmap_process_state->current_lba; 412227569Sphilip ((PTRIM_PAIR)(unmap_process_state->current_dsm_descriptor))->sector_count = 413227569Sphilip dsm_descriptor_lba_count; 414227569Sphilip 415227569Sphilip // See if we can move on to the next descriptor 416227569Sphilip if (unmap_process_state->current_lba_count == 0) { 417227569Sphilip // See if there is another descriptor 418227569Sphilip --unmap_process_state->max_unmap_block_descriptors; 419227569Sphilip if (unmap_process_state->max_unmap_block_descriptors > 0) { 420227569Sphilip // Move on to the next descriptor 421227569Sphilip sati_unmap_load_next_descriptor(sequence,scsi_io); 422227569Sphilip } 423227569Sphilip } else { 424227569Sphilip // Move to the next LBA in this descriptor 425227569Sphilip unmap_process_state->current_lba = unmap_process_state->next_lba; 426227569Sphilip } 427227569Sphilip 428227569Sphilip // Make sure the LBA does not exceed 48 bits... 429227569Sphilip ASSERT(unmap_process_state->current_lba <= SATI_DSM_MAX_SECTOR_ADDRESS); 430227569Sphilip 431227569Sphilip // Increment the number of descriptors used and point to the next entry 432227569Sphilip dsm_descriptor++; 433227569Sphilip unmap_process_state->current_dsm_descriptor = 434227569Sphilip (U8 *)(unmap_process_state->current_dsm_descriptor) + sizeof(TRIM_PAIR); 435227569Sphilip } 436227569Sphilip 437227569Sphilip // Calculate number of blocks we have filled in 438227569Sphilip dsm_blocks = sati_unmap_calculate_dsm_blocks(sequence,dsm_descriptor); 439227569Sphilip dsm_bytes = dsm_blocks * sequence->device->logical_block_size; 440227569Sphilip max_dsm_blocks = sati_unmap_get_max_buffer_size_in_blocks(sequence); 441227569Sphilip 442227569Sphilip // The current_dsm_descriptor points to the next location in the buffer 443227569Sphilip // Get the remaining bytes from the last translated descriptor 444227569Sphilip // to the end of the 4k buffer. 445227569Sphilip dsm_remainder_bytes = sequence->device->logical_block_size; 446227569Sphilip dsm_remainder_bytes -= (U32)((POINTER_UINT)unmap_process_state->current_dsm_descriptor & 447227569Sphilip (sequence->device->logical_block_size-1)); 448227569Sphilip 449227569Sphilip // If there was no remainder, the complete buffer was filled in. 450227569Sphilip if (dsm_remainder_bytes != sequence->device->logical_block_size) 451227569Sphilip { 452227569Sphilip // Add on the remaining unfilled blocks 453227569Sphilip dsm_remainder_bytes += (sequence->device->logical_block_size * (max_dsm_blocks - dsm_blocks)); 454227569Sphilip 455227569Sphilip // According to ATA-8, if the DSM buffer is not completely filled with 456227569Sphilip // valid DSM descriptor data, the remaining portion of the 457227569Sphilip // buffer must be filled in with zeros. 458227569Sphilip memset((U8 *)unmap_process_state->current_dsm_descriptor, 0, dsm_remainder_bytes); 459227569Sphilip } 460227569Sphilip 461227569Sphilip // Tell scic to utilize this sgl pair for write DMA processing of 462227569Sphilip // the SCSI UNMAP translation with the total number of bytes for this transfer 463227569Sphilip sati_cb_sge_write(unmap_process_state->unmap_buffer_sgl_pair, 464227700Sphilip unmap_process_state->physical_unmap_buffer_low, 465227569Sphilip unmap_process_state->physical_unmap_buffer_high, 466227569Sphilip dsm_bytes); 467227569Sphilip 468227569Sphilip // Construct the unmap ATA request 469227569Sphilip sati_unmap_construct(sequence, 470227569Sphilip scsi_io, 471227569Sphilip ata_io, 472227569Sphilip dsm_blocks); 473227569Sphilip 474227569Sphilip // Determine sequence next state based on whether there is more translation 475227569Sphilip // to complete 476227569Sphilip if (unmap_process_state->current_lba_count == 0) 477227569Sphilip { 478227569Sphilip // used for completion routine to determine if there is more processing 479227569Sphilip sequence->state = SATI_SEQUENCE_STATE_FINAL; 480227569Sphilip } 481227569Sphilip // This requests has already translated the SGL, have SCIC skip SGL translataion 482227569Sphilip return SATI_SUCCESS_SGL_TRANSLATED; 483227569Sphilip} 484227569Sphilip 485227569Sphilip//****************************************************************************** 486227569Sphilip//* P U B L I C M E T H O D S 487227569Sphilip//****************************************************************************** 488227569Sphilip 489227569Sphilip/** 490227569Sphilip * @brief This method will handle termination of the 491227569Sphilip * SCSI unmap translation and frees previously allocated 492227569Sphilip * dma buffer. 493227569Sphilip * 494227569Sphilip * @return None 495227569Sphilip */ 496227569Sphilipvoid sati_unmap_terminate( 497227569Sphilip SATI_TRANSLATOR_SEQUENCE_T * sequence, 498227569Sphilip void * scsi_io, 499227569Sphilip void * ata_io 500227569Sphilip) 501227569Sphilip{ 502227569Sphilip SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state; 503227569Sphilip unmap_process_state = &sequence->command_specific_data.unmap_process_state; 504227569Sphilip 505227569Sphilip if (unmap_process_state->virtual_unmap_buffer != NULL) 506227569Sphilip { 507227569Sphilip sati_cb_free_dma_buffer(scsi_io, unmap_process_state->virtual_unmap_buffer); 508227569Sphilip unmap_process_state->virtual_unmap_buffer = NULL; 509227569Sphilip } 510227569Sphilip} 511227569Sphilip 512227569Sphilip/** 513227569Sphilip * @brief This method will translate the SCSI Unmap command 514227569Sphilip * into corresponding ATA commands. Depending upon the capabilities 515227569Sphilip * supported by the target different ATA commands can be selected. 516227569Sphilip * Additionally, in some cases more than a single ATA command may 517227569Sphilip * be required. 518227569Sphilip * 519227569Sphilip * @return Indicate if the command translation succeeded. 520227569Sphilip * @retval SATI_SUCCESS This is returned if the command translation was 521227569Sphilip * successful. 522227569Sphilip * @retval SATI_COMPLETE This is returned if the command translation was 523227569Sphilip * successful and no ATA commands need to be set. 524227569Sphilip * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if 525227569Sphilip * sense data has been created as a result of something specified 526227569Sphilip * in the parameter data fields. 527227569Sphilip */ 528227569SphilipSATI_STATUS sati_unmap_translate_command( 529227569Sphilip SATI_TRANSLATOR_SEQUENCE_T * sequence, 530227569Sphilip void * scsi_io, 531227569Sphilip void * ata_io 532227569Sphilip) 533227569Sphilip{ 534227569Sphilip SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA; 535227569Sphilip SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state; 536227569Sphilip 537227569Sphilip unmap_process_state = &sequence->command_specific_data.unmap_process_state; 538227569Sphilip 539227569Sphilip // Determine if this is the first step in the unmap sequence 540227569Sphilip if ( sequence->state == SATI_SEQUENCE_STATE_INITIAL ) 541227569Sphilip { 542227569Sphilip status = sati_unmap_initial_processing(sequence,scsi_io,ata_io); 543227569Sphilip if (status != SATI_COMPLETE) 544227569Sphilip { 545227569Sphilip return status; 546227569Sphilip } 547227569Sphilip } 548227569Sphilip // Translate the next portion of the UNMAP request 549227569Sphilip return sati_unmap_process(sequence, scsi_io, ata_io); 550227569Sphilip} 551227569Sphilip 552227569Sphilip/** 553227569Sphilip * @brief This method will translate the ATA command register FIS 554227569Sphilip * response into an appropriate SCSI response for Unmap. 555227569Sphilip * For more information on the parameters passed to this method, 556227569Sphilip * please reference sati_translate_response(). 557 * 558 * @return Indicate if the response translation succeeded. 559 * @retval SATI_SUCCESS This is returned if the command translation was 560 * successful. 561 * @retval SATI_COMPLETE This is returned if the command translation was 562 * successful and no ATA commands need to be set. 563 * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if 564 * sense data has been created as a result of something specified 565 * in the parameter data fields. 566 */ 567SATI_STATUS sati_unmap_translate_response( 568 SATI_TRANSLATOR_SEQUENCE_T * sequence, 569 void * scsi_io, 570 void * ata_io 571) 572{ 573 U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io); 574 SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state; 575 SATI_STATUS sati_status = SATI_COMPLETE; 576 577 unmap_process_state = &sequence->command_specific_data.unmap_process_state; 578 579 if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT) 580 { 581 sequence->state = SATI_SEQUENCE_STATE_FINAL; 582 sati_scsi_sense_data_construct( 583 sequence, 584 scsi_io, 585 SCSI_STATUS_CHECK_CONDITION, 586 SCSI_SENSE_ABORTED_COMMAND, 587 SCSI_ASC_NO_ADDITIONAL_SENSE, 588 SCSI_ASCQ_NO_ADDITIONAL_SENSE 589 ); 590 // All done, terminate the translation 591 sati_unmap_terminate(sequence, scsi_io, ata_io); 592 } 593 else 594 { 595 if (sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE) 596 { 597 // All done, terminate the translation 598 sati_unmap_terminate(sequence, scsi_io, ata_io); 599 } 600 else 601 { 602 // Still translating 603 sati_status = SATI_SEQUENCE_STATE_INCOMPLETE; 604 } 605 } 606 return sati_status; 607} 608 609#endif // !defined(DISABLE_SATI_UNMAP) 610