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