1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3 *
4 * This file is provided under a dual BSD/GPLv2 license. When using or
5 * redistributing this file, you may do so under either license.
6 *
7 * GPL LICENSE SUMMARY
8 *
9 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of version 2 of the GNU General Public License as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
23 * The full GNU General Public License is included in this distribution
24 * in the file called LICENSE.GPL.
25 *
26 * BSD LICENSE
27 *
28 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
29 * All rights reserved.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 *
35 * * Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * * Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in
39 * the documentation and/or other materials provided with the
40 * distribution.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
43 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
44 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
45 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
46 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 */
54
55 #include <sys/cdefs.h>
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 */
93 static
sati_inquiry_construct_product_revision(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * ata_input_data,void * scsi_io)94 void 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 */
sati_inquiry_standard_translate_data(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * ata_input_data,void * scsi_io)156 void 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 */
251 static
sati_inquiry_supported_pages_translate_data(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io)252 void 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 */
sati_inquiry_serial_number_translate_data(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * ata_input_data,void * scsi_io)283 void 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 */
sati_inquiry_block_device_translate_data(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * ata_input_data,void * scsi_io)321 void 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 */
sati_inquiry_device_id_translate_data(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * ata_input_data,void * scsi_io)381 void 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 */
sati_inquiry_ata_information_translate_data(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * ata_input_data,void * scsi_io)570 SATI_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 */
sati_inquiry_translate_command(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_io)656 SATI_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 */
sati_inquiry_ata_information_finish_translation(SATI_TRANSLATOR_SEQUENCE_T * sequence,void * scsi_io,void * ata_io)765 void 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