aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/block/ahci.c55
-rw-r--r--include/scsi.h2
2 files changed, 52 insertions, 5 deletions
diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c
index 509235275..c16e8bae6 100644
--- a/drivers/block/ahci.c
+++ b/drivers/block/ahci.c
@@ -672,6 +672,7 @@ static int ata_scsiop_read_write(ccb *pccb, u8 is_write)
static int ata_scsiop_read_capacity10(ccb *pccb)
{
u32 cap;
+ u32 block_size;
if (!ataid[pccb->target]) {
printf("scsi_ahci: SCSI READ CAPACITY10 command failure. "
@@ -680,12 +681,53 @@ static int ata_scsiop_read_capacity10(ccb *pccb)
return -EPERM;
}
- cap = be32_to_cpu(ataid[pccb->target]->lba_capacity);
+ cap = le32_to_cpu(ataid[pccb->target]->lba_capacity);
+ if (cap == 0xfffffff) {
+ unsigned short *cap48 = ataid[pccb->target]->lba48_capacity;
+ if (cap48[2] || cap48[3]) {
+ cap = 0xffffffff;
+ } else {
+ cap = (le16_to_cpu(cap48[1]) << 16) |
+ (le16_to_cpu(cap48[0]));
+ }
+ }
+
+ cap = cpu_to_be32(cap);
memcpy(pccb->pdata, &cap, sizeof(cap));
- pccb->pdata[4] = pccb->pdata[5] = 0;
- pccb->pdata[6] = 512 >> 8;
- pccb->pdata[7] = 512 & 0xff;
+ block_size = cpu_to_be32((u32)512);
+ memcpy(&pccb->pdata[4], &block_size, 4);
+
+ return 0;
+}
+
+
+/*
+ * SCSI READ CAPACITY16 command operation.
+ */
+static int ata_scsiop_read_capacity16(ccb *pccb)
+{
+ u64 cap;
+ u64 block_size;
+
+ if (!ataid[pccb->target]) {
+ printf("scsi_ahci: SCSI READ CAPACITY16 command failure. "
+ "\tNo ATA info!\n"
+ "\tPlease run SCSI commmand INQUIRY firstly!\n");
+ return -EPERM;
+ }
+
+ cap = le32_to_cpu(ataid[pccb->target]->lba_capacity);
+ if (cap == 0xfffffff) {
+ memcpy(&cap, ataid[pccb->target]->lba48_capacity, sizeof(cap));
+ cap = le64_to_cpu(cap);
+ }
+
+ cap = cpu_to_be64(cap);
+ memcpy(pccb->pdata, &cap, sizeof(cap));
+
+ block_size = cpu_to_be64((u64)512);
+ memcpy(&pccb->pdata[8], &block_size, 8);
return 0;
}
@@ -711,9 +753,12 @@ int scsi_exec(ccb *pccb)
case SCSI_WRITE10:
ret = ata_scsiop_read_write(pccb, 1);
break;
- case SCSI_RD_CAPAC:
+ case SCSI_RD_CAPAC10:
ret = ata_scsiop_read_capacity10(pccb);
break;
+ case SCSI_RD_CAPAC16:
+ ret = ata_scsiop_read_capacity16(pccb);
+ break;
case SCSI_TST_U_RDY:
ret = ata_scsiop_test_unit_ready(pccb);
break;
diff --git a/include/scsi.h b/include/scsi.h
index 9681d198d..9da764bdc 100644
--- a/include/scsi.h
+++ b/include/scsi.h
@@ -150,6 +150,8 @@ typedef struct SCSI_cmd_block{
#define SCSI_READ6 0x08 /* Read 6-byte (MANDATORY) */
#define SCSI_READ10 0x28 /* Read 10-byte (MANDATORY) */
#define SCSI_RD_CAPAC 0x25 /* Read Capacity (MANDATORY) */
+#define SCSI_RD_CAPAC10 SCSI_RD_CAPAC /* Read Capacity (10) */
+#define SCSI_RD_CAPAC16 0x9e /* Read Capacity (16) */
#define SCSI_RD_DEFECT 0x37 /* Read Defect Data (O) */
#define SCSI_READ_LONG 0x3E /* Read Long (O) */
#define SCSI_REASS_BLK 0x07 /* Reassign Blocks (O) */