static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)

{

    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);

    uint64_t nb_sectors;

    bool dbd;

    int page, buflen, ret, page_control;

    uint8_t *p;

    uint8_t dev_specific_param;



    dbd = (r->req.cmd.buf[1] & 0x8) != 0;

    page = r->req.cmd.buf[2] & 0x3f;

    page_control = (r->req.cmd.buf[2] & 0xc0) >> 6;

    DPRINTF("Mode Sense(%d) (page %d, xfer %zd, page_control %d)\n",

        (r->req.cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, r->req.cmd.xfer, page_control);

    memset(outbuf, 0, r->req.cmd.xfer);

    p = outbuf;



    if (s->qdev.type == TYPE_DISK) {

        dev_specific_param = s->features & (1 << SCSI_DISK_F_DPOFUA) ? 0x10 : 0;

        if (bdrv_is_read_only(s->qdev.conf.bs)) {

            dev_specific_param |= 0x80; /* Readonly.  */

        }

    } else {

        /* MMC prescribes that CD/DVD drives have no block descriptors,

         * and defines no device-specific parameter.  */

        dev_specific_param = 0x00;

        dbd = true;

    }



    if (r->req.cmd.buf[0] == MODE_SENSE) {

        p[1] = 0; /* Default media type.  */

        p[2] = dev_specific_param;

        p[3] = 0; /* Block descriptor length.  */

        p += 4;

    } else { /* MODE_SENSE_10 */

        p[2] = 0; /* Default media type.  */

        p[3] = dev_specific_param;

        p[6] = p[7] = 0; /* Block descriptor length.  */

        p += 8;

    }



    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);

    if (!dbd && nb_sectors) {

        if (r->req.cmd.buf[0] == MODE_SENSE) {

            outbuf[3] = 8; /* Block descriptor length  */

        } else { /* MODE_SENSE_10 */

            outbuf[7] = 8; /* Block descriptor length  */

        }

        nb_sectors /= (s->qdev.blocksize / 512);

        if (nb_sectors > 0xffffff) {

            nb_sectors = 0;

        }

        p[0] = 0; /* media density code */

        p[1] = (nb_sectors >> 16) & 0xff;

        p[2] = (nb_sectors >> 8) & 0xff;

        p[3] = nb_sectors & 0xff;

        p[4] = 0; /* reserved */

        p[5] = 0; /* bytes 5-7 are the sector size in bytes */

        p[6] = s->qdev.blocksize >> 8;

        p[7] = 0;

        p += 8;

    }



    if (page_control == 3) {

        /* Saved Values */

        scsi_check_condition(r, SENSE_CODE(SAVING_PARAMS_NOT_SUPPORTED));

        return -1;

    }



    if (page == 0x3f) {

        for (page = 0; page <= 0x3e; page++) {

            mode_sense_page(s, page, &p, page_control);

        }

    } else {

        ret = mode_sense_page(s, page, &p, page_control);

        if (ret == -1) {

            return -1;

        }

    }



    buflen = p - outbuf;

    /*

     * The mode data length field specifies the length in bytes of the

     * following data that is available to be transferred. The mode data

     * length does not include itself.

     */

    if (r->req.cmd.buf[0] == MODE_SENSE) {

        outbuf[0] = buflen - 1;

    } else { /* MODE_SENSE_10 */

        outbuf[0] = ((buflen - 2) >> 8) & 0xff;

        outbuf[1] = (buflen - 2) & 0xff;

    }

    return buflen;

}

static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)

{

    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);

    uint64_t nb_sectors;

    bool dbd;

    int page, buflen, ret, page_control;

    uint8_t *p;

    uint8_t dev_specific_param;



    dbd = (r->req.cmd.buf[1] & 0x8) != 0;

    page = r->req.cmd.buf[2] & 0x3f;

    page_control = (r->req.cmd.buf[2] & 0xc0) >> 6;

    DPRINTF("Mode Sense(%d) (page %d, xfer %zd, page_control %d)\n",

        (r->req.cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, r->req.cmd.xfer, page_control);

    memset(outbuf, 0, r->req.cmd.xfer);

    p = outbuf;



    if (s->qdev.type == TYPE_DISK) {

        dev_specific_param = s->features & (1 << SCSI_DISK_F_DPOFUA) ? 0x10 : 0;

        if (bdrv_is_read_only(s->qdev.conf.bs)) {

            dev_specific_param |= 0x80; 

        }

    } else {

        



        dev_specific_param = 0x00;

        dbd = true;

    }



    if (r->req.cmd.buf[0] == MODE_SENSE) {

        p[1] = 0; 

        p[2] = dev_specific_param;

        p[3] = 0; 

        p += 4;

    } else { 

        p[2] = 0; 

        p[3] = dev_specific_param;

        p[6] = p[7] = 0; 

        p += 8;

    }



    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);

    if (!dbd && nb_sectors) {

        if (r->req.cmd.buf[0] == MODE_SENSE) {

            outbuf[3] = 8; 

        } else { 

            outbuf[7] = 8; 

        }

        nb_sectors /= (s->qdev.blocksize / 512);

        if (nb_sectors > 0xffffff) {

            nb_sectors = 0;

        }

        p[0] = 0; 

        p[1] = (nb_sectors >> 16) & 0xff;

        p[2] = (nb_sectors >> 8) & 0xff;

        p[3] = nb_sectors & 0xff;

        p[4] = 0; 

        p[5] = 0; 

        p[6] = s->qdev.blocksize >> 8;

        p[7] = 0;

        p += 8;

    }



    if (page_control == 3) {

        

        scsi_check_condition(r, SENSE_CODE(SAVING_PARAMS_NOT_SUPPORTED));

        return -1;

    }



    if (page == 0x3f) {

        for (page = 0; page <= 0x3e; page++) {

            mode_sense_page(s, page, &p, page_control);

        }

    } else {

        ret = mode_sense_page(s, page, &p, page_control);

        if (ret == -1) {

            return -1;

        }

    }



    buflen = p - outbuf;

    









    if (r->req.cmd.buf[0] == MODE_SENSE) {

        outbuf[0] = buflen - 1;

    } else { 

        outbuf[0] = ((buflen - 2) >> 8) & 0xff;

        outbuf[1] = (buflen - 2) & 0xff;

    }

    return buflen;

}

static int FUNC_0(SCSIDiskReq *VAR_0, uint8_t *VAR_1)

{

    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, VAR_0->req.dev);

    uint64_t nb_sectors;

    bool dbd;

    int VAR_2, VAR_3, VAR_4, VAR_5;

    uint8_t *p;

    uint8_t dev_specific_param;



    dbd = (VAR_0->req.cmd.buf[1] & 0x8) != 0;

    VAR_2 = VAR_0->req.cmd.buf[2] & 0x3f;

    VAR_5 = (VAR_0->req.cmd.buf[2] & 0xc0) >> 6;

    DPRINTF("Mode Sense(%d) (VAR_2 %d, xfer %zd, VAR_5 %d)\n",

        (VAR_0->req.cmd.buf[0] == MODE_SENSE) ? 6 : 10, VAR_2, VAR_0->req.cmd.xfer, VAR_5);

    memset(VAR_1, 0, VAR_0->req.cmd.xfer);

    p = VAR_1;



    if (s->qdev.type == TYPE_DISK) {

        dev_specific_param = s->features & (1 << SCSI_DISK_F_DPOFUA) ? 0x10 : 0;

        if (bdrv_is_read_only(s->qdev.conf.bs)) {

            dev_specific_param |= 0x80; 

        }

    } else {

        



        dev_specific_param = 0x00;

        dbd = true;

    }



    if (VAR_0->req.cmd.buf[0] == MODE_SENSE) {

        p[1] = 0; 

        p[2] = dev_specific_param;

        p[3] = 0; 

        p += 4;

    } else { 

        p[2] = 0; 

        p[3] = dev_specific_param;

        p[6] = p[7] = 0; 

        p += 8;

    }



    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);

    if (!dbd && nb_sectors) {

        if (VAR_0->req.cmd.buf[0] == MODE_SENSE) {

            VAR_1[3] = 8; 

        } else { 

            VAR_1[7] = 8; 

        }

        nb_sectors /= (s->qdev.blocksize / 512);

        if (nb_sectors > 0xffffff) {

            nb_sectors = 0;

        }

        p[0] = 0; 

        p[1] = (nb_sectors >> 16) & 0xff;

        p[2] = (nb_sectors >> 8) & 0xff;

        p[3] = nb_sectors & 0xff;

        p[4] = 0; 

        p[5] = 0; 

        p[6] = s->qdev.blocksize >> 8;

        p[7] = 0;

        p += 8;

    }



    if (VAR_5 == 3) {

        

        scsi_check_condition(VAR_0, SENSE_CODE(SAVING_PARAMS_NOT_SUPPORTED));

        return -1;

    }



    if (VAR_2 == 0x3f) {

        for (VAR_2 = 0; VAR_2 <= 0x3e; VAR_2++) {

            mode_sense_page(s, VAR_2, &p, VAR_5);

        }

    } else {

        VAR_4 = mode_sense_page(s, VAR_2, &p, VAR_5);

        if (VAR_4 == -1) {

            return -1;

        }

    }



    VAR_3 = p - VAR_1;

    









    if (VAR_0->req.cmd.buf[0] == MODE_SENSE) {

        VAR_1[0] = VAR_3 - 1;

    } else { 

        VAR_1[0] = ((VAR_3 - 2) >> 8) & 0xff;

        VAR_1[1] = (VAR_3 - 2) & 0xff;

    }

    return VAR_3;

}

static int FUNC_0(SCSIDiskReq *VAR_0, uint8_t *VAR_1)
{ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, VAR_0->req.dev); uint64_t nb_sectors; bool dbd; int VAR_2, VAR_3, VAR_4, VAR_5; uint8_t *p; uint8_t dev_specific_param; dbd = (VAR_0->req.cmd.buf[1] & 0x8) != 0; VAR_2 = VAR_0->req.cmd.buf[2] & 0x3f; VAR_5 = (VAR_0->req.cmd.buf[2] & 0xc0) >> 6; DPRINTF("Mode Sense(%d) (VAR_2 %d, xfer %zd, VAR_5 %d)\n",
(VAR_0->req.cmd.buf[0] == MODE_SENSE) ? 6 : 10, VAR_2, VAR_0->req.cmd.xfer, VAR_5); memset(VAR_1, 0, VAR_0->req.cmd.xfer); p = VAR_1; if (s->qdev.type == TYPE_DISK) { dev_specific_param = s->features & (1 << SCSI_DISK_F_DPOFUA) ? 0x10 : 0; if (bdrv_is_read_only(s->qdev.conf.bs)) { dev_specific_param |= 0x80; } } else { dev_specific_param = 0x00; dbd = true; } if (VAR_0->req.cmd.buf[0] == MODE_SENSE) { p[1] = 0; p[2] = dev_specific_param; p[3] = 0; p += 4; } else { p[2] = 0; p[3] = dev_specific_param; p[6] = p[7] = 0; p += 8; } bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors); if (!dbd && nb_sectors) { if (VAR_0->req.cmd.buf[0] == MODE_SENSE) { VAR_1[3] = 8; } else { VAR_1[7] = 8; } nb_sectors /= (s->qdev.blocksize / 512); if (nb_sectors > 0xffffff) { nb_sectors = 0; } p[0] = 0; p[1] = (nb_sectors >> 16) & 0xff; p[2] = (nb_sectors >> 8) & 0xff; p[3] = nb_sectors & 0xff; p[4] = 0; p[5] = 0; p[6] = s->qdev.blocksize >> 8; p[7] = 0; p += 8; } if (VAR_5 == 3) { scsi_check_condition(VAR_0, SENSE_CODE(SAVING_PARAMS_NOT_SUPPORTED)); return -1; } if (VAR_2 == 0x3f) { for (VAR_2 = 0; VAR_2 <= 0x3e; VAR_2++) { mode_sense_page(s, VAR_2, &p, VAR_5); } } else { VAR_4 = mode_sense_page(s, VAR_2, &p, VAR_5); if (VAR_4 == -1) { return -1; } } VAR_3 = p - VAR_1; if (VAR_0->req.cmd.buf[0] == MODE_SENSE) { VAR_1[0] = VAR_3 - 1; } else { VAR_1[0] = ((VAR_3 - 2) >> 8) & 0xff; VAR_1[1] = (VAR_3 - 2) & 0xff; } return VAR_3; }