VirtualBox

儲存庫 vbox 的更動 65966


忽略:
時間撮記:
2017-3-7 上午10:47:19 (8 年 以前)
作者:
vboxsync
訊息:

Devices/Storage/DevATA: Get rid of most of the parsing code in atapiR3ParseCmdPassthrough() and replace with the common CDB parsing function in the common ATAPI passthrough code, removes a lot of nasty goto statements.

檔案:
修改 1 筆資料

圖例:

未更動
新增
刪除
  • trunk/src/VBox/Devices/Storage/DevATA.cpp

    r65960 r65966  
    33973397static void atapiR3ParseCmdPassthrough(ATADevState *s)
    33983398{
    3399     const uint8_t *pbPacket;
    3400     uint8_t *pbBuf;
    3401     uint32_t cSectors, iATAPILBA;
    3402     uint32_t cbTransfer = 0;
     3399    const uint8_t *pbPacket = &s->aATAPICmd[0];
     3400    size_t cbTransfer = 0;
    34033401    PDMMEDIATXDIR uTxDir = PDMMEDIATXDIR_NONE;
    3404 
    3405     pbPacket = s->aATAPICmd;
    3406     pbBuf = s->CTX_SUFF(pbIOBuffer);
    3407     switch (pbPacket[0])
    3408     {
    3409         case SCSI_BLANK:
    3410             goto sendcmd;
    3411         case SCSI_CLOSE_TRACK_SESSION:
    3412             goto sendcmd;
    3413         case SCSI_ERASE_10:
    3414             iATAPILBA = scsiBE2H_U32(pbPacket + 2);
    3415             cbTransfer = scsiBE2H_U16(pbPacket + 7);
    3416             Log2(("ATAPI PT: lba %d\n", iATAPILBA));
    3417             uTxDir = PDMMEDIATXDIR_TO_DEVICE;
    3418             goto sendcmd;
    3419         case SCSI_FORMAT_UNIT:
    3420             cbTransfer = s->uATARegLCyl | (s->uATARegHCyl << 8); /* use ATAPI transfer length */
    3421             uTxDir = PDMMEDIATXDIR_TO_DEVICE;
    3422             goto sendcmd;
    3423         case SCSI_GET_CONFIGURATION:
    3424             cbTransfer = scsiBE2H_U16(pbPacket + 7);
    3425             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3426             goto sendcmd;
    3427         case SCSI_GET_EVENT_STATUS_NOTIFICATION:
    3428             cbTransfer = scsiBE2H_U16(pbPacket + 7);
    3429             if (ASMAtomicReadU32(&s->MediaEventStatus) != ATA_EVENT_STATUS_UNCHANGED)
    3430             {
    3431                 ataR3StartTransfer(s, RT_MIN(cbTransfer, 8), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION, true);
    3432                 break;
    3433             }
    3434             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3435             goto sendcmd;
    3436         case SCSI_GET_PERFORMANCE:
    3437             cbTransfer = s->uATARegLCyl | (s->uATARegHCyl << 8); /* use ATAPI transfer length */
    3438             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3439             goto sendcmd;
    3440         case SCSI_INQUIRY:
    3441             cbTransfer = scsiBE2H_U16(pbPacket + 3);
    3442             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3443             goto sendcmd;
    3444         case SCSI_LOAD_UNLOAD_MEDIUM:
    3445             goto sendcmd;
    3446         case SCSI_MECHANISM_STATUS:
    3447             cbTransfer = scsiBE2H_U16(pbPacket + 8);
    3448             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3449             goto sendcmd;
    3450         case SCSI_MODE_SELECT_10:
    3451             cbTransfer = scsiBE2H_U16(pbPacket + 7);
    3452             uTxDir = PDMMEDIATXDIR_TO_DEVICE;
    3453             goto sendcmd;
    3454         case SCSI_MODE_SENSE_10:
    3455             cbTransfer = scsiBE2H_U16(pbPacket + 7);
    3456             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3457             goto sendcmd;
    3458         case SCSI_PAUSE_RESUME:
    3459             goto sendcmd;
    3460         case SCSI_PLAY_AUDIO_10:
    3461             goto sendcmd;
    3462         case SCSI_PLAY_AUDIO_12:
    3463             goto sendcmd;
    3464         case SCSI_PLAY_AUDIO_MSF:
    3465             goto sendcmd;
    3466         case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL:
    3467             /** @todo do not forget to unlock when a VM is shut down */
    3468             goto sendcmd;
    3469         case SCSI_READ_10:
    3470             iATAPILBA = scsiBE2H_U32(pbPacket + 2);
    3471             cSectors = scsiBE2H_U16(pbPacket + 7);
    3472             Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors));
    3473             s->cbATAPISector = 2048;
    3474             cbTransfer = cSectors * s->cbATAPISector;
    3475             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3476             goto sendcmd;
    3477         case SCSI_READ_12:
    3478             iATAPILBA = scsiBE2H_U32(pbPacket + 2);
    3479             cSectors = scsiBE2H_U32(pbPacket + 6);
    3480             Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors));
    3481             s->cbATAPISector = 2048;
    3482             cbTransfer = cSectors * s->cbATAPISector;
    3483             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3484             goto sendcmd;
    3485         case SCSI_READ_BUFFER:
    3486             cbTransfer = scsiBE2H_U24(pbPacket + 6);
    3487             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3488             goto sendcmd;
    3489         case SCSI_READ_BUFFER_CAPACITY:
    3490             cbTransfer = scsiBE2H_U16(pbPacket + 7);
    3491             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3492             goto sendcmd;
    3493         case SCSI_READ_CAPACITY:
    3494             cbTransfer = 8;
    3495             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3496             goto sendcmd;
    3497         case SCSI_READ_CD:
    3498         case SCSI_READ_CD_MSF:
    3499         {
    3500             /* Get sector size based on the expected sector type field. */
    3501             switch ((pbPacket[1] >> 2) & 0x7)
    3502             {
    3503                 case 0x0: /* All types. */
    3504                 {
    3505                     uint32_t iLbaStart;
    3506 
    3507                     if (pbPacket[0] == SCSI_READ_CD)
    3508                         iLbaStart = scsiBE2H_U32(&pbPacket[2]);
    3509                     else
    3510                         iLbaStart = scsiMSF2LBA(&pbPacket[3]);
    3511 
    3512                     if (s->pTrackList)
    3513                         s->cbATAPISector = ATAPIPassthroughTrackListGetSectorSizeFromLba(s->pTrackList, iLbaStart);
    3514                     else
    3515                         s->cbATAPISector = 2048; /* Might be incorrect if we couldn't determine the type. */
    3516                     break;
    3517                 }
    3518                 case 0x1: /* CD-DA */
    3519                     s->cbATAPISector = 2352;
    3520                     break;
    3521                 case 0x2: /* Mode 1 */
    3522                     s->cbATAPISector = 2048;
    3523                     break;
    3524                 case 0x3: /* Mode 2 formless */
    3525                     s->cbATAPISector = 2336;
    3526                     break;
    3527                 case 0x4: /* Mode 2 form 1 */
    3528                     s->cbATAPISector = 2048;
    3529                     break;
    3530                 case 0x5: /* Mode 2 form 2 */
    3531                     s->cbATAPISector = 2324;
    3532                     break;
    3533                 default: /* Reserved */
    3534                     AssertMsgFailed(("Unknown sector type\n"));
    3535                     s->cbATAPISector = 0; /** @todo we should probably fail the command here already. */
    3536             }
    3537 
    3538             if (pbPacket[0] == SCSI_READ_CD)
    3539                 cbTransfer = scsiBE2H_U24(pbPacket + 6) * s->cbATAPISector;
    3540             else /* SCSI_READ_MSF */
    3541             {
    3542                 cSectors = scsiMSF2LBA(pbPacket + 6) - scsiMSF2LBA(pbPacket + 3);
    3543                 if (cSectors > 32)
    3544                     cSectors = 32; /* Limit transfer size to 64~74K. Safety first. In any case this can only harm software doing CDDA extraction. */
    3545                 cbTransfer = cSectors * s->cbATAPISector;
    3546             }
    3547             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3548             goto sendcmd;
    3549         }
    3550         case SCSI_READ_DISC_INFORMATION:
    3551             cbTransfer = scsiBE2H_U16(pbPacket + 7);
    3552             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3553             goto sendcmd;
    3554         case SCSI_READ_DVD_STRUCTURE:
    3555             cbTransfer = scsiBE2H_U16(pbPacket + 8);
    3556             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3557             goto sendcmd;
    3558         case SCSI_READ_FORMAT_CAPACITIES:
    3559             cbTransfer = scsiBE2H_U16(pbPacket + 7);
    3560             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3561             goto sendcmd;
    3562         case SCSI_READ_SUBCHANNEL:
    3563             cbTransfer = scsiBE2H_U16(pbPacket + 7);
    3564             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3565             goto sendcmd;
    3566         case SCSI_READ_TOC_PMA_ATIP:
    3567             cbTransfer = scsiBE2H_U16(pbPacket + 7);
    3568             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3569             goto sendcmd;
    3570         case SCSI_READ_TRACK_INFORMATION:
    3571             cbTransfer = scsiBE2H_U16(pbPacket + 7);
    3572             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3573             goto sendcmd;
    3574         case SCSI_REPAIR_TRACK:
    3575             goto sendcmd;
    3576         case SCSI_REPORT_KEY:
    3577             cbTransfer = scsiBE2H_U16(pbPacket + 8);
    3578             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3579             goto sendcmd;
    3580         case SCSI_REQUEST_SENSE:
    3581             cbTransfer = pbPacket[4];
    3582             if ((s->abATAPISense[2] & 0x0f) != SCSI_SENSE_NONE)
    3583             {
    3584                 ataR3StartTransfer(s, RT_MIN(cbTransfer, 18), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_REQUEST_SENSE, true);
    3585                 break;
    3586             }
    3587             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3588             goto sendcmd;
    3589         case SCSI_RESERVE_TRACK:
    3590             goto sendcmd;
    3591         case SCSI_SCAN:
    3592             goto sendcmd;
    3593         case SCSI_SEEK_10:
    3594             goto sendcmd;
    3595         case SCSI_SEND_CUE_SHEET:
    3596             cbTransfer = scsiBE2H_U24(pbPacket + 6);
    3597             uTxDir = PDMMEDIATXDIR_TO_DEVICE;
    3598             goto sendcmd;
    3599         case SCSI_SEND_DVD_STRUCTURE:
    3600             cbTransfer = scsiBE2H_U16(pbPacket + 8);
    3601             uTxDir = PDMMEDIATXDIR_TO_DEVICE;
    3602             goto sendcmd;
    3603         case SCSI_SEND_EVENT:
    3604             cbTransfer = scsiBE2H_U16(pbPacket + 8);
    3605             uTxDir = PDMMEDIATXDIR_TO_DEVICE;
    3606             goto sendcmd;
    3607         case SCSI_SEND_KEY:
    3608             cbTransfer = scsiBE2H_U16(pbPacket + 8);
    3609             uTxDir = PDMMEDIATXDIR_TO_DEVICE;
    3610             goto sendcmd;
    3611         case SCSI_SEND_OPC_INFORMATION:
    3612             cbTransfer = scsiBE2H_U16(pbPacket + 7);
    3613             uTxDir = PDMMEDIATXDIR_TO_DEVICE;
    3614             goto sendcmd;
    3615         case SCSI_SET_CD_SPEED:
    3616             goto sendcmd;
    3617         case SCSI_SET_READ_AHEAD:
    3618             goto sendcmd;
    3619         case SCSI_SET_STREAMING:
    3620             cbTransfer = scsiBE2H_U16(pbPacket + 9);
    3621             uTxDir = PDMMEDIATXDIR_TO_DEVICE;
    3622             goto sendcmd;
    3623         case SCSI_START_STOP_UNIT:
    3624             goto sendcmd;
    3625         case SCSI_STOP_PLAY_SCAN:
    3626             goto sendcmd;
    3627         case SCSI_SYNCHRONIZE_CACHE:
    3628             goto sendcmd;
    3629         case SCSI_TEST_UNIT_READY:
    3630             goto sendcmd;
    3631         case SCSI_VERIFY_10:
    3632             goto sendcmd;
    3633         case SCSI_WRITE_10:
    3634         case SCSI_WRITE_AND_VERIFY_10:
    3635             iATAPILBA = scsiBE2H_U32(pbPacket + 2);
    3636             cSectors = scsiBE2H_U16(pbPacket + 7);
    3637             if (s->pTrackList)
    3638                 s->cbATAPISector = ATAPIPassthroughTrackListGetSectorSizeFromLba(s->pTrackList, iATAPILBA);
    3639             else
    3640                 s->cbATAPISector = 2048;
    3641             Log2(("ATAPI PT: lba %d sectors %d sector size %d\n", iATAPILBA, cSectors, s->cbATAPISector));
    3642             cbTransfer = cSectors * s->cbATAPISector;
    3643             uTxDir = PDMMEDIATXDIR_TO_DEVICE;
    3644             goto sendcmd;
    3645         case SCSI_WRITE_12:
    3646             iATAPILBA = scsiBE2H_U32(pbPacket + 2);
    3647             cSectors = scsiBE2H_U32(pbPacket + 6);
    3648             if (s->pTrackList)
    3649                 s->cbATAPISector = ATAPIPassthroughTrackListGetSectorSizeFromLba(s->pTrackList, iATAPILBA);
    3650             else
    3651                 s->cbATAPISector = 2048;
    3652             Log2(("ATAPI PT: lba %d sectors %d sector size %d\n", iATAPILBA, cSectors, s->cbATAPISector));
    3653             cbTransfer = cSectors * s->cbATAPISector;
    3654             uTxDir = PDMMEDIATXDIR_TO_DEVICE;
    3655             goto sendcmd;
    3656         case SCSI_WRITE_BUFFER:
    3657             switch (pbPacket[1] & 0x1f)
    3658             {
    3659                 case 0x04: /* download microcode */
    3660                 case 0x05: /* download microcode and save */
    3661                 case 0x06: /* download microcode with offsets */
    3662                 case 0x07: /* download microcode with offsets and save */
    3663                 case 0x0e: /* download microcode with offsets and defer activation */
    3664                 case 0x0f: /* activate deferred microcode */
    3665                     LogRel(("PIIX3 ATA: LUN#%d: CD-ROM passthrough command attempted to update firmware, blocked\n", s->iLUN));
    3666                     atapiR3CmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
    3667                     break;
    3668                 default:
    3669                     cbTransfer = scsiBE2H_U16(pbPacket + 6);
    3670                     uTxDir = PDMMEDIATXDIR_TO_DEVICE;
    3671                     goto sendcmd;
    3672             }
    3673             break;
    3674         case SCSI_REPORT_LUNS: /* Not part of MMC-3, but used by Windows. */
    3675             cbTransfer = scsiBE2H_U32(pbPacket + 6);
    3676             uTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    3677             goto sendcmd;
    3678         case SCSI_REZERO_UNIT:
    3679             /* Obsolete command used by cdrecord. What else would one expect?
    3680              * This command is not sent to the drive, it is handled internally,
    3681              * as the Linux kernel doesn't like it (message "scsi: unknown
    3682              * opcode 0x01" in syslog) and replies with a sense code of 0,
    3683              * which sends cdrecord to an endless loop. */
    3684             atapiR3CmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
    3685             break;
    3686         default:
    3687             LogRel(("PIIX3 ATA: LUN#%d: passthrough unimplemented for command %#x\n", s->iLUN, pbPacket[0]));
    3688             atapiR3CmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
    3689             break;
    3690         sendcmd:
     3402    uint8_t u8ScsiSts = SCSI_STATUS_OK;
     3403
     3404    /* Some cases we have to handle here. */
     3405    if (   pbPacket[0] == SCSI_GET_EVENT_STATUS_NOTIFICATION
     3406        && ASMAtomicReadU32(&s->MediaEventStatus) != ATA_EVENT_STATUS_UNCHANGED)
     3407    {
     3408        cbTransfer = scsiBE2H_U16(pbPacket + 7);
     3409        ataR3StartTransfer(s, RT_MIN(cbTransfer, 8), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION, true);
     3410    }
     3411    else if (   pbPacket[0] == SCSI_REQUEST_SENSE
     3412             && (s->abATAPISense[2] & 0x0f) != SCSI_SENSE_NONE)
     3413        ataR3StartTransfer(s, RT_MIN(pbPacket[4], 18), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_REQUEST_SENSE, true);
     3414    else
     3415    {
     3416        size_t cbBuf = 0;
     3417        size_t cbATAPISector = 0;
     3418        if (pbPacket[0] == SCSI_FORMAT_UNIT || pbPacket[0] == SCSI_GET_PERFORMANCE)
     3419            cbBuf = s->uATARegLCyl | (s->uATARegHCyl << 8); /* use ATAPI transfer length */
     3420
     3421        bool fPassthrough = ATAPIPassthroughParseCdb(pbPacket, sizeof(s->aATAPICmd), cbBuf, s->pTrackList,
     3422                                                     &s->abATAPISense[0], sizeof(s->abATAPISense), &uTxDir, &cbTransfer,
     3423                                                     &cbATAPISector, &u8ScsiSts);
     3424        if (fPassthrough)
     3425        {
     3426            s->cbATAPISector = (uint32_t)cbATAPISector;
     3427            Assert(s->cbATAPISector == (uint32_t)cbATAPISector);
     3428
    36913429            /*
    36923430             * Send a command to the drive, passing data in/out as required.
     
    36983436                uTxDir = PDMMEDIATXDIR_NONE;
    36993437            ataR3StartTransfer(s, cbTransfer, uTxDir, ATAFN_BT_ATAPI_PASSTHROUGH_CMD, ATAFN_SS_ATAPI_PASSTHROUGH, true);
     3438        }
     3439        else if (u8ScsiSts == SCSI_STATUS_CHECK_CONDITION)
     3440        {
     3441            /* Sense data is already set, end the request and notify the guest. */
     3442            Log(("%s: sense=%#x (%s) asc=%#x ascq=%#x (%s)\n", __FUNCTION__, s->abATAPISense[2] & 0x0f, SCSISenseText(s->abATAPISense[2] & 0x0f),
     3443                     s->abATAPISense[12], s->abATAPISense[13], SCSISenseExtText(s->abATAPISense[12], s->abATAPISense[13])));
     3444            s->uATARegError = s->abATAPISense[2] << 4;
     3445            ataSetStatusValue(s, ATA_STAT_READY | ATA_STAT_ERR);
     3446            s->uATARegNSector = (s->uATARegNSector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
     3447            Log2(("%s: interrupt reason %#04x\n", __FUNCTION__, s->uATARegNSector));
     3448            s->cbTotalTransfer = 0;
     3449            s->cbElementaryTransfer = 0;
     3450            s->cbAtapiPassthroughTransfer = 0;
     3451            s->iIOBufferCur = 0;
     3452            s->iIOBufferEnd = 0;
     3453            s->uTxDir = PDMMEDIATXDIR_NONE;
     3454            s->iBeginTransfer = ATAFN_BT_NULL;
     3455            s->iSourceSink = ATAFN_SS_NULL;
     3456        }
     3457        else if (u8ScsiSts == SCSI_STATUS_OK)
     3458            atapiR3CmdOK(s);
    37003459    }
    37013460}
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

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