[haiku-commits] haiku: hrev44639 - src/add-ons/kernel/busses/scsi/ahci

  • From: marcusoverhagen@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 14 Sep 2012 22:29:13 +0200 (CEST)

hrev44639 adds 1 changeset to branch 'master'
old head: 1f6d0a79c927877cdf2aa5a6c6475a2488090f5f
new head: 3c5216179e02f3b711bbac9c021f821ad3628cc7

----------------------------------------------------------------------------

3c52161: implement support for harddisks bigger than 2TB
   * can't test this, it's untested, but similar to ATADevice.cpp
   * should no longer panic when hdd > 2TB is connected
   * fix request completition in two error cases
   * add const to some parameters

                                  [ Marcus Overhagen <marcus@xxxxxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev44639
Commit:      3c5216179e02f3b711bbac9c021f821ad3628cc7
URL:         http://cgit.haiku-os.org/haiku/commit/?id=3c52161
Author:      Marcus Overhagen <marcus@xxxxxxxxxxxx>
Date:        Fri Sep 14 20:21:47 2012 UTC

----------------------------------------------------------------------------

2 files changed, 64 insertions(+), 9 deletions(-)
src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp |   72 ++++++++++++++---
src/add-ons/kernel/busses/scsi/ahci/ahci_port.h   |    1 +

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
index 7cc78c1..85e4403 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
@@ -548,7 +548,7 @@ AHCIPort::ScsiInquiry(scsi_ccb *request)
 {
        TRACE("AHCIPort::ScsiInquiry port %d\n", fIndex);
 
-       scsi_cmd_inquiry *cmd = (scsi_cmd_inquiry *)request->cdb;
+       const scsi_cmd_inquiry *cmd = (const scsi_cmd_inquiry *)request->cdb;
        scsi_res_inquiry scsiData;
        ata_device_infoblock ataData;
 
@@ -679,22 +679,50 @@ AHCIPort::ScsiReadCapacity(scsi_ccb *request)
 {
        TRACE("AHCIPort::ScsiReadCapacity port %d\n", fIndex);
 
-       scsi_cmd_read_capacity *cmd = (scsi_cmd_read_capacity *)request->cdb;
+       const scsi_cmd_read_capacity *cmd = (const scsi_cmd_read_capacity 
*)request->cdb;
        scsi_res_read_capacity scsiData;
 
        if (cmd->pmi || cmd->lba || request->data_length < sizeof(scsiData)) {
                TRACE("invalid request\n");
+               request->subsys_status = SCSI_REQ_ABORTED;
+               gSCSI->finished(request, 1);
                return;
        }
 
        TRACE("SectorSize %" B_PRIu32 ", SectorCount 0x%" B_PRIx64 "\n",
                fSectorSize, fSectorCount);
 
-       if (fSectorCount > 0xffffffff)
-               panic("ahci: SCSI emulation doesn't support harddisks larger 
than 2TB");
+       scsiData.block_size = B_HOST_TO_BENDIAN_INT32(fSectorSize);
+
+       if (fSectorCount <= 0xffffffff)
+               scsiData.lba = B_HOST_TO_BENDIAN_INT32(fSectorCount - 1);
+       else
+               scsiData.lba = 0xffffffff;
+
+       if (sg_memcpy(request->sg_list, request->sg_count, &scsiData,
+                       sizeof(scsiData)) < B_OK) {
+               request->subsys_status = SCSI_DATA_RUN_ERR;
+       } else {
+               request->subsys_status = SCSI_REQ_CMP;
+               request->data_resid = request->data_length - sizeof(scsiData);
+       }
+       gSCSI->finished(request, 1);
+}
+
+
+void
+AHCIPort::ScsiReadCapacity16(scsi_ccb *request)
+{
+       TRACE("AHCIPort::ScsiReadCapacity16 port %d\n", fIndex);
+
+       //const scsi_cmd_read_capacity_long *cmd = (const 
scsi_cmd_read_capacity_long *)request->cdb;
+       scsi_res_read_capacity_long scsiData;
+
+       TRACE("SectorSize %" B_PRIu32 ", SectorCount 0x%" B_PRIx64 "\n",
+               fSectorSize, fSectorCount);
 
        scsiData.block_size = B_HOST_TO_BENDIAN_INT32(fSectorSize);
-       scsiData.lba = B_HOST_TO_BENDIAN_INT32(fSectorCount - 1);
+       scsiData.lba = B_HOST_TO_BENDIAN_INT64(fSectorCount - 1);
 
        if (sg_memcpy(request->sg_list, request->sg_count, &scsiData,
                        sizeof(scsiData)) < B_OK) {
@@ -731,6 +759,7 @@ AHCIPort::ScsiReadWrite(scsi_ccb *request, uint64 lba, 
size_t sectorCount,
                TRACE("out of memory when allocating read/write request\n");
                request->subsys_status = SCSI_REQ_ABORTED;
                gSCSI->finished(request, 1);
+               return;
        }
 
        if (fUse48BitCommands) {
@@ -914,13 +943,21 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
                case SCSI_OP_READ_CAPACITY:
                        ScsiReadCapacity(request);
                        break;
+               case SCSI_OP_SERVICE_ACTION_IN:
+                       if ((request->cdb[1] & 0x1f) == 
SCSI_SAI_READ_CAPACITY_16)
+                               ScsiReadCapacity16(request);
+                       else {
+                               request->subsys_status = SCSI_REQ_INVALID;
+                               gSCSI->finished(request, 1);
+                       }
+                       break; 
                case SCSI_OP_SYNCHRONIZE_CACHE:
                        ScsiSynchronizeCache(request);
                        break;
                case SCSI_OP_READ_6:
                case SCSI_OP_WRITE_6:
                {
-                       scsi_cmd_rw_6 *cmd = (scsi_cmd_rw_6 *)request->cdb;
+                       const scsi_cmd_rw_6 *cmd = (const scsi_cmd_rw_6 
*)request->cdb;
                        uint32 position = ((uint32)cmd->high_lba << 16)
                                | ((uint32)cmd->mid_lba << 8) | 
(uint32)cmd->low_lba;
                        size_t length = cmd->length != 0 ? cmd->length : 256;
@@ -931,7 +968,7 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
                case SCSI_OP_READ_10:
                case SCSI_OP_WRITE_10:
                {
-                       scsi_cmd_rw_10 *cmd = (scsi_cmd_rw_10 *)request->cdb;
+                       const scsi_cmd_rw_10 *cmd = (const scsi_cmd_rw_10 
*)request->cdb;
                        uint32 position = B_BENDIAN_TO_HOST_INT32(cmd->lba);
                        size_t length = B_BENDIAN_TO_HOST_INT16(cmd->length);
                        bool isWrite = request->cdb[0] == SCSI_OP_WRITE_10;
@@ -948,7 +985,7 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
                case SCSI_OP_READ_12:
                case SCSI_OP_WRITE_12:
                {
-                       scsi_cmd_rw_12 *cmd = (scsi_cmd_rw_12 *)request->cdb;
+                       const scsi_cmd_rw_12 *cmd = (const scsi_cmd_rw_12 
*)request->cdb;
                        uint32 position = B_BENDIAN_TO_HOST_INT32(cmd->lba);
                        size_t length = B_BENDIAN_TO_HOST_INT32(cmd->length);
                        bool isWrite = request->cdb[0] == SCSI_OP_WRITE_12;
@@ -962,9 +999,26 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
                        }
                        break;
                }
+               case SCSI_OP_READ_16:
+               case SCSI_OP_WRITE_16:
+               {
+                       const scsi_cmd_rw_16 *cmd = (const scsi_cmd_rw_16 
*)request->cdb;
+                       uint64 position = B_BENDIAN_TO_HOST_INT64(cmd->lba);
+                       size_t length = B_BENDIAN_TO_HOST_INT32(cmd->length);
+                       bool isWrite = request->cdb[0] == SCSI_OP_WRITE_16;
+                       if (length) {
+                               ScsiReadWrite(request, position, length, 
isWrite);
+                       } else {
+                               TRACE("AHCIPort::ScsiExecuteRequest error: 
transfer without "
+                                       "data!\n");
+                               request->subsys_status = SCSI_REQ_INVALID;
+                               gSCSI->finished(request, 1);
+                       }
+                       break;
+               }
                case SCSI_OP_WRITE_SAME_16:
                {
-                       scsi_cmd_wsame_16 *cmd = (scsi_cmd_wsame_16 
*)request->cdb;
+                       const scsi_cmd_wsame_16 *cmd = (const scsi_cmd_wsame_16 
*)request->cdb;
 
                        // SCSI unmap is used for trim, otherwise we don't 
support it
                        if (!cmd->unmap) {
diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h
index 42b8e6b..962e5f7 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h
@@ -33,6 +33,7 @@ private:
        void            ScsiTestUnitReady(scsi_ccb *request);
        void            ScsiInquiry(scsi_ccb *request);
        void            ScsiReadCapacity(scsi_ccb *request);
+       void            ScsiReadCapacity16(scsi_ccb *request);
        void            ScsiReadWrite(scsi_ccb *request, uint64 lba, size_t 
sectorCount, bool isWrite);
        void            ScsiSynchronizeCache(scsi_ccb *request);
 


Other related posts: