[haiku-commits] haiku.r1alpha4: hrevr1alpha4-44654 - src/add-ons/kernel/busses/scsi/ahci

  • From: kallisti5@xxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 29 Oct 2012 18:50:08 +0100 (CET)

hrevr1alpha4-44654 adds 8 changesets to branch 'r1alpha4'
old head: e4ee8aa29ce320c3949c30893446754e08f6983e
new head: f75a9e1563030f4cad57d527883203dac85c3c0a

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

252ba05: make sure there are no pending interrupts during setup

ef8225c: set GHC.AE before performing reset (should be done by BIOS already)

4bd48c6: properly check intel port count and don't panic on more than 8.

bba08d9: add missing line breaks in debug output

773c5f2: cleanup variable naming for port count

5d1a895: gcc2 compile fix (gcc4 didn't complain)

e3c7f04: use template max() instead of max_c() macro

f75a9e1: 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> ]

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

4 files changed, 105 insertions(+), 36 deletions(-)
.../kernel/busses/scsi/ahci/ahci_controller.cpp  | 61 ++++++++++------
.../kernel/busses/scsi/ahci/ahci_controller.h    |  3 +-
.../kernel/busses/scsi/ahci/ahci_port.cpp        | 76 +++++++++++++++++---
src/add-ons/kernel/busses/scsi/ahci/ahci_port.h  |  1 +

############################################################################

Commit:      252ba057d37d8d0e10a9364ee133fe9d3e5bdd4c
URL:         http://cgit.haiku-os.org/haiku/commit/?id=252ba05
Author:      Marcus Overhagen <marcus@xxxxxxxxxxxx>
Date:        Fri Sep 14 16:16:51 2012 UTC
Committer:   Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>
Commit-Date: Mon Oct 29 17:42:40 2012 UTC

make sure there are no pending interrupts during setup

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

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
index 24ded54..311825f 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
@@ -122,6 +122,10 @@ AHCIController::Init()
                return B_ERROR;
        }
 
+       // make sure interrupts are disabled
+       fRegs->ghc &= ~GHC_IE;
+       FlushPostedWrites();
+
        if (ResetController() < B_OK) {
                TRACE("controller reset failed\n");
                goto err;
@@ -194,6 +198,12 @@ AHCIController::Init()
                }
        }
 
+       // clear any pending interrupts
+       uint32 interruptsPending;
+       interruptsPending = fRegs->is;
+       fRegs->is = interruptsPending; 
+       FlushPostedWrites();
+
        // enable interrupts
        fRegs->ghc |= GHC_IE;
        FlushPostedWrites();

############################################################################

Commit:      ef8225c4f0197b5b53b0923330371a68ba30108a
URL:         http://cgit.haiku-os.org/haiku/commit/?id=ef8225c
Author:      Marcus Overhagen <marcus@xxxxxxxxxxxx>
Date:        Fri Sep 14 16:19:11 2012 UTC
Committer:   Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>
Commit-Date: Mon Oct 29 17:43:17 2012 UTC

set GHC.AE before performing reset (should be done by BIOS already)

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

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
index 311825f..cf60573 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
@@ -266,6 +266,10 @@ AHCIController::ResetController()
        uint32 saveCaps = fRegs->cap & (CAP_SMPS | CAP_SSS | CAP_SPM | CAP_EMS 
| CAP_SXS);
        uint32 savePI = fRegs->pi;
 
+       // AHCI 1.3: Software may perform an HBA reset prior to initializing 
the controller
+       //           by setting GHC.AE to â1â and then setting GHC.HR to â1â if 
desired.
+       fRegs->ghc |= GHC_AE;
+       FlushPostedWrites();
        fRegs->ghc |= GHC_HR;
        FlushPostedWrites();
        if (wait_until_clear(&fRegs->ghc, GHC_HR, 1000000) < B_OK)

############################################################################

Commit:      4bd48c6a2dd86d2ad9bb9bd3de61de09bafae092
URL:         http://cgit.haiku-os.org/haiku/commit/?id=4bd48c6
Author:      Marcus Overhagen <marcus@xxxxxxxxxxxx>
Date:        Fri Sep 14 16:31:01 2012 UTC
Committer:   Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>
Commit-Date: Mon Oct 29 17:43:52 2012 UTC

properly check intel port count and don't panic on more than 8.

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

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
index cf60573..e23cddc 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
@@ -284,9 +284,12 @@ AHCIController::ResetController()
        if (fPCIVendorID == PCI_VENDOR_INTEL) {
                // Intel PCSâPort Control and Status
                // SATA port enable bits must be set
-               int portCount = 1 + ((fRegs->cap >> CAP_NP_SHIFT) & 
CAP_NP_MASK);
-               if (portCount > 8)
-                       panic("Intel AHCI: too many SATA ports! Please report 
at http://dev.haiku-os.org";);
+               int portCount = max_c(fls(fRegs->pi), 1 + ((fRegs->cap >> 
CAP_NP_SHIFT) & CAP_NP_MASK));
+               if (portCount > 8) {
+                       // TODO: fix this when specification available
+                       TRACE("don't know how to enable SATA ports 9 to %d\n", 
portCount);
+                       portCount = 8;
+               }
                uint16 pcs = fPCI->read_pci_config(fPCIDevice, 0x92, 2);
                pcs |= (0xff >> (8 - portCount));
                fPCI->write_pci_config(fPCIDevice, 0x92, 2, pcs);

############################################################################

Commit:      bba08d97c43545212145e61b1746fade3911af56
URL:         http://cgit.haiku-os.org/haiku/commit/?id=bba08d9
Author:      Marcus Overhagen <marcus@xxxxxxxxxxxx>
Date:        Fri Sep 14 16:42:00 2012 UTC
Committer:   Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>
Commit-Date: Mon Oct 29 17:44:15 2012 UTC

add missing line breaks in debug output

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

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
index e23cddc..3612f15 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
@@ -186,12 +186,12 @@ AHCIController::Init()
                if (fPortImplementedMask & (1 << i)) {
                        fPort[i] = new (std::nothrow)AHCIPort(this, i);
                        if (!fPort[i]) {
-                               TRACE("out of memory creating port %d", i);
+                               TRACE("out of memory creating port %d\n", i);
                                break;
                        }
                        status_t status = fPort[i]->Init1();
                        if (status < B_OK) {
-                               TRACE("init-1 port %d failed", i);
+                               TRACE("init-1 port %d failed\n", i);
                                delete fPort[i];
                                fPort[i] = NULL;
                        }
@@ -212,7 +212,7 @@ AHCIController::Init()
                if (fPort[i]) {
                        status_t status = fPort[i]->Init2();
                        if (status < B_OK) {
-                               TRACE("init-2 port %d failed", i);
+                               TRACE("init-2 port %d failed\n", i);
                                fPort[i]->Uninit();
                                delete fPort[i];
                                fPort[i] = NULL;
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 c4e4184..7cc78c1 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
@@ -398,12 +398,12 @@ AHCIPort::InterruptErrorHandler(uint32 is)
                TRACE("Interface Non Fatal Error\n");
        }
        if (is & PORT_INT_OF) {
-               TRACE("Overflow");
+               TRACE("Overflow\n");
                fResetPort = true;
                fError = true;
        }
        if (is & PORT_INT_IPM) {
-               TRACE("Incorrect Port Multiplier Status");
+               TRACE("Incorrect Port Multiplier Status\n");
        }
        if (is & PORT_INT_PRC) {
                TRACE("PhyReady Change\n");

############################################################################

Commit:      773c5f2fd1817cac4dcba1c25e950a9ce06e6768
URL:         http://cgit.haiku-os.org/haiku/commit/?id=773c5f2
Author:      Marcus Overhagen <marcus@xxxxxxxxxxxx>
Date:        Fri Sep 14 16:56:56 2012 UTC
Committer:   Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>
Commit-Date: Mon Oct 29 17:45:01 2012 UTC

cleanup variable naming for port count

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

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
index 3612f15..ab0bb0b 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
@@ -25,8 +25,7 @@ AHCIController::AHCIController(device_node *node,
        fPCIDeviceID(0xffff),
        fFlags(0),
        fCommandSlotCount(0),
-       fPortCountMax(0),
-       fPortCountAvail(0),
+       fPortCount(0),
        fPortImplementedMask(0),
        fIRQ(0),
        fInstanceCheck(-1)
@@ -132,29 +131,27 @@ AHCIController::Init()
        }
 
        fCommandSlotCount = 1 + ((fRegs->cap >> CAP_NCS_SHIFT) & CAP_NCS_MASK);
-       fPortCountMax = 1 + ((fRegs->cap >> CAP_NP_SHIFT) & CAP_NP_MASK);
+       fPortCount = 1 + ((fRegs->cap >> CAP_NP_SHIFT) & CAP_NP_MASK);
 
        fPortImplementedMask = fRegs->pi;
        // reported mask of implemented ports is sometimes empty
        if (fPortImplementedMask == 0) {
-               fPortImplementedMask = 0xffffffff >> (32 - fPortCountMax);
+               fPortImplementedMask = 0xffffffff >> (32 - fPortCount);
                TRACE("ports-implemented mask is zero, using 0x%" B_PRIx32 " 
instead.\n",
                        fPortImplementedMask);
        }
 
        // reported number of ports is sometimes too small
-       int maxPortIndex;
-       maxPortIndex = fls(fPortImplementedMask);
-       if (fPortCountMax < maxPortIndex) {
-               TRACE("reported number of ports is wrong, using %d instead.\n", 
maxPortIndex);
-               fPortCountMax = maxPortIndex;
+       int highestPort;
+       highestPort = fls(fPortImplementedMask); // 1-based, 1 to 32
+       if (fPortCount < highestPort) {
+               TRACE("reported number of ports is wrong, using %d instead.\n", 
highestPort);
+               fPortCount = highestPort;
        }
 
-       fPortCountAvail = count_bits_set(fPortImplementedMask);
-
        TRACE("cap: Interface Speed Support: generation %" B_PRIu32 "\n",       
(fRegs->cap >> CAP_ISS_SHIFT) & CAP_ISS_MASK);
        TRACE("cap: Number of Command Slots: %d (raw %#" B_PRIx32 ")\n",        
fCommandSlotCount, (fRegs->cap >> CAP_NCS_SHIFT) & CAP_NCS_MASK);
-       TRACE("cap: Number of Ports: %d (raw %#" B_PRIx32 ")\n",                
        fPortCountMax, (fRegs->cap >> CAP_NP_SHIFT) & CAP_NP_MASK);
+       TRACE("cap: Number of Ports: %d (raw %#" B_PRIx32 ")\n",                
        fPortCount, (fRegs->cap >> CAP_NP_SHIFT) & CAP_NP_MASK);
        TRACE("cap: Supports Port Multiplier: %s\n",            (fRegs->cap & 
CAP_SPM) ? "yes" : "no");
        TRACE("cap: Supports External SATA: %s\n",                      
(fRegs->cap & CAP_SXS) ? "yes" : "no");
        TRACE("cap: Enclosure Management Supported: %s\n",      (fRegs->cap & 
CAP_EMS) ? "yes" : "no");
@@ -172,7 +169,7 @@ AHCIController::Init()
        TRACE("cap: Supports AHCI mode only: %s\n",                     
(fRegs->cap & CAP_SAM) ? "yes" : "no");
        TRACE("ghc: AHCI Enable: %s\n",                                         
(fRegs->ghc & GHC_AE) ? "yes" : "no");
        TRACE("Ports Implemented Mask: %#08" B_PRIx32 "\n",     
fPortImplementedMask);
-       TRACE("Number of Available Ports: %d\n",                        
fPortCountAvail);
+       TRACE("Number of Available Ports: %d\n",                        
count_bits_set(fPortImplementedMask));
        TRACE("AHCI Version %" B_PRIu32 ".%" B_PRIu32 "\n",     fRegs->vs >> 
16, fRegs->vs & 0xff);
        TRACE("Interrupt %u\n",                                                 
        fIRQ);
 
@@ -182,7 +179,7 @@ AHCIController::Init()
                goto err;
        }
 
-       for (int i = 0; i < fPortCountMax; i++) {
+       for (int i = 0; i < fPortCount; i++) {
                if (fPortImplementedMask & (1 << i)) {
                        fPort[i] = new (std::nothrow)AHCIPort(this, i);
                        if (!fPort[i]) {
@@ -208,7 +205,7 @@ AHCIController::Init()
        fRegs->ghc |= GHC_IE;
        FlushPostedWrites();
 
-       for (int i = 0; i < fPortCountMax; i++) {
+       for (int i = 0; i < fPortCount; i++) {
                if (fPort[i]) {
                        status_t status = fPort[i]->Init2();
                        if (status < B_OK) {
@@ -234,7 +231,7 @@ AHCIController::Uninit()
 {
        TRACE("AHCIController::Uninit\n");
 
-       for (int i = 0; i < fPortCountMax; i++) {
+       for (int i = 0; i < fPortCount; i++) {
                if (fPort[i]) {
                        fPort[i]->Uninit();
                        delete fPort[i];
@@ -307,7 +304,7 @@ AHCIController::Interrupt(void *data)
        if (interruptPending == 0)
                return B_UNHANDLED_INTERRUPT;
 
-       for (int i = 0; i < self->fPortCountMax; i++) {
+       for (int i = 0; i < self->fPortCount; i++) {
                if (interruptPending & (1 << i)) {
                        if (self->fPort[i]) {
                                self->fPort[i]->Interrupt();
diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.h 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.h
index 9fd2a6b..c973d41 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.h
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.h
@@ -49,8 +49,7 @@ private:
        volatile ahci_hba *             fRegs;
        area_id                                 fRegsArea;
        int                                             fCommandSlotCount;
-       int                                             fPortCountMax;
-       int                                             fPortCountAvail;
+       int                                             fPortCount;
        uint32                                  fPortImplementedMask;
        uint8                                   fIRQ;
        AHCIPort *                              fPort[32];

############################################################################

Commit:      5d1a895cf49d44b9abee14c71c64ac1d92bcac8b
URL:         http://cgit.haiku-os.org/haiku/commit/?id=5d1a895
Author:      Marcus Overhagen <marcus@xxxxxxxxxxxx>
Date:        Fri Sep 14 17:29:34 2012 UTC
Committer:   Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>
Commit-Date: Mon Oct 29 17:46:08 2012 UTC

gcc2 compile fix (gcc4 didn't complain)

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

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
index ab0bb0b..0d7655a 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
@@ -281,7 +281,7 @@ AHCIController::ResetController()
        if (fPCIVendorID == PCI_VENDOR_INTEL) {
                // Intel PCSâPort Control and Status
                // SATA port enable bits must be set
-               int portCount = max_c(fls(fRegs->pi), 1 + ((fRegs->cap >> 
CAP_NP_SHIFT) & CAP_NP_MASK));
+               int portCount = max_c(fls(fRegs->pi), 1 + (int)((fRegs->cap >> 
CAP_NP_SHIFT) & CAP_NP_MASK));
                if (portCount > 8) {
                        // TODO: fix this when specification available
                        TRACE("don't know how to enable SATA ports 9 to %d\n", 
portCount);

############################################################################

Commit:      e3c7f0425cfce76313d75b23149c5890159cf241
URL:         http://cgit.haiku-os.org/haiku/commit/?id=e3c7f04
Author:      Marcus Overhagen <marcus@xxxxxxxxxxxx>
Date:        Fri Sep 14 18:20:29 2012 UTC
Committer:   Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>
Commit-Date: Mon Oct 29 17:46:36 2012 UTC

use template max() instead of max_c() macro

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

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
index 0d7655a..b5ed575 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
@@ -6,6 +6,7 @@
 #include "ahci_controller.h"
 #include "util.h"
 
+#include <algorithm>
 #include <KernelExport.h>
 #include <stdio.h>
 #include <string.h>
@@ -281,7 +282,7 @@ AHCIController::ResetController()
        if (fPCIVendorID == PCI_VENDOR_INTEL) {
                // Intel PCSâPort Control and Status
                // SATA port enable bits must be set
-               int portCount = max_c(fls(fRegs->pi), 1 + (int)((fRegs->cap >> 
CAP_NP_SHIFT) & CAP_NP_MASK));
+               int portCount = std::max(fls(fRegs->pi), 1 + (int)((fRegs->cap 
>> CAP_NP_SHIFT) & CAP_NP_MASK));
                if (portCount > 8) {
                        // TODO: fix this when specification available
                        TRACE("don't know how to enable SATA ports 9 to %d\n", 
portCount);

############################################################################

Revision:    hrevr1alpha4-44654
Commit:      f75a9e1563030f4cad57d527883203dac85c3c0a
URL:         http://cgit.haiku-os.org/haiku/commit/?id=f75a9e1
Author:      Marcus Overhagen <marcus@xxxxxxxxxxxx>
Date:        Fri Sep 14 20:21:47 2012 UTC
Committer:   Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>
Commit-Date: Mon Oct 29 17:47:08 2012 UTC

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

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

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: