Commit dfe1ce5d authored by Anthony Liguori's avatar Anthony Liguori
Browse files

Merge remote-tracking branch 'kwolf/for-anthony' into staging

* kwolf/for-anthony: (41 commits)
  fdc-test: Clean up a bit
  fdc-test: introduce test_relative_seek
  fdc: fix relative seek
  qemu-iotests: Valgrind support
  coroutine-ucontext: Help valgrind understand coroutines
  qemu-io: Fix memory leaks
  hw/block-common: Factor out fall back to legacy -drive cyls=...
  blockdev: Don't limit DriveInfo serial to 20 characters
  hw/block-common: Factor out fall back to legacy -drive serial=...
  hw/block-common: Move BlockConf & friends from block.h
  Relax IDE CHS limits from 16383,16,63 to 65535,16,255
  blockdev: Drop redundant CHS validation for if=ide
  hd-geometry: Compute BIOS CHS translation in one place
  qtest: Test we don't put hard disk info into CMOS for a CD-ROM
  ide pc: Put hard disk info into CMOS only for hard disks
  block: Geometry and translation hints are now useless, purge them
  qtest: Cover qdev property for BIOS CHS translation
  ide: qdev property for BIOS CHS translation
  qdev: New property type chs-translation
  qdev: Collect private helpers in one place
  ...
parents 09f06a6c c3cdc1b0
Loading
Loading
Loading
Loading
+0 −254
Original line number Diff line number Diff line
@@ -996,12 +996,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
    bs_dest->block_timer        = bs_src->block_timer;
    bs_dest->io_limits_enabled  = bs_src->io_limits_enabled;

    /* geometry */
    bs_dest->cyls               = bs_src->cyls;
    bs_dest->heads              = bs_src->heads;
    bs_dest->secs               = bs_src->secs;
    bs_dest->translation        = bs_src->translation;

    /* r/w error */
    bs_dest->on_read_error      = bs_src->on_read_error;
    bs_dest->on_write_error     = bs_src->on_write_error;
@@ -2132,148 +2126,6 @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
    *nb_sectors_ptr = length;
}

struct partition {
        uint8_t boot_ind;           /* 0x80 - active */
        uint8_t head;               /* starting head */
        uint8_t sector;             /* starting sector */
        uint8_t cyl;                /* starting cylinder */
        uint8_t sys_ind;            /* What partition type */
        uint8_t end_head;           /* end head */
        uint8_t end_sector;         /* end sector */
        uint8_t end_cyl;            /* end cylinder */
        uint32_t start_sect;        /* starting sector counting from 0 */
        uint32_t nr_sects;          /* nr of sectors in partition */
} QEMU_PACKED;

/* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */
static int guess_disk_lchs(BlockDriverState *bs,
                           int *pcylinders, int *pheads, int *psectors)
{
    uint8_t buf[BDRV_SECTOR_SIZE];
    int i, heads, sectors, cylinders;
    struct partition *p;
    uint32_t nr_sects;
    uint64_t nb_sectors;

    bdrv_get_geometry(bs, &nb_sectors);

    /**
     * The function will be invoked during startup not only in sync I/O mode,
     * but also in async I/O mode. So the I/O throttling function has to
     * be disabled temporarily here, not permanently.
     */
    if (bdrv_read_unthrottled(bs, 0, buf, 1) < 0) {
        return -1;
    }
    /* test msdos magic */
    if (buf[510] != 0x55 || buf[511] != 0xaa)
        return -1;
    for(i = 0; i < 4; i++) {
        p = ((struct partition *)(buf + 0x1be)) + i;
        nr_sects = le32_to_cpu(p->nr_sects);
        if (nr_sects && p->end_head) {
            /* We make the assumption that the partition terminates on
               a cylinder boundary */
            heads = p->end_head + 1;
            sectors = p->end_sector & 63;
            if (sectors == 0)
                continue;
            cylinders = nb_sectors / (heads * sectors);
            if (cylinders < 1 || cylinders > 16383)
                continue;
            *pheads = heads;
            *psectors = sectors;
            *pcylinders = cylinders;
#if 0
            printf("guessed geometry: LCHS=%d %d %d\n",
                   cylinders, heads, sectors);
#endif
            return 0;
        }
    }
    return -1;
}

void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs)
{
    int translation, lba_detected = 0;
    int cylinders, heads, secs;
    uint64_t nb_sectors;

    /* if a geometry hint is available, use it */
    bdrv_get_geometry(bs, &nb_sectors);
    bdrv_get_geometry_hint(bs, &cylinders, &heads, &secs);
    translation = bdrv_get_translation_hint(bs);
    if (cylinders != 0) {
        *pcyls = cylinders;
        *pheads = heads;
        *psecs = secs;
    } else {
        if (guess_disk_lchs(bs, &cylinders, &heads, &secs) == 0) {
            if (heads > 16) {
                /* if heads > 16, it means that a BIOS LBA
                   translation was active, so the default
                   hardware geometry is OK */
                lba_detected = 1;
                goto default_geometry;
            } else {
                *pcyls = cylinders;
                *pheads = heads;
                *psecs = secs;
                /* disable any translation to be in sync with
                   the logical geometry */
                if (translation == BIOS_ATA_TRANSLATION_AUTO) {
                    bdrv_set_translation_hint(bs,
                                              BIOS_ATA_TRANSLATION_NONE);
                }
            }
        } else {
        default_geometry:
            /* if no geometry, use a standard physical disk geometry */
            cylinders = nb_sectors / (16 * 63);

            if (cylinders > 16383)
                cylinders = 16383;
            else if (cylinders < 2)
                cylinders = 2;
            *pcyls = cylinders;
            *pheads = 16;
            *psecs = 63;
            if ((lba_detected == 1) && (translation == BIOS_ATA_TRANSLATION_AUTO)) {
                if ((*pcyls * *pheads) <= 131072) {
                    bdrv_set_translation_hint(bs,
                                              BIOS_ATA_TRANSLATION_LARGE);
                } else {
                    bdrv_set_translation_hint(bs,
                                              BIOS_ATA_TRANSLATION_LBA);
                }
            }
        }
        bdrv_set_geometry_hint(bs, *pcyls, *pheads, *psecs);
    }
}

void bdrv_set_geometry_hint(BlockDriverState *bs,
                            int cyls, int heads, int secs)
{
    bs->cyls = cyls;
    bs->heads = heads;
    bs->secs = secs;
}

void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
{
    bs->translation = translation;
}

void bdrv_get_geometry_hint(BlockDriverState *bs,
                            int *pcyls, int *pheads, int *psecs)
{
    *pcyls = bs->cyls;
    *pheads = bs->heads;
    *psecs = bs->secs;
}

/* throttling disk io limits */
void bdrv_set_io_limits(BlockDriverState *bs,
                        BlockIOLimit *io_limits)
@@ -2282,112 +2134,6 @@ void bdrv_set_io_limits(BlockDriverState *bs,
    bs->io_limits_enabled = bdrv_io_limits_enabled(bs);
}

/* Recognize floppy formats */
typedef struct FDFormat {
    FDriveType drive;
    uint8_t last_sect;
    uint8_t max_track;
    uint8_t max_head;
    FDriveRate rate;
} FDFormat;

static const FDFormat fd_formats[] = {
    /* First entry is default format */
    /* 1.44 MB 3"1/2 floppy disks */
    { FDRIVE_DRV_144, 18, 80, 1, FDRIVE_RATE_500K, },
    { FDRIVE_DRV_144, 20, 80, 1, FDRIVE_RATE_500K, },
    { FDRIVE_DRV_144, 21, 80, 1, FDRIVE_RATE_500K, },
    { FDRIVE_DRV_144, 21, 82, 1, FDRIVE_RATE_500K, },
    { FDRIVE_DRV_144, 21, 83, 1, FDRIVE_RATE_500K, },
    { FDRIVE_DRV_144, 22, 80, 1, FDRIVE_RATE_500K, },
    { FDRIVE_DRV_144, 23, 80, 1, FDRIVE_RATE_500K, },
    { FDRIVE_DRV_144, 24, 80, 1, FDRIVE_RATE_500K, },
    /* 2.88 MB 3"1/2 floppy disks */
    { FDRIVE_DRV_288, 36, 80, 1, FDRIVE_RATE_1M, },
    { FDRIVE_DRV_288, 39, 80, 1, FDRIVE_RATE_1M, },
    { FDRIVE_DRV_288, 40, 80, 1, FDRIVE_RATE_1M, },
    { FDRIVE_DRV_288, 44, 80, 1, FDRIVE_RATE_1M, },
    { FDRIVE_DRV_288, 48, 80, 1, FDRIVE_RATE_1M, },
    /* 720 kB 3"1/2 floppy disks */
    { FDRIVE_DRV_144,  9, 80, 1, FDRIVE_RATE_250K, },
    { FDRIVE_DRV_144, 10, 80, 1, FDRIVE_RATE_250K, },
    { FDRIVE_DRV_144, 10, 82, 1, FDRIVE_RATE_250K, },
    { FDRIVE_DRV_144, 10, 83, 1, FDRIVE_RATE_250K, },
    { FDRIVE_DRV_144, 13, 80, 1, FDRIVE_RATE_250K, },
    { FDRIVE_DRV_144, 14, 80, 1, FDRIVE_RATE_250K, },
    /* 1.2 MB 5"1/4 floppy disks */
    { FDRIVE_DRV_120, 15, 80, 1, FDRIVE_RATE_500K, },
    { FDRIVE_DRV_120, 18, 80, 1, FDRIVE_RATE_500K, },
    { FDRIVE_DRV_120, 18, 82, 1, FDRIVE_RATE_500K, },
    { FDRIVE_DRV_120, 18, 83, 1, FDRIVE_RATE_500K, },
    { FDRIVE_DRV_120, 20, 80, 1, FDRIVE_RATE_500K, },
    /* 720 kB 5"1/4 floppy disks */
    { FDRIVE_DRV_120,  9, 80, 1, FDRIVE_RATE_250K, },
    { FDRIVE_DRV_120, 11, 80, 1, FDRIVE_RATE_250K, },
    /* 360 kB 5"1/4 floppy disks */
    { FDRIVE_DRV_120,  9, 40, 1, FDRIVE_RATE_300K, },
    { FDRIVE_DRV_120,  9, 40, 0, FDRIVE_RATE_300K, },
    { FDRIVE_DRV_120, 10, 41, 1, FDRIVE_RATE_300K, },
    { FDRIVE_DRV_120, 10, 42, 1, FDRIVE_RATE_300K, },
    /* 320 kB 5"1/4 floppy disks */
    { FDRIVE_DRV_120,  8, 40, 1, FDRIVE_RATE_250K, },
    { FDRIVE_DRV_120,  8, 40, 0, FDRIVE_RATE_250K, },
    /* 360 kB must match 5"1/4 better than 3"1/2... */
    { FDRIVE_DRV_144,  9, 80, 0, FDRIVE_RATE_250K, },
    /* end */
    { FDRIVE_DRV_NONE, -1, -1, 0, 0, },
};

void bdrv_get_floppy_geometry_hint(BlockDriverState *bs, int *nb_heads,
                                   int *max_track, int *last_sect,
                                   FDriveType drive_in, FDriveType *drive,
                                   FDriveRate *rate)
{
    const FDFormat *parse;
    uint64_t nb_sectors, size;
    int i, first_match, match;

    bdrv_get_geometry(bs, &nb_sectors);
    match = -1;
    first_match = -1;
    for (i = 0; ; i++) {
        parse = &fd_formats[i];
        if (parse->drive == FDRIVE_DRV_NONE) {
            break;
        }
        if (drive_in == parse->drive ||
            drive_in == FDRIVE_DRV_NONE) {
            size = (parse->max_head + 1) * parse->max_track *
                parse->last_sect;
            if (nb_sectors == size) {
                match = i;
                break;
            }
            if (first_match == -1) {
                first_match = i;
            }
        }
    }
    if (match == -1) {
        if (first_match == -1) {
            match = 1;
        } else {
            match = first_match;
        }
        parse = &fd_formats[match];
    }
    *nb_heads = parse->max_head + 1;
    *max_track = parse->max_track;
    *last_sect = parse->last_sect;
    *drive = parse->drive;
    *rate = parse->rate;
}

int bdrv_get_translation_hint(BlockDriverState *bs)
{
    return bs->translation;
}

void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error,
                       BlockErrorAction on_write_error)
{
+0 −70
Original line number Diff line number Diff line
@@ -178,7 +178,6 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset);
int64_t bdrv_getlength(BlockDriverState *bs);
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs);
int bdrv_commit(BlockDriverState *bs);
int bdrv_commit_all(void);
int bdrv_change_backing_file(BlockDriverState *bs,
@@ -258,36 +257,6 @@ int bdrv_has_zero_init(BlockDriverState *bs);
int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
                      int *pnum);

#define BIOS_ATA_TRANSLATION_AUTO   0
#define BIOS_ATA_TRANSLATION_NONE   1
#define BIOS_ATA_TRANSLATION_LBA    2
#define BIOS_ATA_TRANSLATION_LARGE  3
#define BIOS_ATA_TRANSLATION_RECHS  4

void bdrv_set_geometry_hint(BlockDriverState *bs,
                            int cyls, int heads, int secs);
void bdrv_set_translation_hint(BlockDriverState *bs, int translation);
void bdrv_get_geometry_hint(BlockDriverState *bs,
                            int *pcyls, int *pheads, int *psecs);
typedef enum FDriveType {
    FDRIVE_DRV_144  = 0x00,   /* 1.44 MB 3"5 drive      */
    FDRIVE_DRV_288  = 0x01,   /* 2.88 MB 3"5 drive      */
    FDRIVE_DRV_120  = 0x02,   /* 1.2  MB 5"25 drive     */
    FDRIVE_DRV_NONE = 0x03,   /* No drive connected     */
} FDriveType;

typedef enum FDriveRate {
    FDRIVE_RATE_500K = 0x00,  /* 500 Kbps */
    FDRIVE_RATE_300K = 0x01,  /* 300 Kbps */
    FDRIVE_RATE_250K = 0x02,  /* 250 Kbps */
    FDRIVE_RATE_1M   = 0x03,  /*   1 Mbps */
} FDriveRate;

void bdrv_get_floppy_geometry_hint(BlockDriverState *bs, int *nb_heads,
                                   int *max_track, int *last_sect,
                                   FDriveType drive_in, FDriveType *drive,
                                   FDriveRate *rate);
int bdrv_get_translation_hint(BlockDriverState *bs);
void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error,
                       BlockErrorAction on_write_error);
BlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read);
@@ -434,43 +403,4 @@ typedef enum {
#define BLKDBG_EVENT(bs, evt) bdrv_debug_event(bs, evt)
void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event);


/* Convenience for block device models */

typedef struct BlockConf {
    BlockDriverState *bs;
    uint16_t physical_block_size;
    uint16_t logical_block_size;
    uint16_t min_io_size;
    uint32_t opt_io_size;
    int32_t bootindex;
    uint32_t discard_granularity;
} BlockConf;

static inline unsigned int get_physical_block_exp(BlockConf *conf)
{
    unsigned int exp = 0, size;

    for (size = conf->physical_block_size;
        size > conf->logical_block_size;
        size >>= 1) {
        exp++;
    }

    return exp;
}

#define DEFINE_BLOCK_PROPERTIES(_state, _conf)                          \
    DEFINE_PROP_DRIVE("drive", _state, _conf.bs),                       \
    DEFINE_PROP_BLOCKSIZE("logical_block_size", _state,                 \
                          _conf.logical_block_size, 512),               \
    DEFINE_PROP_BLOCKSIZE("physical_block_size", _state,                \
                          _conf.physical_block_size, 512),              \
    DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0),  \
    DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0),    \
    DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1),        \
    DEFINE_PROP_UINT32("discard_granularity", _state, \
                       _conf.discard_granularity, 0)

#endif
+65 −85
Original line number Diff line number Diff line
@@ -498,26 +498,6 @@ success:
    return fd;
}

static int send_req(int sockfd, SheepdogReq *hdr, void *data,
                    unsigned int *wlen)
{
    int ret;

    ret = qemu_send_full(sockfd, hdr, sizeof(*hdr), 0);
    if (ret < sizeof(*hdr)) {
        error_report("failed to send a req, %s", strerror(errno));
        return -errno;
    }

    ret = qemu_send_full(sockfd, data, *wlen, 0);
    if (ret < *wlen) {
        error_report("failed to send a req, %s", strerror(errno));
        ret = -errno;
    }

    return ret;
}

static coroutine_fn int send_co_req(int sockfd, SheepdogReq *hdr, void *data,
                                    unsigned int *wlen)
{
@@ -537,49 +517,6 @@ static coroutine_fn int send_co_req(int sockfd, SheepdogReq *hdr, void *data,
    return ret;
}

static coroutine_fn int do_co_req(int sockfd, SheepdogReq *hdr, void *data,
                                  unsigned int *wlen, unsigned int *rlen);

static int do_req(int sockfd, SheepdogReq *hdr, void *data,
                  unsigned int *wlen, unsigned int *rlen)
{
    int ret;

    if (qemu_in_coroutine()) {
        return do_co_req(sockfd, hdr, data, wlen, rlen);
    }

    socket_set_block(sockfd);
    ret = send_req(sockfd, hdr, data, wlen);
    if (ret < 0) {
        goto out;
    }

    ret = qemu_recv_full(sockfd, hdr, sizeof(*hdr), 0);
    if (ret < sizeof(*hdr)) {
        error_report("failed to get a rsp, %s", strerror(errno));
        ret = -errno;
        goto out;
    }

    if (*rlen > hdr->data_length) {
        *rlen = hdr->data_length;
    }

    if (*rlen) {
        ret = qemu_recv_full(sockfd, data, *rlen, 0);
        if (ret < *rlen) {
            error_report("failed to get the data, %s", strerror(errno));
            ret = -errno;
            goto out;
        }
    }
    ret = 0;
out:
    socket_set_nonblock(sockfd);
    return ret;
}

static void restart_co_req(void *opaque)
{
    Coroutine *co = opaque;
@@ -587,11 +524,26 @@ static void restart_co_req(void *opaque)
    qemu_coroutine_enter(co, NULL);
}

static coroutine_fn int do_co_req(int sockfd, SheepdogReq *hdr, void *data,
                                  unsigned int *wlen, unsigned int *rlen)
typedef struct SheepdogReqCo {
    int sockfd;
    SheepdogReq *hdr;
    void *data;
    unsigned int *wlen;
    unsigned int *rlen;
    int ret;
    bool finished;
} SheepdogReqCo;

static coroutine_fn void do_co_req(void *opaque)
{
    int ret;
    Coroutine *co;
    SheepdogReqCo *srco = opaque;
    int sockfd = srco->sockfd;
    SheepdogReq *hdr = srco->hdr;
    void *data = srco->data;
    unsigned int *wlen = srco->wlen;
    unsigned int *rlen = srco->rlen;

    co = qemu_coroutine_self();
    qemu_aio_set_fd_handler(sockfd, NULL, restart_co_req, NULL, co);
@@ -627,7 +579,36 @@ static coroutine_fn int do_co_req(int sockfd, SheepdogReq *hdr, void *data,
out:
    qemu_aio_set_fd_handler(sockfd, NULL, NULL, NULL, NULL);
    socket_set_nonblock(sockfd);
    return ret;

    srco->ret = ret;
    srco->finished = true;
}

static int do_req(int sockfd, SheepdogReq *hdr, void *data,
                  unsigned int *wlen, unsigned int *rlen)
{
    Coroutine *co;
    SheepdogReqCo srco = {
        .sockfd = sockfd,
        .hdr = hdr,
        .data = data,
        .wlen = wlen,
        .rlen = rlen,
        .ret = 0,
        .finished = false,
    };

    if (qemu_in_coroutine()) {
        do_co_req(&srco);
    } else {
        co = qemu_coroutine_create(do_co_req);
        qemu_coroutine_enter(co, &srco);
        while (!srco.finished) {
            qemu_aio_wait();
        }
    }

    return srco.ret;
}

static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
@@ -1590,19 +1571,26 @@ static int coroutine_fn sd_co_rw_vector(void *p)

        len = MIN(total - done, SD_DATA_OBJ_SIZE - offset);

        switch (acb->aiocb_type) {
        case AIOCB_READ_UDATA:
            if (!inode->data_vdi_id[idx]) {
            if (acb->aiocb_type == AIOCB_READ_UDATA) {
                qemu_iovec_memset(acb->qiov, done, 0, len);
                goto done;
            }

            break;
        case AIOCB_WRITE_UDATA:
            if (!inode->data_vdi_id[idx]) {
                create = 1;
        } else if (acb->aiocb_type == AIOCB_WRITE_UDATA
                   && !is_data_obj_writable(inode, idx)) {
            } else if (!is_data_obj_writable(inode, idx)) {
                /* Copy-On-Write */
                create = 1;
                old_oid = oid;
                flags = SD_FLAG_CMD_COW;
            }
            break;
        default:
            break;
        }

        if (create) {
            dprintf("update ino (%" PRIu32 ") %" PRIu64 " %" PRIu64 " %ld\n",
@@ -1687,20 +1675,12 @@ static coroutine_fn int sd_co_readv(BlockDriverState *bs, int64_t sector_num,
                       int nb_sectors, QEMUIOVector *qiov)
{
    SheepdogAIOCB *acb;
    int i, ret;
    int ret;

    acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors, NULL, NULL);
    acb->aiocb_type = AIOCB_READ_UDATA;
    acb->aio_done_func = sd_finish_aiocb;

    /*
     * TODO: we can do better; we don't need to initialize
     * blindly.
     */
    for (i = 0; i < qiov->niov; i++) {
        memset(qiov->iov[i].iov_base, 0, qiov->iov[i].iov_len);
    }

    ret = sd_co_rw_vector(acb);
    if (ret <= 0) {
        qemu_aio_release(acb);
+32 −26
Original line number Diff line number Diff line
@@ -359,11 +359,12 @@ typedef struct BDRVVVFATState {
 * if the position is outside the specified geometry, fill maximum value for CHS
 * and return 1 to signal overflow.
 */
static int sector2CHS(BlockDriverState* bs, mbr_chs_t * chs, int spos){
static int sector2CHS(mbr_chs_t *chs, int spos, int cyls, int heads, int secs)
{
    int head,sector;
    sector   = spos % (bs->secs);  spos/= bs->secs;
    head     = spos % (bs->heads); spos/= bs->heads;
    if(spos >= bs->cyls){
    sector   = spos % secs;  spos /= secs;
    head     = spos % heads; spos /= heads;
    if (spos >= cyls) {
        /* Overflow,
        it happens if 32bit sector positions are used, while CHS is only 24bit.
        Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */
@@ -378,7 +379,7 @@ static int sector2CHS(BlockDriverState* bs, mbr_chs_t * chs, int spos){
    return 0;
}

static void init_mbr(BDRVVVFATState* s)
static void init_mbr(BDRVVVFATState *s, int cyls, int heads, int secs)
{
    /* TODO: if the files mbr.img and bootsect.img exist, use them */
    mbr_t* real_mbr=(mbr_t*)s->first_sectors;
@@ -393,12 +394,15 @@ static void init_mbr(BDRVVVFATState* s)
    partition->attributes=0x80; /* bootable */

    /* LBA is used when partition is outside the CHS geometry */
    lba = sector2CHS(s->bs, &partition->start_CHS, s->first_sectors_number-1);
    lba|= sector2CHS(s->bs, &partition->end_CHS,   s->sector_count);
    lba  = sector2CHS(&partition->start_CHS, s->first_sectors_number - 1,
                     cyls, heads, secs);
    lba |= sector2CHS(&partition->end_CHS,   s->bs->total_sectors - 1,
                     cyls, heads, secs);

    /*LBA partitions are identified only by start/length_sector_long not by CHS*/
    partition->start_sector_long  = cpu_to_le32(s->first_sectors_number - 1);
    partition->length_sector_long=cpu_to_le32(s->sector_count - s->first_sectors_number+1);
    partition->length_sector_long = cpu_to_le32(s->bs->total_sectors
                                                - s->first_sectors_number + 1);

    /* FAT12/FAT16/FAT32 */
    /* DOS uses different types when partition is LBA,
@@ -830,7 +834,7 @@ static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num)
}

static int init_directories(BDRVVVFATState* s,
	const char* dirname)
                            const char *dirname, int heads, int secs)
{
    bootsector_t* bootsector;
    mapping_t* mapping;
@@ -957,8 +961,8 @@ static int init_directories(BDRVVVFATState* s,
    bootsector->media_type=(s->first_sectors_number>1?0xf8:0xf0); /* media descriptor (f8=hd, f0=3.5 fd)*/
    s->fat.pointer[0] = bootsector->media_type;
    bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
    bootsector->sectors_per_track=cpu_to_le16(s->bs->secs);
    bootsector->number_of_heads=cpu_to_le16(s->bs->heads);
    bootsector->sectors_per_track = cpu_to_le16(secs);
    bootsector->number_of_heads = cpu_to_le16(heads);
    bootsector->hidden_sectors=cpu_to_le32(s->first_sectors_number==1?0:0x3f);
    bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0);

@@ -991,7 +995,7 @@ static void vvfat_rebind(BlockDriverState *bs)
static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
{
    BDRVVVFATState *s = bs->opaque;
    int i;
    int i, cyls, heads, secs;

#ifdef DEBUG
    vvv = s;
@@ -1033,24 +1037,28 @@ DLOG(if (stderr == NULL) {
	/* 1.44MB or 2.88MB floppy.  2.88MB can be FAT12 (default) or FAT16. */
	if (!s->fat_type) {
	    s->fat_type = 12;
	    bs->secs = 36;
            secs = 36;
	    s->sectors_per_cluster=2;
	} else {
	    bs->secs=(s->fat_type == 12 ? 18 : 36);
            secs = s->fat_type == 12 ? 18 : 36;
	    s->sectors_per_cluster=1;
	}
	s->first_sectors_number = 1;
	bs->cyls=80; bs->heads=2;
        cyls = 80;
        heads = 2;
    } else {
	/* 32MB or 504MB disk*/
	if (!s->fat_type) {
	    s->fat_type = 16;
	}
	bs->cyls=(s->fat_type == 12 ? 64 : 1024);
	bs->heads=16; bs->secs=63;
        cyls = s->fat_type == 12 ? 64 : 1024;
        heads = 16;
        secs = 63;
    }
    fprintf(stderr, "vvfat %s chs %d,%d,%d\n",
            dirname, cyls, heads, secs);

    s->sector_count=bs->cyls*bs->heads*bs->secs-(s->first_sectors_number-1);
    s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);

    if (strstr(dirname, ":rw:")) {
	if (enable_write_target(s))
@@ -1066,18 +1074,16 @@ DLOG(if (stderr == NULL) {
    else
	dirname += i+1;

    bs->total_sectors=bs->cyls*bs->heads*bs->secs;
    bs->total_sectors = cyls * heads * secs;

    if(init_directories(s, dirname))
    if (init_directories(s, dirname, heads, secs)) {
	return -1;
    }

    s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;

    if(s->first_sectors_number==0x40)
	init_mbr(s);
    else {
        /* MS-DOS does not like to know about CHS (?). */
	bs->heads = bs->cyls = bs->secs = 0;
    if (s->first_sectors_number == 0x40) {
        init_mbr(s, cyls, heads, secs);
    }

    //    assert(is_consistent(s));
+0 −1
Original line number Diff line number Diff line
@@ -320,7 +320,6 @@ struct BlockDriverState {

    /* NOTE: the following infos are only hints for real hardware
       drivers. They are not used by the block driver */
    int cyls, heads, secs, translation;
    BlockErrorAction on_read_error, on_write_error;
    bool iostatus_enabled;
    BlockDeviceIoStatus iostatus;
Loading