43
43
#define ATA_PT_12_CMDLEN 12
44
44
#define ATA_PT_16_CMD 0x85
45
45
#define ATA_PT_16_CMDLEN 16
46
+ #define ATA_PT_32_SA 0x1ff0
47
+ #define ATA_PT_32_CMDLEN 32
46
48
#define FORMAT_UNIT_CMD 0x4
47
49
#define FORMAT_UNIT_CMDLEN 6
48
50
#define PERSISTENT_RESERVE_IN_CMD 0x5e
@@ -1531,23 +1533,24 @@ sg_ll_verify16(int sg_fd, int vrprotect, int dpo, int bytchk, uint64_t llba,
1531
1533
return ret ;
1532
1534
}
1533
1535
1534
- /* Invokes a ATA PASS-THROUGH (12 or 16) SCSI command (SAT). If cdb_len
1535
- * is 12 then a ATA PASS-THROUGH (12) command is called. If cdb_len is 16
1536
- * then a ATA PASS-THROUGH (16) command is called. If cdb_len is any other
1537
- * value -1 is returned. After copying from cdbp to an internal buffer,
1538
- * the first byte (i.e. offset 0) is set to 0xa1 if cdb_len is 12; or is
1539
- * set to 0x85 if cdb_len is 16. The last byte (offset 11 or offset 15) is
1540
- * set to 0x0 in the internal buffer. If timeout_secs <= 0 then the timeout
1541
- * is set to 60 seconds. For data in or out transfers set dinp or doutp,
1542
- * and dlen to the number of bytes to transfer. If dlen is zero then no data
1543
- * transfer is assumed. If sense buffer obtained then it is written to
1544
- * sensep, else sensep[0] is set to 0x0. If ATA return descriptor is obtained
1545
- * then written to ata_return_dp, else ata_return_dp[0] is set to 0x0. Either
1546
- * sensep or ata_return_dp (or both) may be NULL pointers. Returns SCSI
1547
- * status value (>= 0) or -1 if other error. Users are expected to check the
1548
- * sense buffer themselves. If available the data in resid is written to
1549
- * residp. Note in SAT-2 and later, fixed format sense data may be placed in
1550
- * *sensep in which case sensep[0]==0x70 .
1536
+ /* Invokes a ATA PASS-THROUGH (12, 16 or 32) SCSI command (SAT). This is
1537
+ * selected by the cdb_len argument that can take values of 12, 16 or 32
1538
+ * only (else -1 is returned). The byte at offset 0 (and bytes 0 to 9
1539
+ * inclusive for ATA PT(32)) pointed to be cdbp are ignored and apart from
1540
+ * the control byte, the rest is copied into an internal cdb which is then
1541
+ * sent to the device. The control byte is byte 11 for ATA PT(12), byte 15
1542
+ * for ATA PT(16) and byte 1 for ATA PT(32). If timeout_secs <= 0 then the
1543
+ * timeout is set to 60 seconds. For data in or out transfers set dinp or
1544
+ * doutp, and dlen to the number of bytes to transfer. If dlen is zero then
1545
+ * no data transfer is assumed. If sense buffer obtained then it is written
1546
+ * to sensep, else sensep[0] is set to 0x0. If ATA return descriptor is
1547
+ * obtained then written to ata_return_dp, else ata_return_dp[0] is set to
1548
+ * 0x0. Either sensep or ata_return_dp (or both) may be NULL pointers.
1549
+ * Returns SCSI status value (>= 0) or -1 if other error. Users are
1550
+ * expected to check the sense buffer themselves. If available the data in
1551
+ * resid is written to residp. Note in SAT-2 and later, fixed format sense
1552
+ * data may be placed in *sensep in which case sensep[0]==0x70, prior to
1553
+ * SAT-2 descriptor sense format was required (i.e. sensep[0]==0x72).
1551
1554
*/
1552
1555
int
1553
1556
sg_ll_ata_pt (int sg_fd , const unsigned char * cdbp , int cdb_len ,
@@ -1557,8 +1560,7 @@ sg_ll_ata_pt(int sg_fd, const unsigned char * cdbp, int cdb_len,
1557
1560
int * residp , int verbose )
1558
1561
{
1559
1562
int k , res , slen , duration ;
1560
- unsigned char aptCmdBlk [ATA_PT_16_CMDLEN ] =
1561
- {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 };
1563
+ unsigned char aptCmdBlk [ATA_PT_32_CMDLEN ];
1562
1564
unsigned char sense_b [SENSE_BUFF_LEN ];
1563
1565
unsigned char * sp ;
1564
1566
const unsigned char * bp ;
@@ -1567,35 +1569,55 @@ sg_ll_ata_pt(int sg_fd, const unsigned char * cdbp, int cdb_len,
1567
1569
char b [256 ];
1568
1570
int ret = -1 ;
1569
1571
1572
+ memset (aptCmdBlk , 0 , sizeof (aptCmdBlk ));
1570
1573
b [0 ] = '\0' ;
1571
- cnamep = (12 == cdb_len ) ?
1572
- "ATA pass through (12)" : "ATA pass through (16)" ;
1573
- if ((NULL == cdbp ) || ((12 != cdb_len ) && (16 != cdb_len ))) {
1574
- if (verbose ) {
1575
- if (NULL == cdbp )
1576
- pr2ws ("%s NULL cdb pointer\n" , cnamep );
1577
- else
1578
- pr2ws ("cdb_len must be 12 or 16\n" );
1579
- }
1574
+ switch (cdb_len ) {
1575
+ case 12 :
1576
+ cnamep = "ATA pass-through(12)" ;
1577
+ aptCmdBlk [0 ] = ATA_PT_12_CMD ;
1578
+ memcpy (aptCmdBlk + 1 , cdbp + 1 , 10 );
1579
+ /* control byte at cdb[11] left at zero */
1580
+ break ;
1581
+ case 16 :
1582
+ cnamep = "ATA pass-through(16)" ;
1583
+ aptCmdBlk [0 ] = ATA_PT_16_CMD ;
1584
+ memcpy (aptCmdBlk + 1 , cdbp + 1 , 14 );
1585
+ /* control byte at cdb[15] left at zero */
1586
+ break ;
1587
+ case 32 :
1588
+ cnamep = "ATA pass-through(32)" ;
1589
+ aptCmdBlk [0 ] = SG_VARIABLE_LENGTH_CMD ;
1590
+ /* control byte at cdb[1] left at zero */
1591
+ aptCmdBlk [7 ] = 0x18 ; /* length starting at next byte */
1592
+ sg_put_unaligned_be16 (ATA_PT_32_SA , aptCmdBlk + 8 );
1593
+ memcpy (aptCmdBlk + 10 , cdbp + 10 , 32 - 10 );
1594
+ break ;
1595
+ default :
1596
+ pr2ws ("cdb_len must be 12, 16 or 32\n" );
1597
+ return -1 ;
1598
+ }
1599
+ if (NULL == cdbp ) {
1600
+ if (verbose )
1601
+ pr2ws ("%s NULL cdb pointer\n" , cnamep );
1580
1602
return -1 ;
1581
1603
}
1582
- aptCmdBlk [0 ] = (12 == cdb_len ) ? ATA_PT_12_CMD : ATA_PT_16_CMD ;
1583
1604
if (sensep && (max_sense_len >= (int )sizeof (sense_b ))) {
1584
1605
sp = sensep ;
1585
1606
slen = max_sense_len ;
1586
1607
} else {
1587
1608
sp = sense_b ;
1588
1609
slen = sizeof (sense_b );
1589
1610
}
1590
- if (12 == cdb_len )
1591
- memcpy (aptCmdBlk + 1 , cdbp + 1 , ((cdb_len > 11 ) ? 10 : (cdb_len - 1 )));
1592
- else
1593
- memcpy (aptCmdBlk + 1 , cdbp + 1 , ((cdb_len > 15 ) ? 14 : (cdb_len - 1 )));
1594
1611
if (verbose ) {
1595
1612
pr2ws (" %s cdb: " , cnamep );
1596
- for (k = 0 ; k < cdb_len ; ++ k )
1597
- pr2ws ("%02x " , aptCmdBlk [k ]);
1598
- pr2ws ("\n" );
1613
+ if (cdb_len < 32 ) {
1614
+ for (k = 0 ; k < cdb_len ; ++ k )
1615
+ pr2ws ("%02x " , aptCmdBlk [k ]);
1616
+ pr2ws ("\n" );
1617
+ } else {
1618
+ pr2ws ("\n" );
1619
+ dStrHexErr ((const char * )aptCmdBlk , cdb_len , -1 );
1620
+ }
1599
1621
}
1600
1622
ptvp = construct_scsi_pt_obj ();
1601
1623
if (NULL == ptvp ) {
0 commit comments