sati_inquiry.c revision 331722
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: stable/11/sys/dev/isci/scil/sati_inquiry.c 331722 2018-03-29 02:50:57Z eadler $");
55
56/**
57 * @file
58 *
59 * @brief This file contains the method implementations required to
60 *        translate the SCSI inquiry command.
61 *        The following (VPD) pages are currently supported:
62 *        - Standard
63 *        - Supported Pages
64 *        - Unit Serial Number
65 *        - Device Identification
66 */
67
68#if !defined(DISABLE_SATI_INQUIRY)
69
70#include <dev/isci/scil/sati_inquiry.h>
71#include <dev/isci/scil/sati_callbacks.h>
72#include <dev/isci/scil/sati_util.h>
73#include <dev/isci/scil/intel_ata.h>
74#include <dev/isci/scil/intel_scsi.h>
75
76//******************************************************************************
77//* P R I V A T E   M E T H O D S
78//******************************************************************************
79/**
80* @brief This method builds the SCSI data associated with the SATI product
81*        revision that is commonly used on the Standard inquiry response and
82*        the ATA information page.
83*
84* @param[in]  sequence This parameter specifies the translator sequence
85*             object to be utilized during data translation.
86* @param[in]  ata_input_data This parameter specifies ata data received from
87*             the remote device.
88* @param[out] scsi_io This parameter specifies the user IO request for
89*             which to construct the standard inquiry data.
90*
91* @return none
92*/
93static
94void sati_inquiry_construct_product_revision(
95   SATI_TRANSLATOR_SEQUENCE_T * sequence,
96   void                       * ata_input_data,
97   void                       * scsi_io
98)
99{
100   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
101      ata_input_data;
102
103   // Fill in the product revision level field.
104   // Per SAT, copy portions of the firmware revision that is not filled
105   // with spaces.  Some devices left-align their firmware rev ID, while
106   // others right-align.
107   if (  (identify->firmware_revision[4] == 0x20)
108       && (identify->firmware_revision[5] == 0x20)
109       && (identify->firmware_revision[6] == 0x20)
110       && (identify->firmware_revision[7] == 0x20) )
111   {
112      sati_ata_identify_device_copy_data(
113         sequence,
114         scsi_io,
115         32,
116         ata_input_data,
117         ATA_IDENTIFY_DEVICE_GET_OFFSET(firmware_revision),
118         4,
119         TRUE
120       );
121   }
122   else
123   {
124      // Since the last 4 bytes of the firmware revision are not spaces,
125      // utilize these bytes as the firmware revision in the inquiry data.
126      sati_ata_identify_device_copy_data(
127         sequence,
128         scsi_io,
129         32,
130         ata_input_data,
131         ATA_IDENTIFY_DEVICE_GET_OFFSET(firmware_revision)+4,
132         4,
133         TRUE
134      );
135   }
136}
137
138
139//******************************************************************************
140//* P U B L I C   M E T H O D S
141//******************************************************************************
142
143/**
144 * @brief This method builds the SCSI data associated with a SCSI standard
145 *        inquiry request.
146 *
147 * @param[in]  sequence This parameter specifies the translator sequence
148 *             object to be utilized during data translation.
149 * @param[in]  ata_input_data This parameter specifies ata data received from
150 *             the remote device.
151 * @param[out] scsi_io This parameter specifies the user IO request for
152 *             which to construct the standard inquiry data.
153 *
154 * @return none
155 */
156void sati_inquiry_standard_translate_data(
157   SATI_TRANSLATOR_SEQUENCE_T * sequence,
158   void                       * ata_input_data,
159   void                       * scsi_io
160)
161{
162   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
163                                           ata_input_data;
164   U32  index;
165
166   // Device type is disk, attached to this lun.
167   sati_set_data_byte(sequence, scsi_io, 0, 0x00);
168
169   // If the device indicates it's a removable media device, then set the
170   // RMB bit
171   if (identify->general_config_bits & ATA_IDENTIFY_REMOVABLE_MEDIA_ENABLE)
172      sati_set_data_byte(sequence, scsi_io, 1, 0x80);
173   else
174      sati_set_data_byte(sequence, scsi_io, 1, 0x00);
175
176   sati_set_data_byte(sequence, scsi_io, 2, 0x05); // Indicate SPC-3 support
177   sati_set_data_byte(sequence, scsi_io, 3, 0x02); // Response Format SPC-3
178
179   sati_set_data_byte(sequence, scsi_io, 4, 62); // 62 Additional Data Bytes.
180                                                 // n-4 per the spec, we end at
181                                                 // byte 66, so 66-4.
182   sati_set_data_byte(sequence, scsi_io, 5, 0x00);
183   sati_set_data_byte(sequence, scsi_io, 6, 0x00);
184   sati_set_data_byte(sequence, scsi_io, 7, 0x02); // Enable Cmd Queueing
185
186   // The Vender identification field is set to "ATA     "
187   sati_set_data_byte(sequence, scsi_io, 8, 0x41);
188   sati_set_data_byte(sequence, scsi_io, 9, 0x54);
189   sati_set_data_byte(sequence, scsi_io, 10, 0x41);
190   sati_set_data_byte(sequence, scsi_io, 11, 0x20);
191   sati_set_data_byte(sequence, scsi_io, 12, 0x20);
192   sati_set_data_byte(sequence, scsi_io, 13, 0x20);
193   sati_set_data_byte(sequence, scsi_io, 14, 0x20);
194   sati_set_data_byte(sequence, scsi_io, 15, 0x20);
195
196   // Fill in the product ID field.
197   sati_ata_identify_device_copy_data(
198      sequence,
199      scsi_io,
200      16,
201      ata_input_data,
202      ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number),
203      16,
204      TRUE
205   );
206
207   sati_inquiry_construct_product_revision(
208      sequence,
209      ata_input_data,
210      scsi_io
211   );
212
213   // Set the remaining fields up to the version descriptors to 0.
214   for (index = 36; index < 58; index++)
215      sati_set_data_byte(sequence, scsi_io, index, 0);
216
217   // Add version descriptors for the various protocols in play.
218
219   // SAM-4
220   sati_set_data_byte(sequence, scsi_io, 58, 0);
221   sati_set_data_byte(sequence, scsi_io, 59, 0x80);
222
223   // SAS-2
224   sati_set_data_byte(sequence, scsi_io, 60, 0x0C);
225   sati_set_data_byte(sequence, scsi_io, 61, 0x20);
226
227   // SPC-4
228   sati_set_data_byte(sequence, scsi_io, 62, 0x04);
229   sati_set_data_byte(sequence, scsi_io, 63, 0x60);
230
231   // SBC-3
232   sati_set_data_byte(sequence, scsi_io, 64, 0x04);
233   sati_set_data_byte(sequence, scsi_io, 65, 0xC0);
234
235   // ATA/ATAPI-8 ACS
236   sati_set_data_byte(sequence, scsi_io, 66, 0x16);
237   sati_set_data_byte(sequence, scsi_io, 67, 0x23);
238}
239
240/**
241 * @brief This method builds the SCSI data associated with an SCSI inquiry
242 *        for the supported VPD pages page.
243 *
244 * @param[in]  sequence This parameter specifies the translator sequence
245 *             object to be utilized during data translation.
246 * @param[out] scsi_io This parameter specifies the user IO request for
247 *             which to construct the supported VPD page information.
248 *
249 * @return none
250 */
251static
252void sati_inquiry_supported_pages_translate_data(
253   SATI_TRANSLATOR_SEQUENCE_T * sequence,
254   void                       * scsi_io
255)
256{
257   // Formulate the SCSI output data for the caller.
258   sati_set_data_byte(sequence, scsi_io, 0, 0); // Qualifier and Device Type
259   sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_SUPPORTED_PAGES_PAGE);
260   sati_set_data_byte(sequence, scsi_io, 2, 0); // Reserved.
261   sati_set_data_byte(sequence, scsi_io, 3, 4); // # VPD pages supported
262   sati_set_data_byte(sequence, scsi_io, 4, SCSI_INQUIRY_SUPPORTED_PAGES_PAGE);
263   sati_set_data_byte(sequence, scsi_io, 5, SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE);
264   sati_set_data_byte(sequence, scsi_io, 6, SCSI_INQUIRY_DEVICE_ID_PAGE);
265   sati_set_data_byte(sequence, scsi_io, 7, SCSI_INQUIRY_ATA_INFORMATION_PAGE);
266   sati_set_data_byte(sequence, scsi_io, 8, SCSI_INQUIRY_BLOCK_DEVICE_PAGE);
267   sati_set_data_byte(sequence, scsi_io, 9, 0); // End of the list
268}
269
270/**
271 * @brief This method builds the SCSI data associated with a request for
272 *        the unit serial number vital product data (VPD) page.
273 *
274 * @param[in]  sequence This parameter specifies the translator sequence
275 *             object to be utilized during data translation.
276 * @param[in]  ata_input_data This parameter specifies ata data received from
277 *             the remote device.
278 * @param[out] scsi_io This parameter specifies the user IO request for
279 *             which to construct the unit serial number data.
280 *
281 * @return none
282 */
283void sati_inquiry_serial_number_translate_data(
284   SATI_TRANSLATOR_SEQUENCE_T * sequence,
285   void                       * ata_input_data,
286   void                       * scsi_io
287)
288{
289   // Peripheral qualifier (0x0, currently connected)
290   // Peripheral device type (0x0 direct-access block device)
291   sati_set_data_byte(sequence, scsi_io, 0, 0x00);
292
293   sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE);
294   sati_set_data_byte(sequence, scsi_io, 2, 0x00);  // Reserved
295   sati_set_data_byte(sequence, scsi_io, 3, ATA_IDENTIFY_SERIAL_NUMBER_LEN);
296
297   sati_ata_identify_device_copy_data(
298      sequence,
299      scsi_io,
300      4,
301      ata_input_data,
302      ATA_IDENTIFY_DEVICE_GET_OFFSET(serial_number),
303      ATA_IDENTIFY_SERIAL_NUMBER_LEN,
304      TRUE
305   );
306}
307
308/**
309* @brief This method builds the SCSI data associated with a request for
310*        the Block Device Characteristics vital product data (VPD) page.
311*
312* @param[in]  sequence This parameter specifies the translator sequence
313*             object to be utilized during data translation.
314* @param[in]  ata_input_data This parameter specifies ata data received from
315*             the remote device.
316* @param[out] scsi_io This parameter specifies the user IO request for
317*             which to construct the unit serial number data.
318*
319* @return none
320*/
321void sati_inquiry_block_device_translate_data(
322   SATI_TRANSLATOR_SEQUENCE_T * sequence,
323   void                       * ata_input_data,
324   void                       * scsi_io
325)
326{
327   ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
328      ata_input_data;
329
330   U32 offset;
331
332   // Peripheral qualifier (0x0, currently connected)
333   // Peripheral device type (0x0 direct-access block device)
334   sati_set_data_byte(sequence, scsi_io, 0, 0x00);
335
336   sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_BLOCK_DEVICE_PAGE);
337
338   //PAGE LENGTH 0x003C
339   sati_set_data_byte(sequence, scsi_io, 2, 0x00);
340   sati_set_data_byte(sequence, scsi_io, 3, SCSI_INQUIRY_BLOCK_DEVICE_LENGTH);
341
342   sati_ata_identify_device_copy_data(
343      sequence,
344      scsi_io,
345      4,
346      ata_input_data,
347      ATA_IDENTIFY_DEVICE_GET_OFFSET(nominal_media_rotation_rate),
348      2,
349      FALSE
350    );
351
352    sati_set_data_byte(sequence, scsi_io, 6, 0x00);
353
354    sati_set_data_byte(
355       sequence,
356       scsi_io,
357       7,
358       (identify->device_nominal_form_factor & 0x0F) // only need bits 0-3
359    );
360
361    //bytes 8-63 are reserved
362    for(offset = 8; offset < 64; offset++)
363    {
364       sati_set_data_byte(sequence, scsi_io, offset, 0x00);
365    }
366}
367
368/**
369 * @brief This method builds the SCSI data associated with a request for
370 *        the device identification vital product data (VPD) page.
371 *
372 * @param[in]  sequence This parameter specifies the translator sequence
373 *             object to be utilized during data translation.
374 * @param[in]  ata_input_data This parameter specifies ata data received from
375 *             the remote device.
376 * @param[out] scsi_io This parameter specifies the user IO request for
377 *             which to construct the device ID page.
378 *
379 * @return none
380 */
381void sati_inquiry_device_id_translate_data(
382   SATI_TRANSLATOR_SEQUENCE_T * sequence,
383   void                       * ata_input_data,
384   void                       * scsi_io
385)
386{
387   ATA_IDENTIFY_DEVICE_DATA_T * identify    = (ATA_IDENTIFY_DEVICE_DATA_T*)
388                                              ata_input_data;
389   U16                     byte_offset = 4;
390   U16                     page_length;
391
392   // Peripheral qualifier (0x0, currently connected)
393   // Peripheral device type (0x0 direct-access block device)
394   sati_set_data_byte(sequence, scsi_io, 0, 0x00);
395
396   sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_DEVICE_ID_PAGE);
397
398   /**
399    * If World Wide Names are supported by this target, then build an
400    * identification descriptor using the WWN.
401    */
402
403   if (identify->command_set_supported_extention
404       & ATA_IDENTIFY_COMMAND_SET_WWN_SUPPORT_ENABLE)
405   {
406
407      sati_set_data_byte(sequence,
408         scsi_io, 4, SCSI_FC_PROTOCOL_IDENTIFIER | SCSI_BINARY_CODE_SET
409      );
410
411
412      sati_set_data_byte(sequence,
413         scsi_io, 5, SCSI_LUN_ASSOCIATION | SCSI_NAA_IDENTIFIER_TYPE
414      );
415
416      sati_set_data_byte(sequence, scsi_io, 6, 0);
417      sati_set_data_byte(sequence, scsi_io, 7, 0x08); // WWN are 8 bytes long
418
419      // Copy data from the identify device world wide name field into the
420      // buffer.
421      sati_ata_identify_device_copy_data(
422         sequence,
423         scsi_io,
424         8,
425         ata_input_data,
426         ATA_IDENTIFY_DEVICE_GET_OFFSET(world_wide_name),
427         ATA_IDENTIFY_WWN_LEN,
428         FALSE
429      );
430
431      byte_offset = 16;
432   }
433
434   /**
435    * Build a identification descriptor using the model number & serial number.
436    */
437
438   sati_set_data_byte(sequence,
439      scsi_io, byte_offset, SCSI_FC_PROTOCOL_IDENTIFIER | SCSI_ASCII_CODE_SET
440   );
441   byte_offset++;
442   sati_set_data_byte(sequence,
443      scsi_io, byte_offset, SCSI_LUN_ASSOCIATION | SCSI_T10_IDENTIFIER_TYPE
444   );
445   byte_offset++;
446   sati_set_data_byte(sequence, scsi_io, byte_offset, 0);
447   byte_offset++;
448
449   // Identifier length (8 bytes for "ATA     " + 40 bytes from ATA IDENTIFY
450   // model number field + 20 bytes from ATA IDENTIFY serial number field.
451   sati_set_data_byte(
452      sequence,
453      scsi_io,
454      byte_offset,
455      8 + (ATA_IDENTIFY_SERIAL_NUMBER_LEN) + (ATA_IDENTIFY_MODEL_NUMBER_LEN)
456   );
457   byte_offset++;
458
459   // Per SAT, write "ATA     ".
460   sati_set_data_byte(sequence, scsi_io, byte_offset, 0x41);
461   byte_offset++;
462   sati_set_data_byte(sequence, scsi_io, byte_offset, 0x54);
463   byte_offset++;
464   sati_set_data_byte(sequence, scsi_io, byte_offset, 0x41);
465   byte_offset++;
466   sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
467   byte_offset++;
468   sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
469   byte_offset++;
470   sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
471   byte_offset++;
472   sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
473   byte_offset++;
474   sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
475   byte_offset++;
476
477   // Copy data from the identify device model number field into the
478   // buffer and update the byte_offset.
479   sati_ata_identify_device_copy_data(
480      sequence,
481      scsi_io,
482      byte_offset,
483      ata_input_data,
484      ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number),
485      ATA_IDENTIFY_MODEL_NUMBER_LEN,
486      TRUE
487   );
488
489   byte_offset += ATA_IDENTIFY_MODEL_NUMBER_LEN;
490
491   // Copy data from the identify device serial number field into the
492   // buffer and update the byte_offset.
493   sati_ata_identify_device_copy_data(
494      sequence,
495      scsi_io,
496      byte_offset,
497      ata_input_data,
498      ATA_IDENTIFY_DEVICE_GET_OFFSET(serial_number),
499      ATA_IDENTIFY_SERIAL_NUMBER_LEN,
500      TRUE
501   );
502
503   byte_offset += ATA_IDENTIFY_SERIAL_NUMBER_LEN;
504
505   /**
506    * If the target is contained in a SAS Domain, then build a target port
507    * ID descriptor using the SAS address.
508    */
509
510#if     defined(SATI_TRANSPORT_SUPPORTS_SAS)       \
511     && defined(DISABLE_MSFT_SCSI_COMPLIANCE_SUPPORT)
512   {
513      SCI_SAS_ADDRESS_T sas_address;
514
515      sati_set_data_byte(
516         sequence,
517         scsi_io,
518         byte_offset,
519         SCSI_SAS_PROTOCOL_IDENTIFIER | SCSI_BINARY_CODE_SET
520      );
521      byte_offset++;
522
523      sati_set_data_byte(
524         sequence,
525         scsi_io,
526         byte_offset,
527         SCSI_PIV_ENABLE | SCSI_TARGET_PORT_ASSOCIATION |
528         SCSI_NAA_IDENTIFIER_TYPE
529      );
530
531      byte_offset++;
532      sati_set_data_byte(sequence, scsi_io, byte_offset, 0);
533      byte_offset++;
534      sati_set_data_byte(sequence, scsi_io, byte_offset, 8); // SAS Addr=8 bytes
535      byte_offset++;
536
537      sati_cb_device_get_sas_address(scsi_io, &sas_address);
538
539      // Store the SAS address in the target port descriptor.
540      sati_set_data_dword(sequence, scsi_io, byte_offset, sas_address.high);
541      byte_offset += 4;
542      sati_set_data_dword(sequence, scsi_io, byte_offset, sas_address.low);
543      byte_offset += 4;
544   }
545#endif // SATI_TRANSPORT_SUPPORTS_SAS && DISABLE_MSFT_SCSI_COMPLIANCE_SUPPORT
546
547   /**
548    * Set the Page length field.  The page length is n-3, where n is the
549    * last offset in the page (considered page length - 4).
550    */
551
552   page_length = byte_offset - 4;
553   sati_set_data_byte(sequence, scsi_io, 2, (U8)((page_length & 0xFF00) >> 8));
554   sati_set_data_byte(sequence, scsi_io, 3, (U8)(page_length & 0x00FF));
555}
556
557/**
558* @brief This method builds the SCSI data associated with a request for
559*        the  ATA information vital product data (VPD) page.
560*
561* @param[in]  sequence This parameter specifies the translator sequence
562*             object to be utilized during data translation.
563* @param[in]  ata_input_data This parameter specifies ata data received from
564*             a identify device command processed by the remote device.
565* @param[out] scsi_io This parameter specifies the user IO request for
566*             which to construct the ATA information page.
567*
568* @return none
569*/
570SATI_STATUS sati_inquiry_ata_information_translate_data(
571   SATI_TRANSLATOR_SEQUENCE_T * sequence,
572   void                       * ata_input_data,
573   void                       * scsi_io
574)
575{
576   sati_set_data_byte(sequence, scsi_io, 0, 0x00);
577   sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_ATA_INFORMATION_PAGE);
578   sati_set_data_byte(sequence, scsi_io, 2, 0x02);
579   sati_set_data_byte(sequence, scsi_io, 3, 0x38);
580
581   //Reserved SAT2r07
582   sati_set_data_byte(sequence, scsi_io, 4, 0x00);
583   sati_set_data_byte(sequence, scsi_io, 5, 0x00);
584   sati_set_data_byte(sequence, scsi_io, 6, 0x00);
585   sati_set_data_byte(sequence, scsi_io, 7, 0x00);
586
587   // The Vender identification field is set to "ATA     "
588   sati_set_data_byte(sequence, scsi_io, 8, 0x41);
589   sati_set_data_byte(sequence, scsi_io, 9, 0x54);
590   sati_set_data_byte(sequence, scsi_io, 10, 0x41);
591   sati_set_data_byte(sequence, scsi_io, 11, 0x20);
592   sati_set_data_byte(sequence, scsi_io, 12, 0x20);
593   sati_set_data_byte(sequence, scsi_io, 13, 0x20);
594   sati_set_data_byte(sequence, scsi_io, 14, 0x20);
595   sati_set_data_byte(sequence, scsi_io, 15, 0x20);
596
597   //SAT Product identification
598   sati_ata_identify_device_copy_data(
599      sequence,
600      scsi_io,
601      16,
602      ata_input_data,
603      ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number),
604      16,
605      TRUE
606   );
607
608   //SAT Product Revision level bytes 32-35
609   sati_inquiry_construct_product_revision(
610      sequence,
611      ata_input_data,
612      scsi_io
613   );
614
615   //skipping ATA device signature for now
616
617   //Command code
618   sati_set_data_byte(sequence, scsi_io, 56, 0xEC);
619
620   //Reserved SAT2r07
621   sati_set_data_byte(sequence, scsi_io, 57, 0x00);
622   sati_set_data_byte(sequence, scsi_io, 58, 0x00);
623   sati_set_data_byte(sequence, scsi_io, 59, 0x00);
624
625   //copy all ATA identify device data
626   sati_ata_identify_device_copy_data(
627      sequence,
628      scsi_io,
629      60,
630      ata_input_data,
631      0,
632      sizeof(ATA_IDENTIFY_DEVICE_DATA_T),
633      FALSE
634   );
635
636   //Need to send ATA Execute Device Diagnostic command still
637   sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
638
639   return SATI_SEQUENCE_INCOMPLETE;
640}
641
642/**
643 * @brief This method will translate the inquiry SCSI command into
644 *        an ATA IDENTIFY DEVICE command.  It will handle several different
645 *        VPD pages and the standard inquiry page.
646 *        For more information on the parameters passed to this method,
647 *        please reference sati_translate_command().
648 *
649 * @return Indicate if the command translation succeeded.
650 * @retval SCI_SUCCESS This is returned if the command translation was
651 *         successful.
652 * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
653 *         the page isn't supported, or the page code
654 *         field is not zero when the EVPD bit is 0.
655 */
656SATI_STATUS sati_inquiry_translate_command(
657   SATI_TRANSLATOR_SEQUENCE_T * sequence,
658   void                       * scsi_io,
659   void                       * ata_io
660)
661{
662   U8 * cdb = sati_cb_get_cdb_address(scsi_io);
663
664   /**
665    * SPC dictates:
666    * - that the page code field must be 0, if VPD enable is 0.
667    */
668   if (  ((sati_get_cdb_byte(cdb, 1) & SCSI_INQUIRY_EVPD_ENABLE) == 0)
669      && (sati_get_cdb_byte(cdb, 2) != 0) )
670   {
671      sati_scsi_sense_data_construct(
672         sequence,
673         scsi_io,
674         SCSI_STATUS_CHECK_CONDITION,
675         SCSI_SENSE_ILLEGAL_REQUEST,
676         SCSI_ASC_INVALID_FIELD_IN_CDB,
677         SCSI_ASCQ_INVALID_FIELD_IN_CDB
678      );
679      return SATI_FAILURE_CHECK_RESPONSE_DATA;
680   }
681
682   // Set the data length based on the allocation length field in the CDB.
683   sequence->allocation_length = (sati_get_cdb_byte(cdb, 3) << 8) |
684                                 (sati_get_cdb_byte(cdb, 4));
685
686   // Check to see if there was a request for the vital product data or just
687   // the standard inquiry.
688   if (sati_get_cdb_byte(cdb, 1) & SCSI_INQUIRY_EVPD_ENABLE)
689   {
690      // Parse the page code to determine which translator to invoke.
691      switch (sati_get_cdb_byte(cdb, 2))
692      {
693         case SCSI_INQUIRY_SUPPORTED_PAGES_PAGE:
694            sequence->type  = SATI_SEQUENCE_INQUIRY_SUPPORTED_PAGES;
695            sati_inquiry_supported_pages_translate_data(sequence, scsi_io);
696            return SATI_COMPLETE;
697         break;
698
699         case SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE:
700            sequence->type = SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER;
701         break;
702
703         case SCSI_INQUIRY_DEVICE_ID_PAGE:
704            sequence->type = SATI_SEQUENCE_INQUIRY_DEVICE_ID;
705         break;
706
707         case SCSI_INQUIRY_ATA_INFORMATION_PAGE:
708
709            if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
710            {
711               sati_ata_execute_device_diagnostic_construct(
712                  ata_io,
713                  sequence
714               );
715               sequence->type = SATI_SEQUENCE_INQUIRY_EXECUTE_DEVICE_DIAG;
716            }
717            else
718            {
719               sequence->type = SATI_SEQUENCE_INQUIRY_ATA_INFORMATION;
720            }
721         break;
722
723         case SCSI_INQUIRY_BLOCK_DEVICE_PAGE:
724            sequence->type = SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE;
725         break;
726
727         default:
728            sati_scsi_sense_data_construct(
729               sequence,
730               scsi_io,
731               SCSI_STATUS_CHECK_CONDITION,
732               SCSI_SENSE_ILLEGAL_REQUEST,
733               SCSI_ASC_INVALID_FIELD_IN_CDB,
734               SCSI_ASCQ_INVALID_FIELD_IN_CDB
735            );
736            return SATI_FAILURE_CHECK_RESPONSE_DATA;
737         break;
738      }
739   }
740   else
741   {
742      sequence->type = SATI_SEQUENCE_INQUIRY_STANDARD;
743   }
744
745   sati_ata_identify_device_construct(ata_io, sequence);
746
747   return SATI_SUCCESS;
748}
749
750/**
751* @brief This method finishes the construction of the SCSI data associated
752         with a request for the  ATA information vital product data (VPD) page.
753         The ATA device signature is written into the data response from the
754         task fle registers after issuing a Execute Device Diagnostic command.
755*
756* @param[in]  sequence This parameter specifies the translator sequence
757*             object to be utilized during data translation.
758* @param[out] scsi_io This parameter specifies the user IO request for
759*             which to construct the ATA information page.
760* @param[in]  ata_io This parameter specifies the ATA payload
761*             buffer location and size to be translated.
762*
763* @return none
764*/
765void sati_inquiry_ata_information_finish_translation(
766   SATI_TRANSLATOR_SEQUENCE_T * sequence,
767   void                       * scsi_io,
768   void                       * ata_io
769)
770{
771   U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
772   U32 offset;
773
774   //SATA transport
775   sati_set_data_byte(sequence, scsi_io, 36, 0x34);
776   sati_set_data_byte(sequence, scsi_io, 37, 0x00);
777   sati_set_data_byte(sequence, scsi_io, 38, (U8) sati_get_ata_status(register_fis));
778   sati_set_data_byte(sequence, scsi_io, 39, (U8) sati_get_ata_error(register_fis));
779   sati_set_data_byte(sequence, scsi_io, 40, sati_get_ata_lba_low(register_fis));
780   sati_set_data_byte(sequence, scsi_io, 41, sati_get_ata_lba_mid(register_fis));
781   sati_set_data_byte(sequence, scsi_io, 42, sati_get_ata_lba_high(register_fis));
782   sati_set_data_byte(sequence, scsi_io, 43, sati_get_ata_device(register_fis));
783   sati_set_data_byte(sequence, scsi_io, 44, sati_get_ata_lba_low_ext(register_fis));
784   sati_set_data_byte(sequence, scsi_io, 45, sati_get_ata_lba_mid_ext(register_fis));
785   sati_set_data_byte(sequence, scsi_io, 46, sati_get_ata_lba_high_ext(register_fis));
786   sati_set_data_byte(sequence, scsi_io, 47, 0x00);
787   sati_set_data_byte(sequence, scsi_io, 48, sati_get_ata_sector_count(register_fis));
788   sati_set_data_byte(sequence, scsi_io, 49, sati_get_ata_sector_count_exp(register_fis));
789
790   for(offset = 50; offset < 56; offset++)
791   {
792      sati_set_data_byte(sequence, scsi_io, offset, 0x00);
793   }
794
795   sequence->state = SATI_SEQUENCE_STATE_FINAL;
796}
797
798#endif // !defined(DISABLE_SATI_INQUIRY)
799
800