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