static int scsi_req_length(SCSIRequest *req, uint8_t *cmd) { switch (cmd[0] >> 5) { case 0: req->cmd.xfer = cmd[4]; req->cmd.len = 6; /* length 0 means 256 blocks */ if (req->cmd.xfer == 0) req->cmd.xfer = 256; break; case 1: case 2: req->cmd.xfer = cmd[8] | (cmd[7] << 8); req->cmd.len = 10; break; case 4: req->cmd.xfer = cmd[13] | (cmd[12] << 8) | (cmd[11] << 16) | (cmd[10] << 24); req->cmd.len = 16; break; case 5: req->cmd.xfer = cmd[9] | (cmd[8] << 8) | (cmd[7] << 16) | (cmd[6] << 24); req->cmd.len = 12; break; default: trace_scsi_req_parse_bad(req->dev->id, req->lun, req->tag, cmd[0]); return -1; } switch(cmd[0]) { case TEST_UNIT_READY: case START_STOP: case SEEK_6: case WRITE_FILEMARKS: case SPACE: case RESERVE: case RELEASE: case ERASE: case ALLOW_MEDIUM_REMOVAL: case VERIFY: case SEEK_10: case SYNCHRONIZE_CACHE: case LOCK_UNLOCK_CACHE: case LOAD_UNLOAD: case SET_CD_SPEED: case SET_LIMITS: case WRITE_LONG: case MOVE_MEDIUM: case UPDATE_BLOCK: req->cmd.xfer = 0; break; case MODE_SENSE: break; case WRITE_SAME: req->cmd.xfer = 1; break; case READ_CAPACITY: req->cmd.xfer = 8; break; case READ_BLOCK_LIMITS: req->cmd.xfer = 6; break; case READ_POSITION: req->cmd.xfer = 20; break; case SEND_VOLUME_TAG: req->cmd.xfer *= 40; break; case MEDIUM_SCAN: req->cmd.xfer *= 8; break; case WRITE_10: case WRITE_VERIFY: case WRITE_6: case WRITE_12: case WRITE_VERIFY_12: case WRITE_16: case WRITE_VERIFY_16: req->cmd.xfer *= req->dev->blocksize; break; case READ_10: case READ_6: case READ_REVERSE: case RECOVER_BUFFERED_DATA: case READ_12: case READ_16: req->cmd.xfer *= req->dev->blocksize; break; case INQUIRY: req->cmd.xfer = cmd[4] | (cmd[3] << 8); break; case MAINTENANCE_OUT: case MAINTENANCE_IN: if (req->dev->type == TYPE_ROM) { /* GPCMD_REPORT_KEY and GPCMD_SEND_KEY from multi media commands */ req->cmd.xfer = cmd[9] | (cmd[8] << 8); } break; } return 0; }