Ticket #12357: ahci-rework-v4.diff

File ahci-rework-v4.diff, 16.1 KB (added by kallisti5, 5 years ago)
  • src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h

    diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h
    index b9c8c03..1e942cb 100644
    a b  
    55#ifndef _AHCI_DEFS_H
    66#define _AHCI_DEFS_H
    77
     8#include <ata_types.h>
    89#include <bus/PCI.h>
    910#include <bus/SCSI.h>
    1011#include <PCI_x86.h>
    enum {  
    9798#define IPM_TRANSITIONS_TO_PARTIAL_DISABLED 0x1
    9899#define IPM_TRANSITIONS_TO_SLUMBER_DISABLED 0x2
    99100
     101// Device signatures
     102#define SATA_SIG_ATA            0x00000101 // SATA drive
     103#define SATA_SIG_ATAPI          0xEB140101 // ATAPI drive
     104#define SATA_SIG_SEMB           0xC33C0101 // Enclosure management bridge
     105#define SATA_SIG_PM             0x96690101 // Port multiplier
    100106
    101107typedef struct {
    102108    uint32      clb;            // Command List Base Address
    enum {  
    130136    PORT_CMD_ATAPI  = (1 << 24),    // Device is ATAPI
    131137    PORT_CMD_CR     = (1 << 15),    // Command List Running (DMA active)
    132138    PORT_CMD_FR     = (1 << 14),    // FIS Receive Running
    133     PORT_CMD_FER    = (1 << 4),     // FIS Receive Enable
     139    PORT_CMD_FRE    = (1 << 4),     // FIS Receive Enable
    134140    PORT_CMD_CLO    = (1 << 3),     // Command List Override
    135141    PORT_CMD_POD    = (1 << 2),     // Power On Device
    136142    PORT_CMD_SUD    = (1 << 1),     // Spin-up Device
    enum {  
    167173                            | PORT_INT_DS | PORT_INT_PS | PORT_INT_DHR)
    168174
    169175enum {
    170     ATA_BSY         = 0x80,
    171     ATA_DF          = 0x20,
    172     ATA_DRQ         = 0x08,
    173     ATA_ERR         = 0x01,
    174 };
    175 
    176 
    177 enum {
    178176    PORT_FBS_DWE_SHIFT      = 16,   // Device With Error
    179177    PORT_FBS_DWE_MASK       = 0xf,
    180178    PORT_FBS_ADO_SHIFT      = 12,   // Active Device Optimization
  • src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp

    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 94a0034..45c7762 100644
    a b AHCIPort::AHCIPort(AHCIController* controller, int index)  
    5454    fSectorCount(0),
    5555    fIsATAPI(false),
    5656    fTestUnitReadyActive(false),
    57     fResetPort(false),
     57    fSoftReset(false),
    5858    fError(false),
    5959    fTrimSupported(false)
    6060{
    AHCIPort::Init1()  
    120120    fRegs->is = fRegs->is;
    121121
    122122    // clear error bits
    123     fRegs->serr = fRegs->serr;
     123    _ClearErrorRegister();
    124124
    125125    // power up device
    126126    fRegs->cmd |= PORT_CMD_POD;
    AHCIPort::Init1()  
    131131    // activate link
    132132    fRegs->cmd = (fRegs->cmd & ~PORT_CMD_ICC_MASK) | PORT_CMD_ICC_ACTIVE;
    133133
    134     // enable FIS receive
    135     fRegs->cmd |= PORT_CMD_FER;
     134    // enable FIS receive (enabled when fb set, only to be disabled when unset)
     135    fRegs->cmd |= PORT_CMD_FRE;
    136136
    137137    FlushPostedWrites();
    138138
    AHCIPort::Init2()  
    146146{
    147147    TRACE("AHCIPort::Init2 port %d\n", fIndex);
    148148
    149     // start DMA engine
    150     fRegs->cmd |= PORT_CMD_ST;
     149    // enable port
     150    Enable();
    151151
    152152    // enable interrupts
    153153    fRegs->ie = PORT_INT_MASK;
    154154
    155155    FlushPostedWrites();
    156156
    157     ResetPort(true);
     157    // reset port and probe info
     158    SoftReset();
    158159
    159160    TRACE("ie   0x%08" B_PRIx32 "\n", fRegs->ie);
    160161    TRACE("is   0x%08" B_PRIx32 "\n", fRegs->is);
    AHCIPort::Init2()  
    172173
    173174    fDevicePresent = (fRegs->ssts & 0xf) == 0x3;
    174175
     176    TRACE("%s: port %d, device %s\n", __func__, fIndex,
     177        fDevicePresent ? "present" : "absent");
     178
    175179    return B_OK;
    176180}
    177181
    AHCIPort::Uninit()  
    181185{
    182186    TRACE("AHCIPort::Uninit port %d\n", fIndex);
    183187
    184     // disable FIS receive
    185     fRegs->cmd &= ~PORT_CMD_FER;
     188    // Spec v1.3.1, §10.3.2 - Shut down port before unsetting FRE
    186189
    187     // wait for receive completion, up to 500ms
    188     if (wait_until_clear(&fRegs->cmd, PORT_CMD_FR, 500000) < B_OK) {
    189         TRACE("AHCIPort::Uninit port %d error FIS rx still running\n", fIndex);
     190    // shutdown the port
     191    if (!Disable()) {
     192        ERROR("%s: port %d error, unable to shutdown before FRE clear!\n",
     193            __func__, fIndex);
     194        return;
    190195    }
    191196
    192     // stop DMA engine
    193     fRegs->cmd &= ~PORT_CMD_ST;
    194 
    195     // wait for DMA completion
    196     if (wait_until_clear(&fRegs->cmd, PORT_CMD_CR, 500000) < B_OK) {
    197         TRACE("AHCIPort::Uninit port %d error DMA engine still running\n",
    198             fIndex);
    199     }
     197    // Clear FRE and wait for completion
     198    fRegs->cmd &= ~PORT_CMD_FRE;
     199    if (wait_until_clear(&fRegs->cmd, PORT_CMD_FR, 500000) < B_OK)
     200        ERROR("%s: port %d error FIS rx still running\n", __func__, fIndex);
    200201
    201202    // disable interrupts
    202203    fRegs->ie = 0;
    void  
    218219AHCIPort::ResetDevice()
    219220{
    220221    // perform a hard reset
    221     if (!_HardReset())
     222    if (PortReset() != B_OK) {
     223        ERROR("%s: port %d unable to hard reset device\n", __func__, fIndex);
    222224        return;
     225    }
    223226
    224227    if (wait_until_set(&fRegs->ssts, 0x1, 100000) < B_OK)
    225228        TRACE("AHCIPort::ResetDevice port %d no device detected\n", fIndex);
    AHCIPort::ResetDevice()  
    238241
    239242
    240243status_t
    241 AHCIPort::ResetPort(bool forceDeviceReset)
     244AHCIPort::SoftReset()
    242245{
    243     if (!fTestUnitReadyActive)
    244         TRACE("AHCIPort::ResetPort port %d\n", fIndex);
     246    TRACE("AHCIPort::SoftReset port %d\n", fIndex);
    245247
    246     // stop DMA engine
    247     fRegs->cmd &= ~PORT_CMD_ST;
    248     FlushPostedWrites();
     248    // Spec v1.3.1, §10.4.1 Software Reset
     249    // A single device on one port is reset, HBA and phy comm remain intact.
    249250
    250     if (wait_until_clear(&fRegs->cmd, PORT_CMD_CR, 500000) < B_OK) {
    251         TRACE("AHCIPort::ResetPort port %d error DMA engine doesn't stop\n",
    252             fIndex);
     251    // stop port, flush transactions
     252    if (!Disable()) {
     253        // If the port doesn't power off, move on to a stronger reset.
     254        ERROR("%s: port %d soft reset failed. Moving on to port reset.\n",
     255            __func__, fIndex);
     256        return PortReset();
    253257    }
    254258
    255     bool deviceBusy = fRegs->tfd & (ATA_BSY | ATA_DRQ);
     259    // TODO: If FBS Enable, clear PxFBS.EN prior to issuing sw reset
    256260
    257     if (!fTestUnitReadyActive) {
    258         TRACE("AHCIPort::ResetPort port %d, deviceBusy %d, "
    259             "forceDeviceReset %d\n", fIndex, deviceBusy, forceDeviceReset);
     261    // If the port is still busy, move on to port reset.
     262    if (fRegs->tfd & (ATA_STATUS_BUSY | ATA_STATUS_DATA_REQUEST)) {
     263        ERROR("%s: port %d still busy. Moving on to port reset.\n",
     264            __func__, fIndex);
     265        return PortReset();
    260266    }
    261267
    262     if (deviceBusy || forceDeviceReset)
    263         ResetDevice();
    264 
    265     // start DMA engine
    266     fRegs->cmd |= PORT_CMD_ST;
     268    // ATA Reset
     269    fCommandList->r = 1;
     270    // ATA Clear Busy
     271    fCommandList->c = 1;
     272    // Issue Command
     273    fRegs->ci = 1;
    267274    FlushPostedWrites();
    268275
     276    if (wait_until_clear(&fRegs->tfd, ATA_STATUS_BUSY | ATA_STATUS_DATA_REQUEST,
     277        1000000) < B_OK) {
     278        ERROR("%s: port %d software reset failed. Doing port reset...\n",
     279            __func__, fIndex);
     280        return PortReset();
     281    }
     282
     283    // start port
     284    Enable();
     285
    269286    return PostReset();
    270287}
    271288
    272289
    273290status_t
    274 AHCIPort::PostReset()
     291AHCIPort::PortReset()
    275292{
    276     if (!fTestUnitReadyActive)
    277         TRACE("AHCIPort::PostReset port %d\n", fIndex);
     293    TRACE("AHCIPort::PortReset port %d\n", fIndex);
     294
     295    // Spec v1.3.1, §10.4.2 Port Reset
     296    // Physical comm between HBA and port disabled. More Intrusive
     297    if (!Disable()) {
     298        ERROR("%s: port %d unable to reset!\n", __func__, fIndex);
     299        return B_ERROR;
     300    }
     301
     302    fRegs->sctl = (fRegs->sctl & ~SATA_CONTROL_DET_MASK)
     303        | DET_INITIALIZATION << SATA_CONTROL_DET_SHIFT;
     304    FlushPostedWrites();
     305    spin(1100);
     306        // You must wait 1ms at minimum
     307    fRegs->sctl = (fRegs->sctl & ~SATA_CONTROL_DET_MASK)
     308        | DET_NO_INITIALIZATION << SATA_CONTROL_DET_SHIFT;
     309    FlushPostedWrites();
    278310
    279     if ((fRegs->ssts & 0xf) != 0x3 || (fRegs->tfd & 0xff) == 0x7f) {
    280         TRACE("AHCIPort::PostReset port %d: no device\n", fIndex);
    281         return B_OK;
     311    if (wait_until_set(&fRegs->ssts, 0x3, 500000) < B_OK) {
     312        TRACE("AHCIPort::PortReset port %d device present but no phy "
     313            "communication\n", fIndex);
     314        return B_ERROR;
    282315    }
    283316
     317    //if ((fRegs->tfd & 0xff) == 0x7f) {
     318    //  TRACE("AHCIPort::PostReset port %d: no device\n", fIndex);
     319    //  return B_OK;
     320    //}
     321
     322    Enable();
     323
     324    return PostReset();
     325}
     326
     327
     328status_t
     329AHCIPort::PostReset()
     330{
    284331    if ((fRegs->tfd & 0xff) == 0xff)
    285332        snooze(200000);
    286333
    AHCIPort::PostReset()  
    290337        return B_ERROR;
    291338    }
    292339
    293     wait_until_clear(&fRegs->tfd, ATA_BSY, 31000000);
    294 
    295     fIsATAPI = fRegs->sig == 0xeb140101;
     340    wait_until_clear(&fRegs->tfd, ATA_STATUS_BUSY, 31000000);
    296341
     342    fIsATAPI = fRegs->sig == SATA_SIG_ATAPI;
    297343    if (fIsATAPI)
    298344        fRegs->cmd |= PORT_CMD_ATAPI;
    299345    else
    AHCIPort::PostReset()  
    302348
    303349    if (!fTestUnitReadyActive) {
    304350        TRACE("device signature 0x%08" B_PRIx32 " (%s)\n", fRegs->sig,
    305             fRegs->sig == 0xeb140101 ? "ATAPI" : fRegs->sig == 0x00000101
     351            fRegs->sig == SATA_SIG_ATAPI ? "ATAPI" : fRegs->sig == SATA_SIG_ATA
    306352                ? "ATA" : "unknown");
    307353    }
    308354
     355    _ClearErrorRegister();
     356
    309357    return B_OK;
    310358}
    311359
    AHCIPort::InterruptErrorHandler(uint32 is)  
    374422    }
    375423
    376424    // read and clear SError
    377     uint32 serr = fRegs->serr;
    378     fRegs->serr = serr;
     425    _ClearErrorRegister();
    379426
    380427    if (is & PORT_INT_TFE) {
    381428        if (!fTestUnitReadyActive)
    382429            TRACE("Task File Error\n");
    383430
    384         fResetPort = true;
     431        fSoftReset = true;
    385432        fError = true;
    386433    }
    387434    if (is & PORT_INT_HBF) {
    388435        TRACE("Host Bus Fatal Error\n");
    389         fResetPort = true;
     436        fSoftReset = true;
    390437        fError = true;
    391438    }
    392439    if (is & PORT_INT_HBD) {
    393440        TRACE("Host Bus Data Error\n");
    394         fResetPort = true;
     441        fSoftReset = true;
    395442        fError = true;
    396443    }
    397444    if (is & PORT_INT_IF) {
    398445        TRACE("Interface Fatal Error\n");
    399         fResetPort = true;
     446        fSoftReset = true;
    400447        fError = true;
    401448    }
    402449    if (is & PORT_INT_INF) {
    AHCIPort::InterruptErrorHandler(uint32 is)  
    404451    }
    405452    if (is & PORT_INT_OF) {
    406453        TRACE("Overflow\n");
    407         fResetPort = true;
     454        fSoftReset = true;
    408455        fError = true;
    409456    }
    410457    if (is & PORT_INT_IPM) {
    AHCIPort::InterruptErrorHandler(uint32 is)  
    412459    }
    413460    if (is & PORT_INT_PRC) {
    414461        TRACE("PhyReady Change\n");
    415 //      fResetPort = true;
     462//      fSoftReset = true;
    416463    }
    417464    if (is & PORT_INT_PC) {
    418465        TRACE("Port Connect Change\n");
    419466        // Spec v1.3, §6.2.2.3 Recovery of Unsolicited COMINIT
    420 
    421         // perform a hard reset
    422         if (!_HardReset())
    423             return;
    424 
    425         // clear error bits to clear PxSERR.DIAG.X
     467        // Spec v1.3.1, §7.4 Interaction of command list and port change status
     468        // TODO: Issue COMRESET ?
     469        //PortReset();
     470        //HBAReset(); ???
    426471        _ClearErrorRegister();
    427472    }
    428473    if (is & PORT_INT_UF) {
    429474        TRACE("Unknown FIS\n");
    430         fResetPort = true;
     475        fSoftReset = true;
    431476    }
    432477
    433478    if (fError) {
    AHCIPort::FillPrdTable(volatile prd* prdTable, int* prdCount, int prdMax,  
    452497    status_t status = get_memory_map_etc(B_CURRENT_TEAM, data, dataSize,
    453498        entries, &entriesUsed);
    454499    if (status != B_OK) {
    455         TRACE("AHCIPort::FillPrdTable get_memory_map() failed: %s\n",
    456             strerror(status));
     500        TRACE("%s: get_memory_map() failed: %s\n", __func__, strerror(status));
    457501        return B_ERROR;
    458502    }
    459503
    AHCIPort::FillPrdTable(volatile prd* prdTable, int* prdCount, int prdMax,  
    500544        sgCount--;
    501545    }
    502546    if (*prdCount == 0) {
    503         TRACE("AHCIPort::FillPrdTable: count is 0\n");
     547        TRACE("%s: count is 0\n", __func__);
    504548        return B_ERROR;
    505549    }
    506550    if (dataSize > 0) {
    AHCIPort::ScsiInquiry(scsi_ccb* request)  
    663707    ExecuteSataRequest(&sreq);
    664708    sreq.WaitForCompletion();
    665709
    666     if ((sreq.CompletionStatus() & ATA_ERR) != 0) {
     710    if ((sreq.CompletionStatus() & ATA_STATUS_ERROR) != 0) {
    667711        ERROR("identify device failed\n");
    668712        request->subsys_status = SCSI_REQ_CMP_ERR;
    669713        gSCSI->finished(request, 1);
    for (uint32 i = 0; i < lbaRangeCount; i++) {  
    10051049        ExecuteSataRequest(&sreq);
    10061050        sreq.WaitForCompletion();
    10071051
    1008         if ((sreq.CompletionStatus() & ATA_ERR) != 0) {
     1052        if ((sreq.CompletionStatus() & ATA_STATUS_ERROR) != 0) {
    10091053            TRACE("trim failed (%" B_PRIu32 " ranges)!\n", lbaRangeCount);
    10101054            request->subsys_status = SCSI_REQ_CMP_ERR;
    10111055        } else
    AHCIPort::ExecuteSataRequest(sata_request* request, bool isWrite)  
    10571101    fCommandList->prdtl = prdEntrys;
    10581102    fCommandList->prdbc = 0;
    10591103
    1060     if (wait_until_clear(&fRegs->tfd, ATA_BSY | ATA_DRQ, 1000000) < B_OK) {
     1104    if (wait_until_clear(&fRegs->tfd, ATA_STATUS_BUSY | ATA_STATUS_DATA_REQUEST,
     1105            1000000) < B_OK) {
    10611106        TRACE("ExecuteAtaRequest port %d: device is busy\n", fIndex);
    1062         ResetPort();
     1107        SoftReset();
    10631108        FinishTransfer();
    10641109        request->Abort();
    10651110        return;
    AHCIPort::ExecuteSataRequest(sata_request* request, bool isWrite)  
    10941139    TRACE("tfd  0x%08" B_PRIx32 "\n", fRegs->tfd);
    10951140*/
    10961141
    1097     if (fResetPort || status == B_TIMED_OUT) {
    1098         fResetPort = false;
    1099         ResetPort();
     1142    if (fSoftReset || status == B_TIMED_OUT) {
     1143        fSoftReset = false;
     1144        SoftReset();
    11001145    }
    11011146
    11021147    size_t bytesTransfered = fCommandList->prdbc;
    AHCIPort::ScsiGetRestrictions(bool* isATAPI, bool* noAutoSense,  
    13221367
    13231368
    13241369bool
    1325 AHCIPort::_HardReset()
     1370AHCIPort::Enable()
    13261371{
     1372    // Spec v1.3.1, §10.3.1 Start (PxCMD.ST)
     1373    TRACE("%s: port %d\n", __func__, fIndex);
    13271374    if ((fRegs->cmd & PORT_CMD_ST) != 0) {
    1328         // We shouldn't perform a reset, but at least document it
    1329         TRACE("AHCIPort::_HardReset() PORT_CMD_ST set, behaviour undefined\n");
     1375        TRACE("%s: Starting port already running!\n", __func__);
    13301376        return false;
    13311377    }
    13321378
    1333     fRegs->sctl = (fRegs->sctl & ~SATA_CONTROL_DET_MASK)
    1334         | DET_INITIALIZATION << SATA_CONTROL_DET_SHIFT;
     1379    if ((fRegs->cmd & PORT_CMD_FRE) == 0) {
     1380        TRACE("%s: Unable to start port without FRE enabled!\n", __func__);
     1381        return false;
     1382    }
     1383
     1384    // Clear DMA engine and wait for completion
     1385    if (wait_until_clear(&fRegs->cmd, PORT_CMD_CR, 500000) < B_OK) {
     1386        TRACE("%s: port %d error DMA engine still running\n", __func__,
     1387            fIndex);
     1388        return false;
     1389    }
     1390    // Start port
     1391    fRegs->cmd |= PORT_CMD_ST;
    13351392    FlushPostedWrites();
    1336     spin(1100);
    1337         // You must wait 1ms at minimum
    1338     fRegs->sctl = (fRegs->sctl & ~SATA_CONTROL_DET_MASK)
    1339         | DET_NO_INITIALIZATION << SATA_CONTROL_DET_SHIFT;
     1393    return true;
     1394}
     1395
     1396
     1397bool
     1398AHCIPort::Disable()
     1399{
     1400    TRACE("%s: port %d\n", __func__, fIndex);
     1401
     1402    if ((fRegs->cmd & PORT_CMD_ST) == 0) {
     1403        TRACE("%s: port %d attempting to disable stopped port.\n",
     1404            __func__, fIndex);
     1405    }
     1406
     1407    // Disable port
     1408    fRegs->cmd &= ~PORT_CMD_ST;
    13401409    FlushPostedWrites();
    13411410
     1411    // Spec v1.3.1, §10.4.2 Port Reset - assume hung after 500 mil.
     1412    // Clear DMA engine and wait for completion
     1413    if (wait_until_clear(&fRegs->cmd, PORT_CMD_CR, 500000) < B_OK) {
     1414        TRACE("%s: port %d error DMA engine still running\n", __func__,
     1415            fIndex);
     1416        return false;
     1417    }
     1418
    13421419    return true;
    13431420}
    13441421
  • src/add-ons/kernel/busses/scsi/ahci/ahci_port.h

    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 0bc4e67..deed571 100644
    a b private:  
    4848    void        ExecuteSataRequest(sata_request *request, bool isWrite = false);
    4949
    5050    void        ResetDevice();
    51     status_t    ResetPort(bool forceDeviceReset = false);
     51    status_t    SoftReset();
     52    status_t    PortReset();
    5253    status_t    PostReset();
     54
     55    bool        Enable();
     56    bool        Disable();
     57
    5358    void        FlushPostedWrites();
    5459    void        DumpD2HFis();
    5560
    private:  
    5762    status_t    WaitForTransfer(int *tfd, bigtime_t timeout);
    5863    void        FinishTransfer();
    5964
    60     inline  bool                _HardReset();
    6165    inline  void                _ClearErrorRegister();
    6266
    6367//  uint8 *     SetCommandFis(volatile command_list_entry *cmd, volatile fis *fis, const void *data, size_t dataSize);
    private:  
    7983    uint64                          fSectorCount;
    8084    bool                            fIsATAPI;
    8185    bool                            fTestUnitReadyActive;
    82     bool                            fResetPort;
     86    bool                            fSoftReset;
    8387    bool                            fError;
    8488    bool                            fTrimSupported;
    8589    uint32                          fMaxTrimRangeBlocks;
  • src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp

    diff --git a/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp
    index 6a53fcf..9e06dce 100644
    a b sata_request::SetATAPICommand(size_t transferLength)  
    121121void
    122122sata_request::Finish(int tfd, size_t bytesTransfered)
    123123{
    124     if ((tfd & (ATA_ERR | ATA_DF)) != 0) {
     124    if ((tfd & (ATA_STATUS_ERROR | ATA_STATUS_DEVICE_FAULT)) != 0) {
    125125        uint8 status = tfd & 0xff;
    126126        uint8 error = (tfd >> 8) & 0xff;
    127127
    sata_request::Finish(int tfd, size_t bytesTransfered)  
    135135        fCcb->data_resid = fCcb->data_length - bytesTransfered;
    136136        fCcb->device_status = SCSI_STATUS_GOOD;
    137137        fCcb->subsys_status = SCSI_REQ_CMP;
    138         if (tfd & (ATA_ERR | ATA_DF)) {
     138        if (tfd & (ATA_STATUS_ERROR | ATA_STATUS_DEVICE_FAULT)) {
    139139            fCcb->subsys_status = SCSI_REQ_CMP_ERR;
    140140            if (fIsATAPI) {
    141141                if (!IsTestUnitReady()) {
    sata_request::Abort()  
    187187        gSCSI->finished(fCcb, 1);
    188188        delete this;
    189189    } else {
    190         fCompletionStatus = ATA_ERR;
     190        fCompletionStatus = ATA_STATUS_ERROR;
    191191        release_sem(fCompletionSem);
    192192    }
    193193}