VirtualBox

Changeset 50282 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Jan 30, 2014 11:20:09 AM (11 years ago)
Author:
vboxsync
Message:

Storage/AHCI: check the correct return code when unmounting a SATA CDROM; coding style

Location:
trunk/src/VBox/Devices/Storage
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevAHCI.cpp

    r50037 r50282  
    41424142                {
    41434143                    case 0x0: /* Physical format information */
     4144                    {
     4145                        int layer = pAhciReq->aATAPICmd[6];
     4146                        uint64_t total_sectors;
     4147
     4148                        if (layer != 0)
    41444149                        {
    4145                             int layer = pAhciReq->aATAPICmd[6];
    4146                             uint64_t total_sectors;
    4147 
    4148                             if (layer != 0)
    4149                             {
    4150                                 uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET;
    4151                                 break;
    4152                             }
    4153 
    4154                             total_sectors = pAhciPort->cTotalSectors;
    4155                             total_sectors >>= 2;
    4156                             if (total_sectors == 0)
    4157                             {
    4158                                 uASC = -SCSI_ASC_MEDIUM_NOT_PRESENT;
    4159                                 break;
    4160                             }
    4161 
    4162                             buf[4] = 1;   /* DVD-ROM, part version 1 */
    4163                             buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
    4164                             buf[6] = 1;   /* one layer, read-only (per MMC-2 spec) */
    4165                             buf[7] = 0;   /* default densities */
    4166 
    4167                             /* FIXME: 0x30000 per spec? */
    4168                             ataH2BE_U32(buf + 8, 0); /* start sector */
    4169                             ataH2BE_U32(buf + 12, total_sectors - 1); /* end sector */
    4170                             ataH2BE_U32(buf + 16, total_sectors - 1); /* l0 end sector */
    4171 
    4172                             /* Size of buffer, not including 2 byte size field */
    4173                             ataH2BE_U32(&buf[0], 2048 + 2);
    4174 
    4175                             /* 2k data + 4 byte header */
    4176                             uASC = (2048 + 4);
     4150                            uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET;
     4151                            break;
    41774152                        }
     4153
     4154                        total_sectors = pAhciPort->cTotalSectors;
     4155                        total_sectors >>= 2;
     4156                        if (total_sectors == 0)
     4157                        {
     4158                            uASC = -SCSI_ASC_MEDIUM_NOT_PRESENT;
     4159                            break;
     4160                        }
     4161
     4162                        buf[4] = 1;   /* DVD-ROM, part version 1 */
     4163                        buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
     4164                        buf[6] = 1;   /* one layer, read-only (per MMC-2 spec) */
     4165                        buf[7] = 0;   /* default densities */
     4166
     4167                        /* FIXME: 0x30000 per spec? */
     4168                        ataH2BE_U32(buf + 8, 0); /* start sector */
     4169                        ataH2BE_U32(buf + 12, total_sectors - 1); /* end sector */
     4170                        ataH2BE_U32(buf + 16, total_sectors - 1); /* l0 end sector */
     4171
     4172                        /* Size of buffer, not including 2 byte size field */
     4173                        ataH2BE_U32(&buf[0], 2048 + 2);
     4174
     4175                        /* 2k data + 4 byte header */
     4176                        uASC = (2048 + 4);
    41784177                        break;
     4178                    }
    41794179                    case 0x01: /* DVD copyright information */
    41804180                        buf[4] = 0; /* no copyright data */
     
    43464346static AHCITXDIR atapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
    43474347{
    4348     AHCITXDIR rc = AHCITXDIR_NONE;
     4348    AHCITXDIR enmTxDir = AHCITXDIR_NONE;
    43494349    const uint8_t *pbPacket;
    43504350    uint32_t cbMax;
     
    43744374            break;
    43754375        case SCSI_MODE_SENSE_10:
     4376        {
     4377            uint8_t uPageControl, uPageCode;
     4378            cbMax = ataBE2H_U16(pbPacket + 7);
     4379            uPageControl = pbPacket[2] >> 6;
     4380            uPageCode = pbPacket[2] & 0x3f;
     4381            switch (uPageControl)
    43764382            {
    4377                 uint8_t uPageControl, uPageCode;
    4378                 cbMax = ataBE2H_U16(pbPacket + 7);
    4379                 uPageControl = pbPacket[2] >> 6;
    4380                 uPageCode = pbPacket[2] & 0x3f;
    4381                 switch (uPageControl)
    4382                 {
    4383                     case SCSI_PAGECONTROL_CURRENT:
    4384                         switch (uPageCode)
    4385                         {
    4386                             case SCSI_MODEPAGE_ERROR_RECOVERY:
    4387                                 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY);
    4388                                 break;
    4389                             case SCSI_MODEPAGE_CD_STATUS:
    4390                                 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS);
    4391                                 break;
    4392                             default:
    4393                                 goto error_cmd;
    4394                         }
    4395                         break;
    4396                     case SCSI_PAGECONTROL_CHANGEABLE:
    4397                         goto error_cmd;
    4398                     case SCSI_PAGECONTROL_DEFAULT:
    4399                         goto error_cmd;
    4400                     default:
    4401                     case SCSI_PAGECONTROL_SAVED:
    4402                         atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
    4403                         break;
    4404                 }
     4383                case SCSI_PAGECONTROL_CURRENT:
     4384                    switch (uPageCode)
     4385                    {
     4386                        case SCSI_MODEPAGE_ERROR_RECOVERY:
     4387                            atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY);
     4388                            break;
     4389                        case SCSI_MODEPAGE_CD_STATUS:
     4390                            atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS);
     4391                            break;
     4392                        default:
     4393                            goto error_cmd;
     4394                    }
     4395                    break;
     4396                case SCSI_PAGECONTROL_CHANGEABLE:
     4397                    goto error_cmd;
     4398                case SCSI_PAGECONTROL_DEFAULT:
     4399                    goto error_cmd;
     4400                default:
     4401                case SCSI_PAGECONTROL_SAVED:
     4402                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
     4403                    break;
    44054404            }
    44064405            break;
     4406        }
    44074407        case SCSI_REQUEST_SENSE:
    44084408            cbMax = pbPacket[4];
     
    44234423        case SCSI_READ_10:
    44244424        case SCSI_READ_12:
     4425        {
     4426            uint32_t cSectors, iATAPILBA;
     4427
     4428            if (pAhciPort->cNotifiedMediaChange > 0)
    44254429            {
    4426                 uint32_t cSectors, iATAPILBA;
    4427 
    4428                 if (pAhciPort->cNotifiedMediaChange > 0)
     4430                pAhciPort->cNotifiedMediaChange-- ;
     4431                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     4432                break;
     4433            }
     4434            if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
     4435            {
     4436                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     4437                break;
     4438            }
     4439            if (pbPacket[0] == SCSI_READ_10)
     4440                cSectors = ataBE2H_U16(pbPacket + 7);
     4441            else
     4442                cSectors = ataBE2H_U32(pbPacket + 6);
     4443            iATAPILBA = ataBE2H_U32(pbPacket + 2);
     4444            if (cSectors == 0)
     4445            {
     4446                atapiCmdOK(pAhciPort, pAhciReq);
     4447                break;
     4448            }
     4449            if ((uint64_t)iATAPILBA + cSectors > pAhciPort->cTotalSectors)
     4450            {
     4451                /* Rate limited logging, one log line per second. For
     4452                 * guests that insist on reading from places outside the
     4453                 * valid area this often generates too many release log
     4454                 * entries otherwise. */
     4455                static uint64_t s_uLastLogTS = 0;
     4456                if (RTTimeMilliTS() >= s_uLastLogTS + 1000)
    44294457                {
    4430                     pAhciPort->cNotifiedMediaChange-- ;
    4431                     atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     4458                    LogRel(("AHCI ATAPI: LUN#%d: CD-ROM block number %Ld invalid (READ)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA + cSectors));
     4459                    s_uLastLogTS = RTTimeMilliTS();
     4460                }
     4461                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
     4462                break;
     4463            }
     4464            atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048);
     4465            enmTxDir = AHCITXDIR_READ;
     4466            break;
     4467        }
     4468        case SCSI_READ_CD:
     4469        {
     4470            uint32_t cSectors, iATAPILBA;
     4471
     4472            if (pAhciPort->cNotifiedMediaChange > 0)
     4473            {
     4474                pAhciPort->cNotifiedMediaChange-- ;
     4475                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     4476                break;
     4477            }
     4478            else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
     4479            {
     4480                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     4481                break;
     4482            }
     4483            cSectors = (pbPacket[6] << 16) | (pbPacket[7] << 8) | pbPacket[8];
     4484            iATAPILBA = ataBE2H_U32(pbPacket + 2);
     4485            if (cSectors == 0)
     4486            {
     4487                atapiCmdOK(pAhciPort, pAhciReq);
     4488                break;
     4489            }
     4490            if ((uint64_t)iATAPILBA + cSectors > pAhciPort->cTotalSectors)
     4491            {
     4492                /* Rate limited logging, one log line per second. For
     4493                 * guests that insist on reading from places outside the
     4494                 * valid area this often generates too many release log
     4495                 * entries otherwise. */
     4496                static uint64_t s_uLastLogTS = 0;
     4497                if (RTTimeMilliTS() >= s_uLastLogTS + 1000)
     4498                {
     4499                    LogRel(("AHCI ATA: LUN#%d: CD-ROM block number %Ld invalid (READ CD)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA + cSectors));
     4500                    s_uLastLogTS = RTTimeMilliTS();
     4501                }
     4502                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
     4503                break;
     4504            }
     4505            switch (pbPacket[9] & 0xf8)
     4506            {
     4507                case 0x00:
     4508                    /* nothing */
     4509                    atapiCmdOK(pAhciPort, pAhciReq);
     4510                    break;
     4511                case 0x10:
     4512                    /* normal read */
     4513                    atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048);
     4514                    enmTxDir = AHCITXDIR_READ;
     4515                    break;
     4516                case 0xf8:
     4517                    /* read all data */
     4518                    atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2352);
     4519                    enmTxDir = AHCITXDIR_READ;
     4520                    break;
     4521                default:
     4522                    LogRel(("AHCI ATAPI: LUN#%d: CD-ROM sector format not supported\n", pAhciPort->iLUN));
     4523                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
     4524                    break;
     4525            }
     4526            break;
     4527        }
     4528        case SCSI_SEEK_10:
     4529        {
     4530            uint32_t iATAPILBA;
     4531            if (pAhciPort->cNotifiedMediaChange > 0)
     4532            {
     4533                pAhciPort->cNotifiedMediaChange-- ;
     4534                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     4535                break;
     4536            }
     4537            else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
     4538            {
     4539                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     4540                break;
     4541            }
     4542            iATAPILBA = ataBE2H_U32(pbPacket + 2);
     4543            if (iATAPILBA > pAhciPort->cTotalSectors)
     4544            {
     4545                /* Rate limited logging, one log line per second. For
     4546                 * guests that insist on seeking to places outside the
     4547                 * valid area this often generates too many release log
     4548                 * entries otherwise. */
     4549                static uint64_t s_uLastLogTS = 0;
     4550                if (RTTimeMilliTS() >= s_uLastLogTS + 1000)
     4551                {
     4552                    LogRel(("AHCI ATAPI: LUN#%d: CD-ROM block number %Ld invalid (SEEK)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA));
     4553                    s_uLastLogTS = RTTimeMilliTS();
     4554                }
     4555                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
     4556                break;
     4557            }
     4558            atapiCmdOK(pAhciPort, pAhciReq);
     4559            pAhciReq->uATARegStatus |= ATA_STAT_SEEK; /* Linux expects this. */
     4560            break;
     4561        }
     4562        case SCSI_START_STOP_UNIT:
     4563        {
     4564            int rc = VINF_SUCCESS;
     4565            switch (pbPacket[4] & 3)
     4566            {
     4567                case 0: /* 00 - Stop motor */
     4568                case 1: /* 01 - Start motor */
     4569                    break;
     4570                case 2: /* 10 - Eject media */
     4571                {
     4572                    /* This must be done from EMT. */
     4573                    PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
     4574                    PPDMDEVINS pDevIns = pAhci->CTX_SUFF(pDevIns);
     4575
     4576                    rc = VMR3ReqPriorityCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
     4577                                                 (PFNRT)pAhciPort->pDrvMount->pfnUnmount, 3,
     4578                                                 pAhciPort->pDrvMount, false/*=fForce*/, true/*=fEject*/);
     4579                    Assert(RT_SUCCESS(rc) || rc == VERR_PDM_MEDIA_LOCKED || rc = VERR_PDM_MEDIA_NOT_MOUNTED);
     4580                    if (RT_SUCCESS(rc) && pAhci->pMediaNotify)
     4581                    {
     4582                        rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
     4583                                               (PFNRT)pAhci->pMediaNotify->pfnEjected, 2,
     4584                                               pAhci->pMediaNotify, pAhciPort->iLUN);
     4585                        AssertRC(rc);
     4586                    }
    44324587                    break;
    44334588                }
    4434                 if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
    4435                 {
    4436                     atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     4589                case 3: /* 11 - Load media */
     4590                    /** @todo rc = s->pDrvMount->pfnLoadMedia(s->pDrvMount) */
    44374591                    break;
    4438                 }
    4439                 if (pbPacket[0] == SCSI_READ_10)
    4440                     cSectors = ataBE2H_U16(pbPacket + 7);
    4441                 else
    4442                     cSectors = ataBE2H_U32(pbPacket + 6);
    4443                 iATAPILBA = ataBE2H_U32(pbPacket + 2);
    4444                 if (cSectors == 0)
    4445                 {
    4446                     atapiCmdOK(pAhciPort, pAhciReq);
     4592            }
     4593            if (RT_SUCCESS(rc))
     4594                atapiCmdOK(pAhciPort, pAhciReq);
     4595            else
     4596                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED);
     4597            break;
     4598        }
     4599        case SCSI_MECHANISM_STATUS:
     4600        {
     4601            cbMax = ataBE2H_U16(pbPacket + 8);
     4602            atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MECHANISM_STATUS);
     4603            break;
     4604        }
     4605        case SCSI_READ_TOC_PMA_ATIP:
     4606        {
     4607            uint8_t format;
     4608
     4609            if (pAhciPort->cNotifiedMediaChange > 0)
     4610            {
     4611                pAhciPort->cNotifiedMediaChange-- ;
     4612                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     4613                break;
     4614            }
     4615            else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
     4616            {
     4617                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     4618                break;
     4619            }
     4620            cbMax = ataBE2H_U16(pbPacket + 7);
     4621            /* SCSI MMC-3 spec says format is at offset 2 (lower 4 bits),
     4622             * but Linux kernel uses offset 9 (topmost 2 bits). Hope that
     4623             * the other field is clear... */
     4624            format = (pbPacket[2] & 0xf) | (pbPacket[9] >> 6);
     4625            switch (format)
     4626            {
     4627                case 0:
     4628                    atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_NORMAL);
    44474629                    break;
    4448                 }
    4449                 if ((uint64_t)iATAPILBA + cSectors > pAhciPort->cTotalSectors)
    4450                 {
    4451                     /* Rate limited logging, one log line per second. For
    4452                      * guests that insist on reading from places outside the
    4453                      * valid area this often generates too many release log
    4454                      * entries otherwise. */
    4455                     static uint64_t s_uLastLogTS = 0;
    4456                     if (RTTimeMilliTS() >= s_uLastLogTS + 1000)
    4457                     {
    4458                         LogRel(("AHCI ATAPI: LUN#%d: CD-ROM block number %Ld invalid (READ)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA + cSectors));
    4459                         s_uLastLogTS = RTTimeMilliTS();
    4460                     }
    4461                     atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
     4630                case 1:
     4631                    atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_MULTI);
    44624632                    break;
    4463                 }
    4464                 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048);
    4465                 rc = AHCITXDIR_READ;
     4633                case 2:
     4634                    atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_RAW);
     4635                    break;
     4636                default:
     4637                  error_cmd:
     4638                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
     4639                    break;
    44664640            }
    44674641            break;
    4468         case SCSI_READ_CD:
    4469             {
    4470                 uint32_t cSectors, iATAPILBA;
    4471 
    4472                 if (pAhciPort->cNotifiedMediaChange > 0)
    4473                 {
    4474                     pAhciPort->cNotifiedMediaChange-- ;
    4475                     atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
    4476                     break;
    4477                 }
    4478                 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
    4479                 {
    4480                     atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
    4481                     break;
    4482                 }
    4483                 cSectors = (pbPacket[6] << 16) | (pbPacket[7] << 8) | pbPacket[8];
    4484                 iATAPILBA = ataBE2H_U32(pbPacket + 2);
    4485                 if (cSectors == 0)
    4486                 {
    4487                     atapiCmdOK(pAhciPort, pAhciReq);
    4488                     break;
    4489                 }
    4490                 if ((uint64_t)iATAPILBA + cSectors > pAhciPort->cTotalSectors)
    4491                 {
    4492                     /* Rate limited logging, one log line per second. For
    4493                      * guests that insist on reading from places outside the
    4494                      * valid area this often generates too many release log
    4495                      * entries otherwise. */
    4496                     static uint64_t s_uLastLogTS = 0;
    4497                     if (RTTimeMilliTS() >= s_uLastLogTS + 1000)
    4498                     {
    4499                         LogRel(("AHCI ATA: LUN#%d: CD-ROM block number %Ld invalid (READ CD)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA + cSectors));
    4500                         s_uLastLogTS = RTTimeMilliTS();
    4501                     }
    4502                     atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
    4503                     break;
    4504                 }
    4505                 switch (pbPacket[9] & 0xf8)
    4506                 {
    4507                     case 0x00:
    4508                         /* nothing */
    4509                         atapiCmdOK(pAhciPort, pAhciReq);
    4510                         break;
    4511                     case 0x10:
    4512                         /* normal read */
    4513                         atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048);
    4514                         rc = AHCITXDIR_READ;
    4515                         break;
    4516                     case 0xf8:
    4517                         /* read all data */
    4518                         atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2352);
    4519                         rc = AHCITXDIR_READ;
    4520                         break;
    4521                     default:
    4522                         LogRel(("AHCI ATAPI: LUN#%d: CD-ROM sector format not supported\n", pAhciPort->iLUN));
    4523                         atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
    4524                         break;
    4525                 }
    4526             }
    4527             break;
    4528         case SCSI_SEEK_10:
    4529             {
    4530                 uint32_t iATAPILBA;
    4531                 if (pAhciPort->cNotifiedMediaChange > 0)
    4532                 {
    4533                     pAhciPort->cNotifiedMediaChange-- ;
    4534                     atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
    4535                     break;
    4536                 }
    4537                 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
    4538                 {
    4539                     atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
    4540                     break;
    4541                 }
    4542                 iATAPILBA = ataBE2H_U32(pbPacket + 2);
    4543                 if (iATAPILBA > pAhciPort->cTotalSectors)
    4544                 {
    4545                     /* Rate limited logging, one log line per second. For
    4546                      * guests that insist on seeking to places outside the
    4547                      * valid area this often generates too many release log
    4548                      * entries otherwise. */
    4549                     static uint64_t s_uLastLogTS = 0;
    4550                     if (RTTimeMilliTS() >= s_uLastLogTS + 1000)
    4551                     {
    4552                         LogRel(("AHCI ATAPI: LUN#%d: CD-ROM block number %Ld invalid (SEEK)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA));
    4553                         s_uLastLogTS = RTTimeMilliTS();
    4554                     }
    4555                     atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
    4556                     break;
    4557                 }
    4558                 atapiCmdOK(pAhciPort, pAhciReq);
    4559                 pAhciReq->uATARegStatus |= ATA_STAT_SEEK; /* Linux expects this. */
    4560             }
    4561             break;
    4562         case SCSI_START_STOP_UNIT:
    4563             {
    4564                 int rc2 = VINF_SUCCESS;
    4565                 switch (pbPacket[4] & 3)
    4566                 {
    4567                     case 0: /* 00 - Stop motor */
    4568                     case 1: /* 01 - Start motor */
    4569                         break;
    4570                     case 2: /* 10 - Eject media */
    4571                     {
    4572                         /* This must be done from EMT. */
    4573                         PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
    4574                         PPDMDEVINS pDevIns = pAhci->CTX_SUFF(pDevIns);
    4575 
    4576                         rc2 = VMR3ReqPriorityCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
    4577                                                       (PFNRT)pAhciPort->pDrvMount->pfnUnmount, 3,
    4578                                                       pAhciPort->pDrvMount, false/*=fForce*/, true/*=fEject*/);
    4579                         Assert(RT_SUCCESS(rc2) || (rc2 == VERR_PDM_MEDIA_LOCKED) || (rc2 = VERR_PDM_MEDIA_NOT_MOUNTED));
    4580                         if (RT_SUCCESS(rc) && pAhci->pMediaNotify)
    4581                         {
    4582                             rc2 = VMR3ReqCallNoWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
    4583                                                     (PFNRT)pAhci->pMediaNotify->pfnEjected, 2,
    4584                                                     pAhci->pMediaNotify, pAhciPort->iLUN);
    4585                             AssertRC(rc);
    4586                         }
    4587                         break;
    4588                     }
    4589                     case 3: /* 11 - Load media */
    4590                         /** @todo rc = s->pDrvMount->pfnLoadMedia(s->pDrvMount) */
    4591                         break;
    4592                 }
    4593                 if (RT_SUCCESS(rc2))
    4594                     atapiCmdOK(pAhciPort, pAhciReq);
    4595                 else
    4596                     atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED);
    4597             }
    4598             break;
    4599         case SCSI_MECHANISM_STATUS:
    4600             {
    4601                 cbMax = ataBE2H_U16(pbPacket + 8);
    4602                 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MECHANISM_STATUS);
    4603             }
    4604             break;
    4605         case SCSI_READ_TOC_PMA_ATIP:
    4606             {
    4607                 uint8_t format;
    4608 
    4609                 if (pAhciPort->cNotifiedMediaChange > 0)
    4610                 {
    4611                     pAhciPort->cNotifiedMediaChange-- ;
    4612                     atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
    4613                     break;
    4614                 }
    4615                 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
    4616                 {
    4617                     atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
    4618                     break;
    4619                 }
    4620                 cbMax = ataBE2H_U16(pbPacket + 7);
    4621                 /* SCSI MMC-3 spec says format is at offset 2 (lower 4 bits),
    4622                  * but Linux kernel uses offset 9 (topmost 2 bits). Hope that
    4623                  * the other field is clear... */
    4624                 format = (pbPacket[2] & 0xf) | (pbPacket[9] >> 6);
    4625                 switch (format)
    4626                 {
    4627                     case 0:
    4628                         atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_NORMAL);
    4629                         break;
    4630                     case 1:
    4631                         atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_MULTI);
    4632                         break;
    4633                     case 2:
    4634                         atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_RAW);
    4635                         break;
    4636                     default:
    4637                     error_cmd:
    4638                         atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
    4639                         break;
    4640                 }
    4641             }
    4642             break;
     4642        }
    46434643        case SCSI_READ_CAPACITY:
    46444644            if (pAhciPort->cNotifiedMediaChange > 0)
     
    47034703    }
    47044704
    4705     return rc;
     4705    return enmTxDir;
    47064706}
    47074707
     
    60606060static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis)
    60616061{
    6062     AHCITXDIR rc = AHCITXDIR_NONE;
     6062    AHCITXDIR enmTxDir = AHCITXDIR_NONE;
    60636063    bool fLBA48 = false;
    60646064    CmdHdr   *pCmdHdr = &pAhciReq->cmdHdr;
     
    61106110                    break;
    61116111                case 0x82: /* write cache disable */
    6112                     rc = AHCITXDIR_FLUSH;
     6112                    enmTxDir = AHCITXDIR_FLUSH;
    61136113                    break;
    61146114                case 0x03:
    6115                 { /* set transfer mode */
     6115                {
     6116                    /* set transfer mode */
    61166117                    Log2(("%s: transfer mode %#04x\n", __FUNCTION__, pCmdFis[AHCI_CMDFIS_SECTC]));
    61176118                    switch (pCmdFis[AHCI_CMDFIS_SECTC] & 0xf8)
     
    61516152        case ATA_FLUSH_CACHE_EXT:
    61526153        case ATA_FLUSH_CACHE:
    6153             rc = AHCITXDIR_FLUSH;
     6154            enmTxDir = AHCITXDIR_FLUSH;
    61546155            break;
    61556156        case ATA_PACKET:
     
    61606161            }
    61616162            else
    6162                 rc = atapiParseCmd(pAhciPort, pAhciReq);
     6163                enmTxDir = atapiParseCmd(pAhciPort, pAhciReq);
    61636164            break;
    61646165        case ATA_IDENTIFY_PACKET_DEVICE:
     
    62156216            pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * pAhciPort->cbSector;
    62166217            pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * pAhciPort->cbSector;
    6217             rc = AHCITXDIR_READ;
     6218            enmTxDir = AHCITXDIR_READ;
    62186219            break;
    62196220        }
     
    62246225            pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * pAhciPort->cbSector;
    62256226            pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * pAhciPort->cbSector;
    6226             rc = AHCITXDIR_WRITE;
     6227            enmTxDir = AHCITXDIR_WRITE;
    62276228            break;
    62286229        }
     
    62326233            pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * pAhciPort->cbSector;
    62336234            pAhciReq->fFlags |= AHCI_REQ_IS_QUEUED;
    6234             rc = AHCITXDIR_READ;
     6235            enmTxDir = AHCITXDIR_READ;
    62356236            break;
    62366237        }
     
    62406241            pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * pAhciPort->cbSector;
    62416242            pAhciReq->fFlags |= AHCI_REQ_IS_QUEUED;
    6242             rc = AHCITXDIR_WRITE;
     6243            enmTxDir = AHCITXDIR_WRITE;
    62436244            break;
    62446245        }
     
    63216322                }
    63226323                else
    6323                     rc = AHCITXDIR_TRIM;
     6324                    enmTxDir = AHCITXDIR_TRIM;
    63246325                break;
    63256326            }
     
    63406341    }
    63416342
    6342     return rc;
     6343    return enmTxDir;
    63436344}
    63446345
  • trunk/src/VBox/Devices/Storage/DevATA.cpp

    r48744 r50282  
    18621862            break;
    18631863        case 2352:
     1864        {
     1865            uint8_t *pbBuf = s->CTX_SUFF(pbIOBuffer);
     1866
     1867            for (uint32_t i = s->iATAPILBA; i < s->iATAPILBA + cSectors; i++)
    18641868            {
    1865                 uint8_t *pbBuf = s->CTX_SUFF(pbIOBuffer);
    1866 
    1867                 for (uint32_t i = s->iATAPILBA; i < s->iATAPILBA + cSectors; i++)
    1868                 {
    1869                     /* Sync bytes, see 4.2.3.8 CD Main Channel Block Formats */
    1870                     *pbBuf++ = 0x00;
    1871                     memset(pbBuf, 0xff, 10);
    1872                     pbBuf += 10;
    1873                     *pbBuf++ = 0x00;
    1874                     /* MSF */
    1875                     ataLBA2MSF(pbBuf, i);
    1876                     pbBuf += 3;
    1877                     *pbBuf++ = 0x01; /* mode 1 data */
    1878                     /* data */
    1879                     rc = s->pDrvBlock->pfnRead(s->pDrvBlock, (uint64_t)i * 2048, pbBuf, 2048);
    1880                     if (RT_FAILURE(rc))
    1881                         break;
    1882                     pbBuf += 2048;
    1883                     /**
    1884                      * @todo: maybe compute ECC and parity, layout is:
    1885                      * 2072 4   EDC
    1886                      * 2076 172 P parity symbols
    1887                      * 2248 104 Q parity symbols
    1888                      */
    1889                     memset(pbBuf, 0, 280);
    1890                     pbBuf += 280;
    1891                 }
     1869                /* Sync bytes, see 4.2.3.8 CD Main Channel Block Formats */
     1870                *pbBuf++ = 0x00;
     1871                memset(pbBuf, 0xff, 10);
     1872                pbBuf += 10;
     1873                *pbBuf++ = 0x00;
     1874                /* MSF */
     1875                ataLBA2MSF(pbBuf, i);
     1876                pbBuf += 3;
     1877                *pbBuf++ = 0x01; /* mode 1 data */
     1878                /* data */
     1879                rc = s->pDrvBlock->pfnRead(s->pDrvBlock, (uint64_t)i * 2048, pbBuf, 2048);
     1880                if (RT_FAILURE(rc))
     1881                    break;
     1882                pbBuf += 2048;
     1883                /**
     1884                 * @todo: maybe compute ECC and parity, layout is:
     1885                 * 2072 4   EDC
     1886                 * 2076 172 P parity symbols
     1887                 * 2248 104 Q parity symbols
     1888                 */
     1889                memset(pbBuf, 0, 280);
     1890                pbBuf += 280;
    18921891            }
    18931892            break;
     1893        }
    18941894        default:
    18951895            break;
     
    22712271                {
    22722272                    case 0x0: /* Physical format information */
     2273                    {
     2274                        int layer = s->aATAPICmd[6];
     2275                        uint64_t total_sectors;
     2276
     2277                        if (layer != 0)
    22732278                        {
    2274                             int layer = s->aATAPICmd[6];
    2275                             uint64_t total_sectors;
    2276 
    2277                             if (layer != 0)
    2278                             {
    2279                                 uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET;
    2280                                 break;
    2281                             }
    2282 
    2283                             total_sectors = s->cTotalSectors;
    2284                             total_sectors >>= 2;
    2285                             if (total_sectors == 0)
    2286                             {
    2287                                 uASC = -SCSI_ASC_MEDIUM_NOT_PRESENT;
    2288                                 break;
    2289                             }
    2290 
    2291                             buf[4] = 1;   /* DVD-ROM, part version 1 */
    2292                             buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
    2293                             buf[6] = 1;   /* one layer, read-only (per MMC-2 spec) */
    2294                             buf[7] = 0;   /* default densities */
    2295 
    2296                             /* FIXME: 0x30000 per spec? */
    2297                             ataH2BE_U32(buf + 8, 0); /* start sector */
    2298                             ataH2BE_U32(buf + 12, total_sectors - 1); /* end sector */
    2299                             ataH2BE_U32(buf + 16, total_sectors - 1); /* l0 end sector */
    2300 
    2301                             /* Size of buffer, not including 2 byte size field */
    2302                             ataH2BE_U32(&buf[0], 2048 + 2);
    2303 
    2304                             /* 2k data + 4 byte header */
    2305                             uASC = (2048 + 4);
     2279                            uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET;
     2280                            break;
    23062281                        }
     2282
     2283                        total_sectors = s->cTotalSectors;
     2284                        total_sectors >>= 2;
     2285                        if (total_sectors == 0)
     2286                        {
     2287                            uASC = -SCSI_ASC_MEDIUM_NOT_PRESENT;
     2288                            break;
     2289                        }
     2290
     2291                        buf[4] = 1;   /* DVD-ROM, part version 1 */
     2292                        buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
     2293                        buf[6] = 1;   /* one layer, read-only (per MMC-2 spec) */
     2294                        buf[7] = 0;   /* default densities */
     2295
     2296                        /* FIXME: 0x30000 per spec? */
     2297                        ataH2BE_U32(buf + 8, 0); /* start sector */
     2298                        ataH2BE_U32(buf + 12, total_sectors - 1); /* end sector */
     2299                        ataH2BE_U32(buf + 16, total_sectors - 1); /* l0 end sector */
     2300
     2301                        /* Size of buffer, not including 2 byte size field */
     2302                        ataH2BE_U32(&buf[0], 2048 + 2);
     2303
     2304                        /* 2k data + 4 byte header */
     2305                        uASC = (2048 + 4);
    23072306                        break;
     2307                    }
    23082308                    case 0x01: /* DVD copyright information */
    23092309                        buf[4] = 0; /* no copyright data */
     
    30703070            break;
    30713071        case SCSI_MODE_SENSE_10:
     3072        {
     3073            uint8_t uPageControl, uPageCode;
     3074            cbMax = ataBE2H_U16(pbPacket + 7);
     3075            uPageControl = pbPacket[2] >> 6;
     3076            uPageCode = pbPacket[2] & 0x3f;
     3077            switch (uPageControl)
    30723078            {
    3073                 uint8_t uPageControl, uPageCode;
    3074                 cbMax = ataBE2H_U16(pbPacket + 7);
    3075                 uPageControl = pbPacket[2] >> 6;
    3076                 uPageCode = pbPacket[2] & 0x3f;
    3077                 switch (uPageControl)
    3078                 {
    3079                     case SCSI_PAGECONTROL_CURRENT:
    3080                         switch (uPageCode)
    3081                         {
    3082                             case SCSI_MODEPAGE_ERROR_RECOVERY:
    3083                                 ataStartTransfer(s, RT_MIN(cbMax, 16), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY, true);
    3084                                 break;
    3085                             case SCSI_MODEPAGE_CD_STATUS:
    3086                                 ataStartTransfer(s, RT_MIN(cbMax, 40), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS, true);
    3087                                 break;
    3088                             default:
    3089                                 goto error_cmd;
    3090                         }
    3091                         break;
    3092                     case SCSI_PAGECONTROL_CHANGEABLE:
    3093                         goto error_cmd;
    3094                     case SCSI_PAGECONTROL_DEFAULT:
    3095                         goto error_cmd;
    3096                     default:
    3097                     case SCSI_PAGECONTROL_SAVED:
    3098                         atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
    3099                         break;
    3100                 }
     3079                case SCSI_PAGECONTROL_CURRENT:
     3080                    switch (uPageCode)
     3081                    {
     3082                        case SCSI_MODEPAGE_ERROR_RECOVERY:
     3083                            ataStartTransfer(s, RT_MIN(cbMax, 16), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY, true);
     3084                            break;
     3085                        case SCSI_MODEPAGE_CD_STATUS:
     3086                            ataStartTransfer(s, RT_MIN(cbMax, 40), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS, true);
     3087                            break;
     3088                        default:
     3089                            goto error_cmd;
     3090                    }
     3091                    break;
     3092                case SCSI_PAGECONTROL_CHANGEABLE:
     3093                    goto error_cmd;
     3094                case SCSI_PAGECONTROL_DEFAULT:
     3095                    goto error_cmd;
     3096                default:
     3097                case SCSI_PAGECONTROL_SAVED:
     3098                    atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
     3099                    break;
    31013100            }
    31023101            break;
     3102        }
    31033103        case SCSI_REQUEST_SENSE:
    31043104            cbMax = pbPacket[4];
     
    31193119        case SCSI_READ_10:
    31203120        case SCSI_READ_12:
     3121        {
     3122            uint32_t cSectors, iATAPILBA;
     3123
     3124            if (s->cNotifiedMediaChange > 0)
    31213125            {
    3122                 uint32_t cSectors, iATAPILBA;
    3123 
    3124                 if (s->cNotifiedMediaChange > 0)
     3126                s->cNotifiedMediaChange-- ;
     3127                atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     3128                break;
     3129            }
     3130            else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
     3131            {
     3132                atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     3133                break;
     3134            }
     3135            if (pbPacket[0] == SCSI_READ_10)
     3136                cSectors = ataBE2H_U16(pbPacket + 7);
     3137            else
     3138                cSectors = ataBE2H_U32(pbPacket + 6);
     3139            iATAPILBA = ataBE2H_U32(pbPacket + 2);
     3140            if (cSectors == 0)
     3141            {
     3142                atapiCmdOK(s);
     3143                break;
     3144            }
     3145            if ((uint64_t)iATAPILBA + cSectors > s->cTotalSectors)
     3146            {
     3147                /* Rate limited logging, one log line per second. For
     3148                 * guests that insist on reading from places outside the
     3149                 * valid area this often generates too many release log
     3150                 * entries otherwise. */
     3151                static uint64_t uLastLogTS = 0;
     3152                if (RTTimeMilliTS() >= uLastLogTS + 1000)
    31253153                {
    3126                     s->cNotifiedMediaChange-- ;
    3127                     atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     3154                    LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (READ)\n", s->iLUN, (uint64_t)iATAPILBA + cSectors));
     3155                    uLastLogTS = RTTimeMilliTS();
     3156                }
     3157                atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
     3158                break;
     3159            }
     3160            atapiReadSectors(s, iATAPILBA, cSectors, 2048);
     3161            break;
     3162        }
     3163        case SCSI_READ_CD:
     3164        {
     3165            uint32_t cSectors, iATAPILBA;
     3166
     3167            if (s->cNotifiedMediaChange > 0)
     3168            {
     3169                s->cNotifiedMediaChange-- ;
     3170                atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     3171                break;
     3172            }
     3173            else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
     3174            {
     3175                atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     3176                break;
     3177            }
     3178            cSectors = (pbPacket[6] << 16) | (pbPacket[7] << 8) | pbPacket[8];
     3179            iATAPILBA = ataBE2H_U32(pbPacket + 2);
     3180            if (cSectors == 0)
     3181            {
     3182                atapiCmdOK(s);
     3183                break;
     3184            }
     3185            if ((uint64_t)iATAPILBA + cSectors > s->cTotalSectors)
     3186            {
     3187                /* Rate limited logging, one log line per second. For
     3188                 * guests that insist on reading from places outside the
     3189                 * valid area this often generates too many release log
     3190                 * entries otherwise. */
     3191                static uint64_t uLastLogTS = 0;
     3192                if (RTTimeMilliTS() >= uLastLogTS + 1000)
     3193                {
     3194                    LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (READ CD)\n", s->iLUN, (uint64_t)iATAPILBA + cSectors));
     3195                    uLastLogTS = RTTimeMilliTS();
     3196                }
     3197                atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
     3198                break;
     3199            }
     3200            switch (pbPacket[9] & 0xf8)
     3201            {
     3202                case 0x00:
     3203                    /* nothing */
     3204                    atapiCmdOK(s);
     3205                    break;
     3206                case 0x10:
     3207                    /* normal read */
     3208                    atapiReadSectors(s, iATAPILBA, cSectors, 2048);
     3209                    break;
     3210                case 0xf8:
     3211                    /* read all data */
     3212                    atapiReadSectors(s, iATAPILBA, cSectors, 2352);
     3213                    break;
     3214                default:
     3215                    LogRel(("PIIX3 ATA: LUN#%d: CD-ROM sector format not supported (%#x)\n", s->iLUN, pbPacket[9] & 0xf8));
     3216                    atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
     3217                    break;
     3218            }
     3219            break;
     3220        }
     3221        case SCSI_SEEK_10:
     3222        {
     3223            uint32_t iATAPILBA;
     3224            if (s->cNotifiedMediaChange > 0)
     3225            {
     3226                s->cNotifiedMediaChange-- ;
     3227                atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     3228                break;
     3229            }
     3230            else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
     3231            {
     3232                atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     3233                break;
     3234            }
     3235            iATAPILBA = ataBE2H_U32(pbPacket + 2);
     3236            if (iATAPILBA > s->cTotalSectors)
     3237            {
     3238                /* Rate limited logging, one log line per second. For
     3239                 * guests that insist on seeking to places outside the
     3240                 * valid area this often generates too many release log
     3241                 * entries otherwise. */
     3242                static uint64_t uLastLogTS = 0;
     3243                if (RTTimeMilliTS() >= uLastLogTS + 1000)
     3244                {
     3245                    LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (SEEK)\n", s->iLUN, (uint64_t)iATAPILBA));
     3246                    uLastLogTS = RTTimeMilliTS();
     3247                }
     3248                atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
     3249                break;
     3250            }
     3251            atapiCmdOK(s);
     3252            ataSetStatus(s, ATA_STAT_SEEK); /* Linux expects this. */
     3253            break;
     3254        }
     3255        case SCSI_START_STOP_UNIT:
     3256        {
     3257            int rc = VINF_SUCCESS;
     3258            switch (pbPacket[4] & 3)
     3259            {
     3260                case 0: /* 00 - Stop motor */
     3261                case 1: /* 01 - Start motor */
     3262                    break;
     3263                case 2: /* 10 - Eject media */
     3264                {
     3265                    /* This must be done from EMT. */
     3266                    PATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
     3267                    PPDMDEVINS pDevIns = ATADEVSTATE_2_DEVINS(s);
     3268                    PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *);
     3269
     3270                    PDMCritSectLeave(&pCtl->lock);
     3271                    rc = VMR3ReqPriorityCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
     3272                                                 (PFNRT)s->pDrvMount->pfnUnmount, 3,
     3273                                                 s->pDrvMount, false /*=fForce*/, true /*=fEject*/);
     3274                    Assert(RT_SUCCESS(rc) || rc == VERR_PDM_MEDIA_LOCKED || rc = VERR_PDM_MEDIA_NOT_MOUNTED);
     3275                    if (RT_SUCCESS(rc) && pThis->pMediaNotify)
     3276                    {
     3277                        rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
     3278                                               (PFNRT)pThis->pMediaNotify->pfnEjected, 2,
     3279                                               pThis->pMediaNotify, s->iLUN);
     3280                        AssertRC(rc);
     3281                    }
     3282                    {
     3283                        STAM_PROFILE_START(&pCtl->StatLockWait, a);
     3284                        PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
     3285                        STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
     3286                    }
    31283287                    break;
    31293288                }
    3130                 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
    3131                 {
    3132                     atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     3289                case 3: /* 11 - Load media */
     3290                    /** @todo rc = s->pDrvMount->pfnLoadMedia(s->pDrvMount) */
    31333291                    break;
    3134                 }
    3135                 if (pbPacket[0] == SCSI_READ_10)
    3136                     cSectors = ataBE2H_U16(pbPacket + 7);
    3137                 else
    3138                     cSectors = ataBE2H_U32(pbPacket + 6);
    3139                 iATAPILBA = ataBE2H_U32(pbPacket + 2);
    3140                 if (cSectors == 0)
    3141                 {
    3142                     atapiCmdOK(s);
     3292            }
     3293            if (RT_SUCCESS(rc))
     3294                atapiCmdOK(s);
     3295            else
     3296                atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED);
     3297            break;
     3298        }
     3299        case SCSI_MECHANISM_STATUS:
     3300        {
     3301            cbMax = ataBE2H_U16(pbPacket + 8);
     3302            ataStartTransfer(s, RT_MIN(cbMax, 8), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MECHANISM_STATUS, true);
     3303            break;
     3304        }
     3305        case SCSI_READ_TOC_PMA_ATIP:
     3306        {
     3307            uint8_t format;
     3308
     3309            if (s->cNotifiedMediaChange > 0)
     3310            {
     3311                s->cNotifiedMediaChange-- ;
     3312                atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     3313                break;
     3314            }
     3315            else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
     3316            {
     3317                atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     3318                break;
     3319            }
     3320            cbMax = ataBE2H_U16(pbPacket + 7);
     3321            /* SCSI MMC-3 spec says format is at offset 2 (lower 4 bits),
     3322             * but Linux kernel uses offset 9 (topmost 2 bits). Hope that
     3323             * the other field is clear... */
     3324            format = (pbPacket[2] & 0xf) | (pbPacket[9] >> 6);
     3325            switch (format)
     3326            {
     3327                case 0:
     3328                    ataStartTransfer(s, cbMax, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_NORMAL, true);
    31433329                    break;
    3144                 }
    3145                 if ((uint64_t)iATAPILBA + cSectors > s->cTotalSectors)
    3146                 {
    3147                     /* Rate limited logging, one log line per second. For
    3148                      * guests that insist on reading from places outside the
    3149                      * valid area this often generates too many release log
    3150                      * entries otherwise. */
    3151                     static uint64_t uLastLogTS = 0;
    3152                     if (RTTimeMilliTS() >= uLastLogTS + 1000)
    3153                     {
    3154                         LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (READ)\n", s->iLUN, (uint64_t)iATAPILBA + cSectors));
    3155                         uLastLogTS = RTTimeMilliTS();
    3156                     }
    3157                     atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
     3330                case 1:
     3331                    ataStartTransfer(s, RT_MIN(cbMax, 12), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_MULTI, true);
    31583332                    break;
    3159                 }
    3160                 atapiReadSectors(s, iATAPILBA, cSectors, 2048);
     3333                case 2:
     3334                    ataStartTransfer(s, cbMax, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_RAW, true);
     3335                    break;
     3336                default:
     3337                  error_cmd:
     3338                    atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
     3339                    break;
    31613340            }
    31623341            break;
    3163         case SCSI_READ_CD:
    3164             {
    3165                 uint32_t cSectors, iATAPILBA;
    3166 
    3167                 if (s->cNotifiedMediaChange > 0)
    3168                 {
    3169                     s->cNotifiedMediaChange-- ;
    3170                     atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
    3171                     break;
    3172                 }
    3173                 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
    3174                 {
    3175                     atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
    3176                     break;
    3177                 }
    3178                 cSectors = (pbPacket[6] << 16) | (pbPacket[7] << 8) | pbPacket[8];
    3179                 iATAPILBA = ataBE2H_U32(pbPacket + 2);
    3180                 if (cSectors == 0)
    3181                 {
    3182                     atapiCmdOK(s);
    3183                     break;
    3184                 }
    3185                 if ((uint64_t)iATAPILBA + cSectors > s->cTotalSectors)
    3186                 {
    3187                     /* Rate limited logging, one log line per second. For
    3188                      * guests that insist on reading from places outside the
    3189                      * valid area this often generates too many release log
    3190                      * entries otherwise. */
    3191                     static uint64_t uLastLogTS = 0;
    3192                     if (RTTimeMilliTS() >= uLastLogTS + 1000)
    3193                     {
    3194                         LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (READ CD)\n", s->iLUN, (uint64_t)iATAPILBA + cSectors));
    3195                         uLastLogTS = RTTimeMilliTS();
    3196                     }
    3197                     atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
    3198                     break;
    3199                 }
    3200                 switch (pbPacket[9] & 0xf8)
    3201                 {
    3202                     case 0x00:
    3203                         /* nothing */
    3204                         atapiCmdOK(s);
    3205                         break;
    3206                     case 0x10:
    3207                         /* normal read */
    3208                         atapiReadSectors(s, iATAPILBA, cSectors, 2048);
    3209                         break;
    3210                     case 0xf8:
    3211                         /* read all data */
    3212                         atapiReadSectors(s, iATAPILBA, cSectors, 2352);
    3213                         break;
    3214                     default:
    3215                         LogRel(("PIIX3 ATA: LUN#%d: CD-ROM sector format not supported (%#x)\n", s->iLUN, pbPacket[9] & 0xf8));
    3216                         atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
    3217                         break;
    3218                 }
    3219             }
    3220             break;
    3221         case SCSI_SEEK_10:
    3222             {
    3223                 uint32_t iATAPILBA;
    3224                 if (s->cNotifiedMediaChange > 0)
    3225                 {
    3226                     s->cNotifiedMediaChange-- ;
    3227                     atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
    3228                     break;
    3229                 }
    3230                 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
    3231                 {
    3232                     atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
    3233                     break;
    3234                 }
    3235                 iATAPILBA = ataBE2H_U32(pbPacket + 2);
    3236                 if (iATAPILBA > s->cTotalSectors)
    3237                 {
    3238                     /* Rate limited logging, one log line per second. For
    3239                      * guests that insist on seeking to places outside the
    3240                      * valid area this often generates too many release log
    3241                      * entries otherwise. */
    3242                     static uint64_t uLastLogTS = 0;
    3243                     if (RTTimeMilliTS() >= uLastLogTS + 1000)
    3244                     {
    3245                         LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (SEEK)\n", s->iLUN, (uint64_t)iATAPILBA));
    3246                         uLastLogTS = RTTimeMilliTS();
    3247                     }
    3248                     atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
    3249                     break;
    3250                 }
    3251                 atapiCmdOK(s);
    3252                 ataSetStatus(s, ATA_STAT_SEEK); /* Linux expects this. */
    3253             }
    3254             break;
    3255         case SCSI_START_STOP_UNIT:
    3256             {
    3257                 int rc = VINF_SUCCESS;
    3258                 switch (pbPacket[4] & 3)
    3259                 {
    3260                     case 0: /* 00 - Stop motor */
    3261                     case 1: /* 01 - Start motor */
    3262                         break;
    3263                     case 2: /* 10 - Eject media */
    3264                     {
    3265                         /* This must be done from EMT. */
    3266                         PATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
    3267                         PPDMDEVINS pDevIns = ATADEVSTATE_2_DEVINS(s);
    3268                         PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *);
    3269 
    3270                         PDMCritSectLeave(&pCtl->lock);
    3271                         rc = VMR3ReqPriorityCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
    3272                                                      (PFNRT)s->pDrvMount->pfnUnmount, 3,
    3273                                                      s->pDrvMount, false /*=fForce*/, true /*=fEject*/);
    3274                         Assert(RT_SUCCESS(rc) || (rc == VERR_PDM_MEDIA_LOCKED) || (rc = VERR_PDM_MEDIA_NOT_MOUNTED));
    3275                         if (RT_SUCCESS(rc) && pThis->pMediaNotify)
    3276                         {
    3277                             rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
    3278                                                    (PFNRT)pThis->pMediaNotify->pfnEjected, 2,
    3279                                                    pThis->pMediaNotify, s->iLUN);
    3280                             AssertRC(rc);
    3281                         }
    3282                         {
    3283                             STAM_PROFILE_START(&pCtl->StatLockWait, a);
    3284                             PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
    3285                             STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
    3286                         }
    3287                         break;
    3288                     }
    3289                     case 3: /* 11 - Load media */
    3290                         /** @todo rc = s->pDrvMount->pfnLoadMedia(s->pDrvMount) */
    3291                         break;
    3292                 }
    3293                 if (RT_SUCCESS(rc))
    3294                     atapiCmdOK(s);
    3295                 else
    3296                     atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED);
    3297             }
    3298             break;
    3299         case SCSI_MECHANISM_STATUS:
    3300             {
    3301                 cbMax = ataBE2H_U16(pbPacket + 8);
    3302                 ataStartTransfer(s, RT_MIN(cbMax, 8), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MECHANISM_STATUS, true);
    3303             }
    3304             break;
    3305         case SCSI_READ_TOC_PMA_ATIP:
    3306             {
    3307                 uint8_t format;
    3308 
    3309                 if (s->cNotifiedMediaChange > 0)
    3310                 {
    3311                     s->cNotifiedMediaChange-- ;
    3312                     atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
    3313                     break;
    3314                 }
    3315                 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
    3316                 {
    3317                     atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
    3318                     break;
    3319                 }
    3320                 cbMax = ataBE2H_U16(pbPacket + 7);
    3321                 /* SCSI MMC-3 spec says format is at offset 2 (lower 4 bits),
    3322                  * but Linux kernel uses offset 9 (topmost 2 bits). Hope that
    3323                  * the other field is clear... */
    3324                 format = (pbPacket[2] & 0xf) | (pbPacket[9] >> 6);
    3325                 switch (format)
    3326                 {
    3327                     case 0:
    3328                         ataStartTransfer(s, cbMax, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_NORMAL, true);
    3329                         break;
    3330                     case 1:
    3331                         ataStartTransfer(s, RT_MIN(cbMax, 12), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_MULTI, true);
    3332                         break;
    3333                     case 2:
    3334                         ataStartTransfer(s, cbMax, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_RAW, true);
    3335                         break;
    3336                     default:
    3337                     error_cmd:
    3338                         atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
    3339                         break;
    3340                 }
    3341             }
    3342             break;
     3342        }
    33433343        case SCSI_READ_CAPACITY:
    33443344            if (s->cNotifiedMediaChange > 0)
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette