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 ...
This commit is contained in:
		
						commit
						dfe1ce5d80
					
				
							
								
								
									
										254
									
								
								block.c
									
									
									
									
									
								
							
							
						
						
									
										254
									
								
								block.c
									
									
									
									
									
								
							@ -996,12 +996,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
 | 
				
			|||||||
    bs_dest->block_timer        = bs_src->block_timer;
 | 
					    bs_dest->block_timer        = bs_src->block_timer;
 | 
				
			||||||
    bs_dest->io_limits_enabled  = bs_src->io_limits_enabled;
 | 
					    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 */
 | 
					    /* r/w error */
 | 
				
			||||||
    bs_dest->on_read_error      = bs_src->on_read_error;
 | 
					    bs_dest->on_read_error      = bs_src->on_read_error;
 | 
				
			||||||
    bs_dest->on_write_error     = bs_src->on_write_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;
 | 
					    *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 */
 | 
					/* throttling disk io limits */
 | 
				
			||||||
void bdrv_set_io_limits(BlockDriverState *bs,
 | 
					void bdrv_set_io_limits(BlockDriverState *bs,
 | 
				
			||||||
                        BlockIOLimit *io_limits)
 | 
					                        BlockIOLimit *io_limits)
 | 
				
			||||||
@ -2282,112 +2134,6 @@ void bdrv_set_io_limits(BlockDriverState *bs,
 | 
				
			|||||||
    bs->io_limits_enabled = bdrv_io_limits_enabled(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,
 | 
					void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error,
 | 
				
			||||||
                       BlockErrorAction on_write_error)
 | 
					                       BlockErrorAction on_write_error)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										70
									
								
								block.h
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								block.h
									
									
									
									
									
								
							@ -178,7 +178,6 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset);
 | 
				
			|||||||
int64_t bdrv_getlength(BlockDriverState *bs);
 | 
					int64_t bdrv_getlength(BlockDriverState *bs);
 | 
				
			||||||
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
 | 
					int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
 | 
				
			||||||
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
 | 
					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(BlockDriverState *bs);
 | 
				
			||||||
int bdrv_commit_all(void);
 | 
					int bdrv_commit_all(void);
 | 
				
			||||||
int bdrv_change_backing_file(BlockDriverState *bs,
 | 
					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 bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
 | 
				
			||||||
                      int *pnum);
 | 
					                      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,
 | 
					void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error,
 | 
				
			||||||
                       BlockErrorAction on_write_error);
 | 
					                       BlockErrorAction on_write_error);
 | 
				
			||||||
BlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read);
 | 
					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)
 | 
					#define BLKDBG_EVENT(bs, evt) bdrv_debug_event(bs, evt)
 | 
				
			||||||
void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event);
 | 
					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
 | 
					#endif
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										150
									
								
								block/sheepdog.c
									
									
									
									
									
								
							
							
						
						
									
										150
									
								
								block/sheepdog.c
									
									
									
									
									
								
							@ -498,26 +498,6 @@ success:
 | 
				
			|||||||
    return fd;
 | 
					    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,
 | 
					static coroutine_fn int send_co_req(int sockfd, SheepdogReq *hdr, void *data,
 | 
				
			||||||
                                    unsigned int *wlen)
 | 
					                                    unsigned int *wlen)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -537,49 +517,6 @@ static coroutine_fn int send_co_req(int sockfd, SheepdogReq *hdr, void *data,
 | 
				
			|||||||
    return ret;
 | 
					    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)
 | 
					static void restart_co_req(void *opaque)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Coroutine *co = opaque;
 | 
					    Coroutine *co = opaque;
 | 
				
			||||||
@ -587,11 +524,26 @@ static void restart_co_req(void *opaque)
 | 
				
			|||||||
    qemu_coroutine_enter(co, NULL);
 | 
					    qemu_coroutine_enter(co, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static coroutine_fn int do_co_req(int sockfd, SheepdogReq *hdr, void *data,
 | 
					typedef struct SheepdogReqCo {
 | 
				
			||||||
                                  unsigned int *wlen, unsigned int *rlen)
 | 
					    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;
 | 
					    int ret;
 | 
				
			||||||
    Coroutine *co;
 | 
					    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();
 | 
					    co = qemu_coroutine_self();
 | 
				
			||||||
    qemu_aio_set_fd_handler(sockfd, NULL, restart_co_req, NULL, co);
 | 
					    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:
 | 
					out:
 | 
				
			||||||
    qemu_aio_set_fd_handler(sockfd, NULL, NULL, NULL, NULL);
 | 
					    qemu_aio_set_fd_handler(sockfd, NULL, NULL, NULL, NULL);
 | 
				
			||||||
    socket_set_nonblock(sockfd);
 | 
					    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,
 | 
					static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
 | 
				
			||||||
@ -1590,18 +1571,25 @@ static int coroutine_fn sd_co_rw_vector(void *p)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        len = MIN(total - done, SD_DATA_OBJ_SIZE - offset);
 | 
					        len = MIN(total - done, SD_DATA_OBJ_SIZE - offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!inode->data_vdi_id[idx]) {
 | 
					        switch (acb->aiocb_type) {
 | 
				
			||||||
            if (acb->aiocb_type == AIOCB_READ_UDATA) {
 | 
					        case AIOCB_READ_UDATA:
 | 
				
			||||||
 | 
					            if (!inode->data_vdi_id[idx]) {
 | 
				
			||||||
 | 
					                qemu_iovec_memset(acb->qiov, done, 0, len);
 | 
				
			||||||
                goto done;
 | 
					                goto done;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
            create = 1;
 | 
					        case AIOCB_WRITE_UDATA:
 | 
				
			||||||
        } else if (acb->aiocb_type == AIOCB_WRITE_UDATA
 | 
					            if (!inode->data_vdi_id[idx]) {
 | 
				
			||||||
                   && !is_data_obj_writable(inode, idx)) {
 | 
					                create = 1;
 | 
				
			||||||
            /* Copy-On-Write */
 | 
					            } else if (!is_data_obj_writable(inode, idx)) {
 | 
				
			||||||
            create = 1;
 | 
					                /* Copy-On-Write */
 | 
				
			||||||
            old_oid = oid;
 | 
					                create = 1;
 | 
				
			||||||
            flags = SD_FLAG_CMD_COW;
 | 
					                old_oid = oid;
 | 
				
			||||||
 | 
					                flags = SD_FLAG_CMD_COW;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (create) {
 | 
					        if (create) {
 | 
				
			||||||
@ -1687,20 +1675,12 @@ static coroutine_fn int sd_co_readv(BlockDriverState *bs, int64_t sector_num,
 | 
				
			|||||||
                       int nb_sectors, QEMUIOVector *qiov)
 | 
					                       int nb_sectors, QEMUIOVector *qiov)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    SheepdogAIOCB *acb;
 | 
					    SheepdogAIOCB *acb;
 | 
				
			||||||
    int i, ret;
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors, NULL, NULL);
 | 
					    acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors, NULL, NULL);
 | 
				
			||||||
    acb->aiocb_type = AIOCB_READ_UDATA;
 | 
					    acb->aiocb_type = AIOCB_READ_UDATA;
 | 
				
			||||||
    acb->aio_done_func = sd_finish_aiocb;
 | 
					    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);
 | 
					    ret = sd_co_rw_vector(acb);
 | 
				
			||||||
    if (ret <= 0) {
 | 
					    if (ret <= 0) {
 | 
				
			||||||
        qemu_aio_release(acb);
 | 
					        qemu_aio_release(acb);
 | 
				
			||||||
 | 
				
			|||||||
@ -359,11 +359,12 @@ typedef struct BDRVVVFATState {
 | 
				
			|||||||
 * if the position is outside the specified geometry, fill maximum value for CHS
 | 
					 * if the position is outside the specified geometry, fill maximum value for CHS
 | 
				
			||||||
 * and return 1 to signal overflow.
 | 
					 * 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;
 | 
					    int head,sector;
 | 
				
			||||||
    sector   = spos % (bs->secs);  spos/= bs->secs;
 | 
					    sector   = spos % secs;  spos /= secs;
 | 
				
			||||||
    head     = spos % (bs->heads); spos/= bs->heads;
 | 
					    head     = spos % heads; spos /= heads;
 | 
				
			||||||
    if(spos >= bs->cyls){
 | 
					    if (spos >= cyls) {
 | 
				
			||||||
        /* Overflow,
 | 
					        /* Overflow,
 | 
				
			||||||
        it happens if 32bit sector positions are used, while CHS is only 24bit.
 | 
					        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 */
 | 
					        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;
 | 
					    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 */
 | 
					    /* TODO: if the files mbr.img and bootsect.img exist, use them */
 | 
				
			||||||
    mbr_t* real_mbr=(mbr_t*)s->first_sectors;
 | 
					    mbr_t* real_mbr=(mbr_t*)s->first_sectors;
 | 
				
			||||||
@ -393,12 +394,15 @@ static void init_mbr(BDRVVVFATState* s)
 | 
				
			|||||||
    partition->attributes=0x80; /* bootable */
 | 
					    partition->attributes=0x80; /* bootable */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* LBA is used when partition is outside the CHS geometry */
 | 
					    /* LBA is used when partition is outside the CHS geometry */
 | 
				
			||||||
    lba = sector2CHS(s->bs, &partition->start_CHS, s->first_sectors_number-1);
 | 
					    lba  = sector2CHS(&partition->start_CHS, s->first_sectors_number - 1,
 | 
				
			||||||
    lba|= sector2CHS(s->bs, &partition->end_CHS,   s->sector_count);
 | 
					                     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*/
 | 
					    /*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->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 */
 | 
					    /* FAT12/FAT16/FAT32 */
 | 
				
			||||||
    /* DOS uses different types when partition is LBA,
 | 
					    /* 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,
 | 
					static int init_directories(BDRVVVFATState* s,
 | 
				
			||||||
	const char* dirname)
 | 
					                            const char *dirname, int heads, int secs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    bootsector_t* bootsector;
 | 
					    bootsector_t* bootsector;
 | 
				
			||||||
    mapping_t* mapping;
 | 
					    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)*/
 | 
					    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;
 | 
					    s->fat.pointer[0] = bootsector->media_type;
 | 
				
			||||||
    bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
 | 
					    bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
 | 
				
			||||||
    bootsector->sectors_per_track=cpu_to_le16(s->bs->secs);
 | 
					    bootsector->sectors_per_track = cpu_to_le16(secs);
 | 
				
			||||||
    bootsector->number_of_heads=cpu_to_le16(s->bs->heads);
 | 
					    bootsector->number_of_heads = cpu_to_le16(heads);
 | 
				
			||||||
    bootsector->hidden_sectors=cpu_to_le32(s->first_sectors_number==1?0:0x3f);
 | 
					    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);
 | 
					    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)
 | 
					static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    BDRVVVFATState *s = bs->opaque;
 | 
					    BDRVVVFATState *s = bs->opaque;
 | 
				
			||||||
    int i;
 | 
					    int i, cyls, heads, secs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef DEBUG
 | 
					#ifdef DEBUG
 | 
				
			||||||
    vvv = s;
 | 
					    vvv = s;
 | 
				
			||||||
@ -1033,24 +1037,28 @@ DLOG(if (stderr == NULL) {
 | 
				
			|||||||
	/* 1.44MB or 2.88MB floppy.  2.88MB can be FAT12 (default) or FAT16. */
 | 
						/* 1.44MB or 2.88MB floppy.  2.88MB can be FAT12 (default) or FAT16. */
 | 
				
			||||||
	if (!s->fat_type) {
 | 
						if (!s->fat_type) {
 | 
				
			||||||
	    s->fat_type = 12;
 | 
						    s->fat_type = 12;
 | 
				
			||||||
	    bs->secs = 36;
 | 
					            secs = 36;
 | 
				
			||||||
	    s->sectors_per_cluster=2;
 | 
						    s->sectors_per_cluster=2;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
	    bs->secs=(s->fat_type == 12 ? 18 : 36);
 | 
					            secs = s->fat_type == 12 ? 18 : 36;
 | 
				
			||||||
	    s->sectors_per_cluster=1;
 | 
						    s->sectors_per_cluster=1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	s->first_sectors_number = 1;
 | 
						s->first_sectors_number = 1;
 | 
				
			||||||
	bs->cyls=80; bs->heads=2;
 | 
					        cyls = 80;
 | 
				
			||||||
 | 
					        heads = 2;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
	/* 32MB or 504MB disk*/
 | 
						/* 32MB or 504MB disk*/
 | 
				
			||||||
	if (!s->fat_type) {
 | 
						if (!s->fat_type) {
 | 
				
			||||||
	    s->fat_type = 16;
 | 
						    s->fat_type = 16;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	bs->cyls=(s->fat_type == 12 ? 64 : 1024);
 | 
					        cyls = s->fat_type == 12 ? 64 : 1024;
 | 
				
			||||||
	bs->heads=16; bs->secs=63;
 | 
					        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 (strstr(dirname, ":rw:")) {
 | 
				
			||||||
	if (enable_write_target(s))
 | 
						if (enable_write_target(s))
 | 
				
			||||||
@ -1066,18 +1074,16 @@ DLOG(if (stderr == NULL) {
 | 
				
			|||||||
    else
 | 
					    else
 | 
				
			||||||
	dirname += i+1;
 | 
						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;
 | 
						return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
 | 
					    s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(s->first_sectors_number==0x40)
 | 
					    if (s->first_sectors_number == 0x40) {
 | 
				
			||||||
	init_mbr(s);
 | 
					        init_mbr(s, cyls, heads, secs);
 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
        /* MS-DOS does not like to know about CHS (?). */
 | 
					 | 
				
			||||||
	bs->heads = bs->cyls = bs->secs = 0;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //    assert(is_consistent(s));
 | 
					    //    assert(is_consistent(s));
 | 
				
			||||||
 | 
				
			|||||||
@ -320,7 +320,6 @@ struct BlockDriverState {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* NOTE: the following infos are only hints for real hardware
 | 
					    /* NOTE: the following infos are only hints for real hardware
 | 
				
			||||||
       drivers. They are not used by the block driver */
 | 
					       drivers. They are not used by the block driver */
 | 
				
			||||||
    int cyls, heads, secs, translation;
 | 
					 | 
				
			||||||
    BlockErrorAction on_read_error, on_write_error;
 | 
					    BlockErrorAction on_read_error, on_write_error;
 | 
				
			||||||
    bool iostatus_enabled;
 | 
					    bool iostatus_enabled;
 | 
				
			||||||
    BlockDeviceIoStatus iostatus;
 | 
					    BlockDeviceIoStatus iostatus;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										28
									
								
								blockdev.c
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								blockdev.c
									
									
									
									
									
								
							@ -7,8 +7,8 @@
 | 
				
			|||||||
 * later.  See the COPYING file in the top-level directory.
 | 
					 * later.  See the COPYING file in the top-level directory.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "block.h"
 | 
					 | 
				
			||||||
#include "blockdev.h"
 | 
					#include "blockdev.h"
 | 
				
			||||||
 | 
					#include "hw/block-common.h"
 | 
				
			||||||
#include "monitor.h"
 | 
					#include "monitor.h"
 | 
				
			||||||
#include "qerror.h"
 | 
					#include "qerror.h"
 | 
				
			||||||
#include "qemu-option.h"
 | 
					#include "qemu-option.h"
 | 
				
			||||||
@ -330,15 +330,15 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
 | 
				
			|||||||
    max_devs = if_max_devs[type];
 | 
					    max_devs = if_max_devs[type];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (cyls || heads || secs) {
 | 
					    if (cyls || heads || secs) {
 | 
				
			||||||
        if (cyls < 1 || (type == IF_IDE && cyls > 16383)) {
 | 
					        if (cyls < 1) {
 | 
				
			||||||
            error_report("invalid physical cyls number");
 | 
					            error_report("invalid physical cyls number");
 | 
				
			||||||
	    return NULL;
 | 
						    return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
        if (heads < 1 || (type == IF_IDE && heads > 16)) {
 | 
					        if (heads < 1) {
 | 
				
			||||||
            error_report("invalid physical heads number");
 | 
					            error_report("invalid physical heads number");
 | 
				
			||||||
	    return NULL;
 | 
						    return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
        if (secs < 1 || (type == IF_IDE && secs > 63)) {
 | 
					        if (secs < 1) {
 | 
				
			||||||
            error_report("invalid physical secs number");
 | 
					            error_report("invalid physical secs number");
 | 
				
			||||||
	    return NULL;
 | 
						    return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -530,11 +530,13 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
 | 
				
			|||||||
    dinfo->type = type;
 | 
					    dinfo->type = type;
 | 
				
			||||||
    dinfo->bus = bus_id;
 | 
					    dinfo->bus = bus_id;
 | 
				
			||||||
    dinfo->unit = unit_id;
 | 
					    dinfo->unit = unit_id;
 | 
				
			||||||
 | 
					    dinfo->cyls = cyls;
 | 
				
			||||||
 | 
					    dinfo->heads = heads;
 | 
				
			||||||
 | 
					    dinfo->secs = secs;
 | 
				
			||||||
 | 
					    dinfo->trans = translation;
 | 
				
			||||||
    dinfo->opts = opts;
 | 
					    dinfo->opts = opts;
 | 
				
			||||||
    dinfo->refcount = 1;
 | 
					    dinfo->refcount = 1;
 | 
				
			||||||
    if (serial) {
 | 
					    dinfo->serial = serial;
 | 
				
			||||||
        pstrcpy(dinfo->serial, sizeof(dinfo->serial), serial);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    QTAILQ_INSERT_TAIL(&drives, dinfo, next);
 | 
					    QTAILQ_INSERT_TAIL(&drives, dinfo, next);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error);
 | 
					    bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error);
 | 
				
			||||||
@ -547,17 +549,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
 | 
				
			|||||||
    case IF_SCSI:
 | 
					    case IF_SCSI:
 | 
				
			||||||
    case IF_XEN:
 | 
					    case IF_XEN:
 | 
				
			||||||
    case IF_NONE:
 | 
					    case IF_NONE:
 | 
				
			||||||
        switch(media) {
 | 
					        dinfo->media_cd = media == MEDIA_CDROM;
 | 
				
			||||||
	case MEDIA_DISK:
 | 
					 | 
				
			||||||
            if (cyls != 0) {
 | 
					 | 
				
			||||||
                bdrv_set_geometry_hint(dinfo->bdrv, cyls, heads, secs);
 | 
					 | 
				
			||||||
                bdrv_set_translation_hint(dinfo->bdrv, translation);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
	    break;
 | 
					 | 
				
			||||||
	case MEDIA_CDROM:
 | 
					 | 
				
			||||||
            dinfo->media_cd = 1;
 | 
					 | 
				
			||||||
	    break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case IF_SD:
 | 
					    case IF_SD:
 | 
				
			||||||
    case IF_FLOPPY:
 | 
					    case IF_FLOPPY:
 | 
				
			||||||
 | 
				
			|||||||
@ -17,8 +17,6 @@
 | 
				
			|||||||
void blockdev_mark_auto_del(BlockDriverState *bs);
 | 
					void blockdev_mark_auto_del(BlockDriverState *bs);
 | 
				
			||||||
void blockdev_auto_del(BlockDriverState *bs);
 | 
					void blockdev_auto_del(BlockDriverState *bs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define BLOCK_SERIAL_STRLEN 20
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    IF_DEFAULT = -1,            /* for use with drive_add() only */
 | 
					    IF_DEFAULT = -1,            /* for use with drive_add() only */
 | 
				
			||||||
    IF_NONE,
 | 
					    IF_NONE,
 | 
				
			||||||
@ -35,8 +33,9 @@ struct DriveInfo {
 | 
				
			|||||||
    int unit;
 | 
					    int unit;
 | 
				
			||||||
    int auto_del;               /* see blockdev_mark_auto_del() */
 | 
					    int auto_del;               /* see blockdev_mark_auto_del() */
 | 
				
			||||||
    int media_cd;
 | 
					    int media_cd;
 | 
				
			||||||
 | 
					    int cyls, heads, secs, trans;
 | 
				
			||||||
    QemuOpts *opts;
 | 
					    QemuOpts *opts;
 | 
				
			||||||
    char serial[BLOCK_SERIAL_STRLEN + 1];
 | 
					    const char *serial;
 | 
				
			||||||
    QTAILQ_ENTRY(DriveInfo) next;
 | 
					    QTAILQ_ENTRY(DriveInfo) next;
 | 
				
			||||||
    int refcount;
 | 
					    int refcount;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										20
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								configure
									
									
									
									
										vendored
									
									
								
							@ -2870,6 +2870,22 @@ if compile_prog "" "" ; then
 | 
				
			|||||||
    linux_magic_h=yes
 | 
					    linux_magic_h=yes
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					########################################
 | 
				
			||||||
 | 
					# check if we have valgrind/valgrind.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					valgrind_h=no
 | 
				
			||||||
 | 
					cat > $TMPC << EOF
 | 
				
			||||||
 | 
					#include <valgrind/valgrind.h>
 | 
				
			||||||
 | 
					#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 | 
				
			||||||
 | 
					int main(void) {
 | 
				
			||||||
 | 
					  VALGRIND_STACK_DEREGISTER(0);
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
					if compile_prog "" "" ; then
 | 
				
			||||||
 | 
					    valgrind_h=yes
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
########################################
 | 
					########################################
 | 
				
			||||||
# check if environ is declared
 | 
					# check if environ is declared
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -3379,6 +3395,10 @@ if test "$linux_magic_h" = "yes" ; then
 | 
				
			|||||||
  echo "CONFIG_LINUX_MAGIC_H=y" >> $config_host_mak
 | 
					  echo "CONFIG_LINUX_MAGIC_H=y" >> $config_host_mak
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if test "$valgrind_h" = "yes" ; then
 | 
				
			||||||
 | 
					  echo "CONFIG_VALGRIND_H=y" >> $config_host_mak
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if test "$has_environ" = "yes" ; then
 | 
					if test "$has_environ" = "yes" ; then
 | 
				
			||||||
  echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak
 | 
					  echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
				
			|||||||
@ -30,6 +30,10 @@
 | 
				
			|||||||
#include "qemu-common.h"
 | 
					#include "qemu-common.h"
 | 
				
			||||||
#include "qemu-coroutine-int.h"
 | 
					#include "qemu-coroutine-int.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_VALGRIND_H
 | 
				
			||||||
 | 
					#include <valgrind/valgrind.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
    /* Maximum free pool size prevents holding too many freed coroutines */
 | 
					    /* Maximum free pool size prevents holding too many freed coroutines */
 | 
				
			||||||
    POOL_MAX_SIZE = 64,
 | 
					    POOL_MAX_SIZE = 64,
 | 
				
			||||||
@ -43,6 +47,11 @@ typedef struct {
 | 
				
			|||||||
    Coroutine base;
 | 
					    Coroutine base;
 | 
				
			||||||
    void *stack;
 | 
					    void *stack;
 | 
				
			||||||
    jmp_buf env;
 | 
					    jmp_buf env;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_VALGRIND_H
 | 
				
			||||||
 | 
					    unsigned int valgrind_stack_id;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} CoroutineUContext;
 | 
					} CoroutineUContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -159,6 +168,11 @@ static Coroutine *coroutine_new(void)
 | 
				
			|||||||
    uc.uc_stack.ss_size = stack_size;
 | 
					    uc.uc_stack.ss_size = stack_size;
 | 
				
			||||||
    uc.uc_stack.ss_flags = 0;
 | 
					    uc.uc_stack.ss_flags = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_VALGRIND_H
 | 
				
			||||||
 | 
					    co->valgrind_stack_id =
 | 
				
			||||||
 | 
					        VALGRIND_STACK_REGISTER(co->stack, co->stack + stack_size);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    arg.p = co;
 | 
					    arg.p = co;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    makecontext(&uc, (void (*)(void))coroutine_trampoline,
 | 
					    makecontext(&uc, (void (*)(void))coroutine_trampoline,
 | 
				
			||||||
@ -185,6 +199,16 @@ Coroutine *qemu_coroutine_new(void)
 | 
				
			|||||||
    return co;
 | 
					    return co;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_VALGRIND_H
 | 
				
			||||||
 | 
					/* Work around an unused variable in the valgrind.h macro... */
 | 
				
			||||||
 | 
					#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 | 
				
			||||||
 | 
					static inline void valgrind_stack_deregister(CoroutineUContext *co)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VALGRIND_STACK_DEREGISTER(co->valgrind_stack_id);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#pragma GCC diagnostic error "-Wunused-but-set-variable"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void qemu_coroutine_delete(Coroutine *co_)
 | 
					void qemu_coroutine_delete(Coroutine *co_)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_);
 | 
					    CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_);
 | 
				
			||||||
@ -196,6 +220,10 @@ void qemu_coroutine_delete(Coroutine *co_)
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_VALGRIND_H
 | 
				
			||||||
 | 
					    valgrind_stack_deregister(co);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_free(co->stack);
 | 
					    g_free(co->stack);
 | 
				
			||||||
    g_free(co);
 | 
					    g_free(co);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -138,7 +138,7 @@ common-obj-$(CONFIG_MAX111X) += max111x.o
 | 
				
			|||||||
common-obj-$(CONFIG_DS1338) += ds1338.o
 | 
					common-obj-$(CONFIG_DS1338) += ds1338.o
 | 
				
			||||||
common-obj-y += i2c.o smbus.o smbus_eeprom.o
 | 
					common-obj-y += i2c.o smbus.o smbus_eeprom.o
 | 
				
			||||||
common-obj-y += eeprom93xx.o
 | 
					common-obj-y += eeprom93xx.o
 | 
				
			||||||
common-obj-y += scsi-disk.o cdrom.o
 | 
					common-obj-y += scsi-disk.o cdrom.o hd-geometry.o block-common.o
 | 
				
			||||||
common-obj-y += scsi-generic.o scsi-bus.o
 | 
					common-obj-y += scsi-generic.o scsi-bus.o
 | 
				
			||||||
common-obj-y += hid.o
 | 
					common-obj-y += hid.o
 | 
				
			||||||
common-obj-$(CONFIG_SSI) += ssi.o
 | 
					common-obj-$(CONFIG_SSI) += ssi.o
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										64
									
								
								hw/block-common.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								hw/block-common.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Common code for block device models
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2012 Red Hat, Inc.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This work is licensed under the terms of the GNU GPL, version 2 or
 | 
				
			||||||
 | 
					 * later.  See the COPYING file in the top-level directory.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "blockdev.h"
 | 
				
			||||||
 | 
					#include "hw/block-common.h"
 | 
				
			||||||
 | 
					#include "qemu-error.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void blkconf_serial(BlockConf *conf, char **serial)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    DriveInfo *dinfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!*serial) {
 | 
				
			||||||
 | 
					        /* try to fall back to value set with legacy -drive serial=... */
 | 
				
			||||||
 | 
					        dinfo = drive_get_by_blockdev(conf->bs);
 | 
				
			||||||
 | 
					        if (dinfo->serial) {
 | 
				
			||||||
 | 
					            *serial = g_strdup(dinfo->serial);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int blkconf_geometry(BlockConf *conf, int *ptrans,
 | 
				
			||||||
 | 
					                     unsigned cyls_max, unsigned heads_max, unsigned secs_max)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    DriveInfo *dinfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!conf->cyls && !conf->heads && !conf->secs) {
 | 
				
			||||||
 | 
					        /* try to fall back to value set with legacy -drive cyls=... */
 | 
				
			||||||
 | 
					        dinfo = drive_get_by_blockdev(conf->bs);
 | 
				
			||||||
 | 
					        conf->cyls  = dinfo->cyls;
 | 
				
			||||||
 | 
					        conf->heads = dinfo->heads;
 | 
				
			||||||
 | 
					        conf->secs  = dinfo->secs;
 | 
				
			||||||
 | 
					        if (ptrans) {
 | 
				
			||||||
 | 
					            *ptrans = dinfo->trans;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!conf->cyls && !conf->heads && !conf->secs) {
 | 
				
			||||||
 | 
					        hd_geometry_guess(conf->bs,
 | 
				
			||||||
 | 
					                          &conf->cyls, &conf->heads, &conf->secs,
 | 
				
			||||||
 | 
					                          ptrans);
 | 
				
			||||||
 | 
					    } else if (ptrans && *ptrans == BIOS_ATA_TRANSLATION_AUTO) {
 | 
				
			||||||
 | 
					        *ptrans = hd_bios_chs_auto_trans(conf->cyls, conf->heads, conf->secs);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (conf->cyls || conf->heads || conf->secs) {
 | 
				
			||||||
 | 
					        if (conf->cyls < 1 || conf->cyls > cyls_max) {
 | 
				
			||||||
 | 
					            error_report("cyls must be between 1 and %u", cyls_max);
 | 
				
			||||||
 | 
					            return -1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (conf->heads < 1 || conf->heads > heads_max) {
 | 
				
			||||||
 | 
					            error_report("heads must be between 1 and %u", heads_max);
 | 
				
			||||||
 | 
					            return -1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (conf->secs < 1 || conf->secs > secs_max) {
 | 
				
			||||||
 | 
					            error_report("secs must be between 1 and %u", secs_max);
 | 
				
			||||||
 | 
					            return -1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										79
									
								
								hw/block-common.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								hw/block-common.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,79 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Common code for block device models
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2012 Red Hat, Inc.
 | 
				
			||||||
 | 
					 * Copyright (c) 2003-2008 Fabrice Bellard
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This work is licensed under the terms of the GNU GPL, version 2 or
 | 
				
			||||||
 | 
					 * later.  See the COPYING file in the top-level directory.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef HW_BLOCK_COMMON_H
 | 
				
			||||||
 | 
					#define HW_BLOCK_COMMON_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "qemu-common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Configuration */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					    /* geometry, not all devices use this */
 | 
				
			||||||
 | 
					    uint32_t cyls, heads, secs;
 | 
				
			||||||
 | 
					} 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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DEFINE_BLOCK_CHS_PROPERTIES(_state, _conf)      \
 | 
				
			||||||
 | 
					    DEFINE_PROP_UINT32("cyls", _state, _conf.cyls, 0),  \
 | 
				
			||||||
 | 
					    DEFINE_PROP_UINT32("heads", _state, _conf.heads, 0), \
 | 
				
			||||||
 | 
					    DEFINE_PROP_UINT32("secs", _state, _conf.secs, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Configuration helpers */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void blkconf_serial(BlockConf *conf, char **serial);
 | 
				
			||||||
 | 
					int blkconf_geometry(BlockConf *conf, int *trans,
 | 
				
			||||||
 | 
					                     unsigned cyls_max, unsigned heads_max, unsigned secs_max);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Hard disk geometry */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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 hd_geometry_guess(BlockDriverState *bs,
 | 
				
			||||||
 | 
					                       uint32_t *pcyls, uint32_t *pheads, uint32_t *psecs,
 | 
				
			||||||
 | 
					                       int *ptrans);
 | 
				
			||||||
 | 
					int hd_bios_chs_auto_trans(uint32_t cyls, uint32_t heads, uint32_t secs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										132
									
								
								hw/fdc.c
									
									
									
									
									
								
							
							
						
						
									
										132
									
								
								hw/fdc.c
									
									
									
									
									
								
							@ -52,6 +52,113 @@
 | 
				
			|||||||
/********************************************************/
 | 
					/********************************************************/
 | 
				
			||||||
/* Floppy drive emulation                               */
 | 
					/* Floppy drive emulation                               */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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, },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void pick_geometry(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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define GET_CUR_DRV(fdctrl) ((fdctrl)->cur_drv)
 | 
					#define GET_CUR_DRV(fdctrl) ((fdctrl)->cur_drv)
 | 
				
			||||||
#define SET_CUR_DRV(fdctrl, drive) ((fdctrl)->cur_drv = (drive))
 | 
					#define SET_CUR_DRV(fdctrl, drive) ((fdctrl)->cur_drv = (drive))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -187,8 +294,8 @@ static void fd_revalidate(FDrive *drv)
 | 
				
			|||||||
    FLOPPY_DPRINTF("revalidate\n");
 | 
					    FLOPPY_DPRINTF("revalidate\n");
 | 
				
			||||||
    if (drv->bs != NULL) {
 | 
					    if (drv->bs != NULL) {
 | 
				
			||||||
        ro = bdrv_is_read_only(drv->bs);
 | 
					        ro = bdrv_is_read_only(drv->bs);
 | 
				
			||||||
        bdrv_get_floppy_geometry_hint(drv->bs, &nb_heads, &max_track,
 | 
					        pick_geometry(drv->bs, &nb_heads, &max_track,
 | 
				
			||||||
                                      &last_sect, drv->drive, &drive, &rate);
 | 
					                      &last_sect, drv->drive, &drive, &rate);
 | 
				
			||||||
        if (!bdrv_is_inserted(drv->bs)) {
 | 
					        if (!bdrv_is_inserted(drv->bs)) {
 | 
				
			||||||
            FLOPPY_DPRINTF("No disk in drive\n");
 | 
					            FLOPPY_DPRINTF("No disk in drive\n");
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
@ -1695,7 +1802,7 @@ static void fdctrl_handle_drive_specification_command(FDCtrl *fdctrl, int direct
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void fdctrl_handle_relative_seek_out(FDCtrl *fdctrl, int direction)
 | 
					static void fdctrl_handle_relative_seek_in(FDCtrl *fdctrl, int direction)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    FDrive *cur_drv;
 | 
					    FDrive *cur_drv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1705,14 +1812,15 @@ static void fdctrl_handle_relative_seek_out(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
        fd_seek(cur_drv, cur_drv->head, cur_drv->max_track - 1,
 | 
					        fd_seek(cur_drv, cur_drv->head, cur_drv->max_track - 1,
 | 
				
			||||||
                cur_drv->sect, 1);
 | 
					                cur_drv->sect, 1);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        fd_seek(cur_drv, cur_drv->head, fdctrl->fifo[2], cur_drv->sect, 1);
 | 
					        fd_seek(cur_drv, cur_drv->head,
 | 
				
			||||||
 | 
					                cur_drv->track + fdctrl->fifo[2], cur_drv->sect, 1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fdctrl_reset_fifo(fdctrl);
 | 
					    fdctrl_reset_fifo(fdctrl);
 | 
				
			||||||
    /* Raise Interrupt */
 | 
					    /* Raise Interrupt */
 | 
				
			||||||
    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
 | 
					    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void fdctrl_handle_relative_seek_in(FDCtrl *fdctrl, int direction)
 | 
					static void fdctrl_handle_relative_seek_out(FDCtrl *fdctrl, int direction)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    FDrive *cur_drv;
 | 
					    FDrive *cur_drv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1721,7 +1829,8 @@ static void fdctrl_handle_relative_seek_in(FDCtrl *fdctrl, int direction)
 | 
				
			|||||||
    if (fdctrl->fifo[2] > cur_drv->track) {
 | 
					    if (fdctrl->fifo[2] > cur_drv->track) {
 | 
				
			||||||
        fd_seek(cur_drv, cur_drv->head, 0, cur_drv->sect, 1);
 | 
					        fd_seek(cur_drv, cur_drv->head, 0, cur_drv->sect, 1);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        fd_seek(cur_drv, cur_drv->head, fdctrl->fifo[2], cur_drv->sect, 1);
 | 
					        fd_seek(cur_drv, cur_drv->head,
 | 
				
			||||||
 | 
					                cur_drv->track - fdctrl->fifo[2], cur_drv->sect, 1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fdctrl_reset_fifo(fdctrl);
 | 
					    fdctrl_reset_fifo(fdctrl);
 | 
				
			||||||
    /* Raise Interrupt */
 | 
					    /* Raise Interrupt */
 | 
				
			||||||
@ -2054,18 +2163,13 @@ static int sun4m_fdc_init1(SysBusDevice *dev)
 | 
				
			|||||||
    return fdctrl_init_common(fdctrl);
 | 
					    return fdctrl_init_common(fdctrl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void fdc_get_bs(BlockDriverState *bs[], ISADevice *dev)
 | 
					FDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    FDCtrlISABus *isa = DO_UPCAST(FDCtrlISABus, busdev, dev);
 | 
					    FDCtrlISABus *isa = DO_UPCAST(FDCtrlISABus, busdev, fdc);
 | 
				
			||||||
    FDCtrl *fdctrl = &isa->state;
 | 
					 | 
				
			||||||
    int i;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < MAX_FD; i++) {
 | 
					    return isa->state.drives[i].drive;
 | 
				
			||||||
        bs[i] = fdctrl->drives[i].bs;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
static const VMStateDescription vmstate_isa_fdc ={
 | 
					static const VMStateDescription vmstate_isa_fdc ={
 | 
				
			||||||
    .name = "fdc",
 | 
					    .name = "fdc",
 | 
				
			||||||
    .version_id = 2,
 | 
					    .version_id = 2,
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										10
									
								
								hw/fdc.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								hw/fdc.h
									
									
									
									
									
								
							@ -6,11 +6,19 @@
 | 
				
			|||||||
/* fdc.c */
 | 
					/* fdc.c */
 | 
				
			||||||
#define MAX_FD 2
 | 
					#define MAX_FD 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds);
 | 
					ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds);
 | 
				
			||||||
void fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
 | 
					void fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
 | 
				
			||||||
                        target_phys_addr_t mmio_base, DriveInfo **fds);
 | 
					                        target_phys_addr_t mmio_base, DriveInfo **fds);
 | 
				
			||||||
void sun4m_fdctrl_init(qemu_irq irq, target_phys_addr_t io_base,
 | 
					void sun4m_fdctrl_init(qemu_irq irq, target_phys_addr_t io_base,
 | 
				
			||||||
                       DriveInfo **fds, qemu_irq *fdc_tc);
 | 
					                       DriveInfo **fds, qemu_irq *fdc_tc);
 | 
				
			||||||
void fdc_get_bs(BlockDriverState *bs[], ISADevice *dev);
 | 
					
 | 
				
			||||||
 | 
					FDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										157
									
								
								hw/hd-geometry.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								hw/hd-geometry.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,157 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Hard disk geometry utilities
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2012 Red Hat, Inc.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 | 
				
			||||||
 | 
					 * See the COPYING file in the top-level directory.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This file incorporates work covered by the following copyright and
 | 
				
			||||||
 | 
					 * permission notice:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (c) 2003 Fabrice Bellard
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					 * of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					 * in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					 * copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					 * furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The above copyright notice and this permission notice shall be included in
 | 
				
			||||||
 | 
					 * all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
				
			||||||
 | 
					 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
				
			||||||
 | 
					 * THE SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "block.h"
 | 
				
			||||||
 | 
					#include "hw/block-common.h"
 | 
				
			||||||
 | 
					#include "trace.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					            trace_hd_geometry_lchs_guess(bs, cylinders, heads, sectors);
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void guess_chs_for_size(BlockDriverState *bs,
 | 
				
			||||||
 | 
					                uint32_t *pcyls, uint32_t *pheads, uint32_t *psecs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint64_t nb_sectors;
 | 
				
			||||||
 | 
					    int cylinders;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bdrv_get_geometry(bs, &nb_sectors);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cylinders = nb_sectors / (16 * 63);
 | 
				
			||||||
 | 
					    if (cylinders > 16383) {
 | 
				
			||||||
 | 
					        cylinders = 16383;
 | 
				
			||||||
 | 
					    } else if (cylinders < 2) {
 | 
				
			||||||
 | 
					        cylinders = 2;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    *pcyls = cylinders;
 | 
				
			||||||
 | 
					    *pheads = 16;
 | 
				
			||||||
 | 
					    *psecs = 63;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void hd_geometry_guess(BlockDriverState *bs,
 | 
				
			||||||
 | 
					                       uint32_t *pcyls, uint32_t *pheads, uint32_t *psecs,
 | 
				
			||||||
 | 
					                       int *ptrans)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int cylinders, heads, secs, translation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (guess_disk_lchs(bs, &cylinders, &heads, &secs) < 0) {
 | 
				
			||||||
 | 
					        /* no LCHS guess: use a standard physical disk geometry  */
 | 
				
			||||||
 | 
					        guess_chs_for_size(bs, pcyls, pheads, psecs);
 | 
				
			||||||
 | 
					        translation = hd_bios_chs_auto_trans(*pcyls, *pheads, *psecs);
 | 
				
			||||||
 | 
					    } else if (heads > 16) {
 | 
				
			||||||
 | 
					        /* LCHS guess with heads > 16 means that a BIOS LBA
 | 
				
			||||||
 | 
					           translation was active, so a standard physical disk
 | 
				
			||||||
 | 
					           geometry is OK */
 | 
				
			||||||
 | 
					        guess_chs_for_size(bs, pcyls, pheads, psecs);
 | 
				
			||||||
 | 
					        translation = *pcyls * *pheads <= 131072
 | 
				
			||||||
 | 
					            ? BIOS_ATA_TRANSLATION_LARGE
 | 
				
			||||||
 | 
					            : BIOS_ATA_TRANSLATION_LBA;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        /* LCHS guess with heads <= 16: use as physical geometry */
 | 
				
			||||||
 | 
					        *pcyls = cylinders;
 | 
				
			||||||
 | 
					        *pheads = heads;
 | 
				
			||||||
 | 
					        *psecs = secs;
 | 
				
			||||||
 | 
					        /* disable any translation to be in sync with
 | 
				
			||||||
 | 
					           the logical geometry */
 | 
				
			||||||
 | 
					        translation = BIOS_ATA_TRANSLATION_NONE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (ptrans) {
 | 
				
			||||||
 | 
					        *ptrans = translation;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    trace_hd_geometry_guess(bs, *pcyls, *pheads, *psecs, translation);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int hd_bios_chs_auto_trans(uint32_t cyls, uint32_t heads, uint32_t secs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return cyls <= 1024 && heads <= 16 && secs <= 63
 | 
				
			||||||
 | 
					        ? BIOS_ATA_TRANSLATION_NONE
 | 
				
			||||||
 | 
					        : BIOS_ATA_TRANSLATION_LBA;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										4
									
								
								hw/ide.h
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								hw/ide.h
									
									
									
									
									
								
							@ -29,7 +29,9 @@ void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2,
 | 
				
			|||||||
                    qemu_irq irq, int shift,
 | 
					                    qemu_irq irq, int shift,
 | 
				
			||||||
                    DriveInfo *hd0, DriveInfo *hd1);
 | 
					                    DriveInfo *hd0, DriveInfo *hd1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ide_get_bs(BlockDriverState *bs[], BusState *qbus);
 | 
					int ide_get_geometry(BusState *bus, int unit,
 | 
				
			||||||
 | 
					                     int16_t *cyls, int8_t *heads, int8_t *secs);
 | 
				
			||||||
 | 
					int ide_get_bios_chs_trans(BusState *bus, int unit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ide/core.c */
 | 
					/* ide/core.c */
 | 
				
			||||||
void ide_drive_get(DriveInfo **hd, int max_bus);
 | 
					void ide_drive_get(DriveInfo **hd, int max_bus);
 | 
				
			||||||
 | 
				
			|||||||
@ -30,6 +30,7 @@
 | 
				
			|||||||
#include "qemu-timer.h"
 | 
					#include "qemu-timer.h"
 | 
				
			||||||
#include "sysemu.h"
 | 
					#include "sysemu.h"
 | 
				
			||||||
#include "dma.h"
 | 
					#include "dma.h"
 | 
				
			||||||
 | 
					#include "hw/block-common.h"
 | 
				
			||||||
#include "blockdev.h"
 | 
					#include "blockdev.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <hw/ide/internal.h>
 | 
					#include <hw/ide/internal.h>
 | 
				
			||||||
@ -1924,31 +1925,20 @@ static const BlockDevOps ide_cd_block_ops = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
 | 
					int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
 | 
				
			||||||
                   const char *version, const char *serial, const char *model,
 | 
					                   const char *version, const char *serial, const char *model,
 | 
				
			||||||
                   uint64_t wwn)
 | 
					                   uint64_t wwn,
 | 
				
			||||||
 | 
					                   uint32_t cylinders, uint32_t heads, uint32_t secs,
 | 
				
			||||||
 | 
					                   int chs_trans)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int cylinders, heads, secs;
 | 
					 | 
				
			||||||
    uint64_t nb_sectors;
 | 
					    uint64_t nb_sectors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->bs = bs;
 | 
					    s->bs = bs;
 | 
				
			||||||
    s->drive_kind = kind;
 | 
					    s->drive_kind = kind;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bdrv_get_geometry(bs, &nb_sectors);
 | 
					    bdrv_get_geometry(bs, &nb_sectors);
 | 
				
			||||||
    bdrv_guess_geometry(bs, &cylinders, &heads, &secs);
 | 
					 | 
				
			||||||
    if (cylinders < 1 || cylinders > 16383) {
 | 
					 | 
				
			||||||
        error_report("cyls must be between 1 and 16383");
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (heads < 1 || heads > 16) {
 | 
					 | 
				
			||||||
        error_report("heads must be between 1 and 16");
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (secs < 1 || secs > 63) {
 | 
					 | 
				
			||||||
        error_report("secs must be between 1 and 63");
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    s->cylinders = cylinders;
 | 
					    s->cylinders = cylinders;
 | 
				
			||||||
    s->heads = heads;
 | 
					    s->heads = heads;
 | 
				
			||||||
    s->sectors = secs;
 | 
					    s->sectors = secs;
 | 
				
			||||||
 | 
					    s->chs_trans = chs_trans;
 | 
				
			||||||
    s->nb_sectors = nb_sectors;
 | 
					    s->nb_sectors = nb_sectors;
 | 
				
			||||||
    s->wwn = wwn;
 | 
					    s->wwn = wwn;
 | 
				
			||||||
    /* The SMART values should be preserved across power cycles
 | 
					    /* The SMART values should be preserved across power cycles
 | 
				
			||||||
@ -2075,17 +2065,39 @@ void ide_init2(IDEBus *bus, qemu_irq irq)
 | 
				
			|||||||
void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
 | 
					void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
 | 
				
			||||||
                                    DriveInfo *hd1, qemu_irq irq)
 | 
					                                    DriveInfo *hd1, qemu_irq irq)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int i;
 | 
					    int i, trans;
 | 
				
			||||||
    DriveInfo *dinfo;
 | 
					    DriveInfo *dinfo;
 | 
				
			||||||
 | 
					    uint32_t cyls, heads, secs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for(i = 0; i < 2; i++) {
 | 
					    for(i = 0; i < 2; i++) {
 | 
				
			||||||
        dinfo = i == 0 ? hd0 : hd1;
 | 
					        dinfo = i == 0 ? hd0 : hd1;
 | 
				
			||||||
        ide_init1(bus, i);
 | 
					        ide_init1(bus, i);
 | 
				
			||||||
        if (dinfo) {
 | 
					        if (dinfo) {
 | 
				
			||||||
 | 
					            cyls  = dinfo->cyls;
 | 
				
			||||||
 | 
					            heads = dinfo->heads;
 | 
				
			||||||
 | 
					            secs  = dinfo->secs;
 | 
				
			||||||
 | 
					            trans = dinfo->trans;
 | 
				
			||||||
 | 
					            if (!cyls && !heads && !secs) {
 | 
				
			||||||
 | 
					                hd_geometry_guess(dinfo->bdrv, &cyls, &heads, &secs, &trans);
 | 
				
			||||||
 | 
					            } else if (trans == BIOS_ATA_TRANSLATION_AUTO) {
 | 
				
			||||||
 | 
					                trans = hd_bios_chs_auto_trans(cyls, heads, secs);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (cyls < 1 || cyls > 65535) {
 | 
				
			||||||
 | 
					                error_report("cyls must be between 1 and 65535");
 | 
				
			||||||
 | 
					                exit(1);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (heads < 1 || heads > 16) {
 | 
				
			||||||
 | 
					                error_report("heads must be between 1 and 16");
 | 
				
			||||||
 | 
					                exit(1);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (secs < 1 || secs > 255) {
 | 
				
			||||||
 | 
					                error_report("secs must be between 1 and 255");
 | 
				
			||||||
 | 
					                exit(1);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            if (ide_init_drive(&bus->ifs[i], dinfo->bdrv,
 | 
					            if (ide_init_drive(&bus->ifs[i], dinfo->bdrv,
 | 
				
			||||||
                               dinfo->media_cd ? IDE_CD : IDE_HD, NULL,
 | 
					                               dinfo->media_cd ? IDE_CD : IDE_HD,
 | 
				
			||||||
                               *dinfo->serial ? dinfo->serial : NULL,
 | 
					                               NULL, dinfo->serial, NULL, 0,
 | 
				
			||||||
                               NULL, 0) < 0) {
 | 
					                               cyls, heads, secs, trans) < 0) {
 | 
				
			||||||
                error_report("Can't set up IDE drive %s", dinfo->id);
 | 
					                error_report("Can't set up IDE drive %s", dinfo->id);
 | 
				
			||||||
                exit(1);
 | 
					                exit(1);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,7 @@
 | 
				
			|||||||
#include "iorange.h"
 | 
					#include "iorange.h"
 | 
				
			||||||
#include "dma.h"
 | 
					#include "dma.h"
 | 
				
			||||||
#include "sysemu.h"
 | 
					#include "sysemu.h"
 | 
				
			||||||
 | 
					#include "hw/block-common.h"
 | 
				
			||||||
#include "hw/scsi-defs.h"
 | 
					#include "hw/scsi-defs.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* debug IDE devices */
 | 
					/* debug IDE devices */
 | 
				
			||||||
@ -344,7 +345,7 @@ struct IDEState {
 | 
				
			|||||||
    uint8_t unit;
 | 
					    uint8_t unit;
 | 
				
			||||||
    /* ide config */
 | 
					    /* ide config */
 | 
				
			||||||
    IDEDriveKind drive_kind;
 | 
					    IDEDriveKind drive_kind;
 | 
				
			||||||
    int cylinders, heads, sectors;
 | 
					    int cylinders, heads, sectors, chs_trans;
 | 
				
			||||||
    int64_t nb_sectors;
 | 
					    int64_t nb_sectors;
 | 
				
			||||||
    int mult_sectors;
 | 
					    int mult_sectors;
 | 
				
			||||||
    int identify_set;
 | 
					    int identify_set;
 | 
				
			||||||
@ -474,6 +475,7 @@ struct IDEDevice {
 | 
				
			|||||||
    DeviceState qdev;
 | 
					    DeviceState qdev;
 | 
				
			||||||
    uint32_t unit;
 | 
					    uint32_t unit;
 | 
				
			||||||
    BlockConf conf;
 | 
					    BlockConf conf;
 | 
				
			||||||
 | 
					    int chs_trans;
 | 
				
			||||||
    char *version;
 | 
					    char *version;
 | 
				
			||||||
    char *serial;
 | 
					    char *serial;
 | 
				
			||||||
    char *model;
 | 
					    char *model;
 | 
				
			||||||
@ -545,7 +547,9 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
 | 
					int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
 | 
				
			||||||
                   const char *version, const char *serial, const char *model,
 | 
					                   const char *version, const char *serial, const char *model,
 | 
				
			||||||
                   uint64_t wwn);
 | 
					                   uint64_t wwn,
 | 
				
			||||||
 | 
					                   uint32_t cylinders, uint32_t heads, uint32_t secs,
 | 
				
			||||||
 | 
					                   int chs_trans);
 | 
				
			||||||
void ide_init2(IDEBus *bus, qemu_irq irq);
 | 
					void ide_init2(IDEBus *bus, qemu_irq irq);
 | 
				
			||||||
void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
 | 
					void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
 | 
				
			||||||
                                    DriveInfo *hd1, qemu_irq irq);
 | 
					                                    DriveInfo *hd1, qemu_irq irq);
 | 
				
			||||||
 | 
				
			|||||||
@ -21,6 +21,7 @@
 | 
				
			|||||||
#include "qemu-error.h"
 | 
					#include "qemu-error.h"
 | 
				
			||||||
#include <hw/ide/internal.h>
 | 
					#include <hw/ide/internal.h>
 | 
				
			||||||
#include "blockdev.h"
 | 
					#include "blockdev.h"
 | 
				
			||||||
 | 
					#include "hw/block-common.h"
 | 
				
			||||||
#include "sysemu.h"
 | 
					#include "sysemu.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* --------------------------------- */
 | 
					/* --------------------------------- */
 | 
				
			||||||
@ -111,11 +112,24 @@ IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive)
 | 
				
			|||||||
    return DO_UPCAST(IDEDevice, qdev, dev);
 | 
					    return DO_UPCAST(IDEDevice, qdev, dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ide_get_bs(BlockDriverState *bs[], BusState *qbus)
 | 
					int ide_get_geometry(BusState *bus, int unit,
 | 
				
			||||||
 | 
					                     int16_t *cyls, int8_t *heads, int8_t *secs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    IDEBus *bus = DO_UPCAST(IDEBus, qbus, qbus);
 | 
					    IDEState *s = &DO_UPCAST(IDEBus, qbus, bus)->ifs[unit];
 | 
				
			||||||
    bs[0] = bus->master ? bus->master->conf.bs : NULL;
 | 
					
 | 
				
			||||||
    bs[1] = bus->slave  ? bus->slave->conf.bs  : NULL;
 | 
					    if (s->drive_kind != IDE_HD || !s->bs) {
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    *cyls = s->cylinders;
 | 
				
			||||||
 | 
					    *heads = s->heads;
 | 
				
			||||||
 | 
					    *secs = s->sectors;
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ide_get_bios_chs_trans(BusState *bus, int unit)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return DO_UPCAST(IDEBus, qbus, bus)->ifs[unit].chs_trans;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* --------------------------------- */
 | 
					/* --------------------------------- */
 | 
				
			||||||
@ -128,25 +142,21 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
 | 
					    IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
 | 
				
			||||||
    IDEState *s = bus->ifs + dev->unit;
 | 
					    IDEState *s = bus->ifs + dev->unit;
 | 
				
			||||||
    const char *serial;
 | 
					 | 
				
			||||||
    DriveInfo *dinfo;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (dev->conf.discard_granularity && dev->conf.discard_granularity != 512) {
 | 
					    if (dev->conf.discard_granularity && dev->conf.discard_granularity != 512) {
 | 
				
			||||||
        error_report("discard_granularity must be 512 for ide");
 | 
					        error_report("discard_granularity must be 512 for ide");
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    serial = dev->serial;
 | 
					    blkconf_serial(&dev->conf, &dev->serial);
 | 
				
			||||||
    if (!serial) {
 | 
					    if (blkconf_geometry(&dev->conf, &dev->chs_trans, 65536, 16, 255) < 0) {
 | 
				
			||||||
        /* try to fall back to value set with legacy -drive serial=... */
 | 
					        return -1;
 | 
				
			||||||
        dinfo = drive_get_by_blockdev(dev->conf.bs);
 | 
					 | 
				
			||||||
        if (*dinfo->serial) {
 | 
					 | 
				
			||||||
            serial = dinfo->serial;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (ide_init_drive(s, dev->conf.bs, kind,
 | 
					    if (ide_init_drive(s, dev->conf.bs, kind,
 | 
				
			||||||
                       dev->version, serial, dev->model, dev->wwn) < 0) {
 | 
					                       dev->version, dev->serial, dev->model, dev->wwn,
 | 
				
			||||||
 | 
					                       dev->conf.cyls, dev->conf.heads, dev->conf.secs,
 | 
				
			||||||
 | 
					                       dev->chs_trans) < 0) {
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -189,6 +199,9 @@ static int ide_drive_initfn(IDEDevice *dev)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static Property ide_hd_properties[] = {
 | 
					static Property ide_hd_properties[] = {
 | 
				
			||||||
    DEFINE_IDE_DEV_PROPERTIES(),
 | 
					    DEFINE_IDE_DEV_PROPERTIES(),
 | 
				
			||||||
 | 
					    DEFINE_BLOCK_CHS_PROPERTIES(IDEDrive, dev.conf),
 | 
				
			||||||
 | 
					    DEFINE_PROP_BIOS_CHS_TRANS("bios-chs-trans",
 | 
				
			||||||
 | 
					                IDEDrive, dev.chs_trans, BIOS_ATA_TRANSLATION_AUTO),
 | 
				
			||||||
    DEFINE_PROP_END_OF_LIST(),
 | 
					    DEFINE_PROP_END_OF_LIST(),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										78
									
								
								hw/pc.c
									
									
									
									
									
								
							
							
						
						
									
										78
									
								
								hw/pc.c
									
									
									
									
									
								
							@ -44,6 +44,7 @@
 | 
				
			|||||||
#include "kvm.h"
 | 
					#include "kvm.h"
 | 
				
			||||||
#include "xen.h"
 | 
					#include "xen.h"
 | 
				
			||||||
#include "blockdev.h"
 | 
					#include "blockdev.h"
 | 
				
			||||||
 | 
					#include "hw/block-common.h"
 | 
				
			||||||
#include "ui/qemu-spice.h"
 | 
					#include "ui/qemu-spice.h"
 | 
				
			||||||
#include "memory.h"
 | 
					#include "memory.h"
 | 
				
			||||||
#include "exec-memory.h"
 | 
					#include "exec-memory.h"
 | 
				
			||||||
@ -216,11 +217,9 @@ static int cmos_get_fd_drive_type(FDriveType fd0)
 | 
				
			|||||||
    return val;
 | 
					    return val;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd,
 | 
					static void cmos_init_hd(ISADevice *s, int type_ofs, int info_ofs,
 | 
				
			||||||
                         ISADevice *s)
 | 
					                         int16_t cylinders, int8_t heads, int8_t sectors)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int cylinders, heads, sectors;
 | 
					 | 
				
			||||||
    bdrv_get_geometry_hint(hd, &cylinders, &heads, §ors);
 | 
					 | 
				
			||||||
    rtc_set_memory(s, type_ofs, 47);
 | 
					    rtc_set_memory(s, type_ofs, 47);
 | 
				
			||||||
    rtc_set_memory(s, info_ofs, cylinders);
 | 
					    rtc_set_memory(s, info_ofs, cylinders);
 | 
				
			||||||
    rtc_set_memory(s, info_ofs + 1, cylinders >> 8);
 | 
					    rtc_set_memory(s, info_ofs + 1, cylinders >> 8);
 | 
				
			||||||
@ -281,48 +280,42 @@ static int pc_boot_set(void *opaque, const char *boot_device)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
typedef struct pc_cmos_init_late_arg {
 | 
					typedef struct pc_cmos_init_late_arg {
 | 
				
			||||||
    ISADevice *rtc_state;
 | 
					    ISADevice *rtc_state;
 | 
				
			||||||
    BusState *idebus0, *idebus1;
 | 
					    BusState *idebus[2];
 | 
				
			||||||
} pc_cmos_init_late_arg;
 | 
					} pc_cmos_init_late_arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void pc_cmos_init_late(void *opaque)
 | 
					static void pc_cmos_init_late(void *opaque)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    pc_cmos_init_late_arg *arg = opaque;
 | 
					    pc_cmos_init_late_arg *arg = opaque;
 | 
				
			||||||
    ISADevice *s = arg->rtc_state;
 | 
					    ISADevice *s = arg->rtc_state;
 | 
				
			||||||
 | 
					    int16_t cylinders;
 | 
				
			||||||
 | 
					    int8_t heads, sectors;
 | 
				
			||||||
    int val;
 | 
					    int val;
 | 
				
			||||||
    BlockDriverState *hd_table[4];
 | 
					    int i, trans;
 | 
				
			||||||
    int i;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ide_get_bs(hd_table, arg->idebus0);
 | 
					    val = 0;
 | 
				
			||||||
    ide_get_bs(hd_table + 2, arg->idebus1);
 | 
					    if (ide_get_geometry(arg->idebus[0], 0,
 | 
				
			||||||
 | 
					                         &cylinders, &heads, §ors) >= 0) {
 | 
				
			||||||
    rtc_set_memory(s, 0x12, (hd_table[0] ? 0xf0 : 0) | (hd_table[1] ? 0x0f : 0));
 | 
					        cmos_init_hd(s, 0x19, 0x1b, cylinders, heads, sectors);
 | 
				
			||||||
    if (hd_table[0])
 | 
					        val |= 0xf0;
 | 
				
			||||||
        cmos_init_hd(0x19, 0x1b, hd_table[0], s);
 | 
					    }
 | 
				
			||||||
    if (hd_table[1])
 | 
					    if (ide_get_geometry(arg->idebus[0], 1,
 | 
				
			||||||
        cmos_init_hd(0x1a, 0x24, hd_table[1], s);
 | 
					                         &cylinders, &heads, §ors) >= 0) {
 | 
				
			||||||
 | 
					        cmos_init_hd(s, 0x1a, 0x24, cylinders, heads, sectors);
 | 
				
			||||||
 | 
					        val |= 0x0f;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    rtc_set_memory(s, 0x12, val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    val = 0;
 | 
					    val = 0;
 | 
				
			||||||
    for (i = 0; i < 4; i++) {
 | 
					    for (i = 0; i < 4; i++) {
 | 
				
			||||||
        if (hd_table[i]) {
 | 
					        /* NOTE: ide_get_geometry() returns the physical
 | 
				
			||||||
            int cylinders, heads, sectors, translation;
 | 
					           geometry.  It is always such that: 1 <= sects <= 63, 1
 | 
				
			||||||
            /* NOTE: bdrv_get_geometry_hint() returns the physical
 | 
					           <= heads <= 16, 1 <= cylinders <= 16383. The BIOS
 | 
				
			||||||
                geometry.  It is always such that: 1 <= sects <= 63, 1
 | 
					           geometry can be different if a translation is done. */
 | 
				
			||||||
                <= heads <= 16, 1 <= cylinders <= 16383. The BIOS
 | 
					        if (ide_get_geometry(arg->idebus[i / 2], i % 2,
 | 
				
			||||||
                geometry can be different if a translation is done. */
 | 
					                             &cylinders, &heads, §ors) >= 0) {
 | 
				
			||||||
            translation = bdrv_get_translation_hint(hd_table[i]);
 | 
					            trans = ide_get_bios_chs_trans(arg->idebus[i / 2], i % 2) - 1;
 | 
				
			||||||
            if (translation == BIOS_ATA_TRANSLATION_AUTO) {
 | 
					            assert((trans & ~3) == 0);
 | 
				
			||||||
                bdrv_get_geometry_hint(hd_table[i], &cylinders, &heads, §ors);
 | 
					            val |= trans << (i * 2);
 | 
				
			||||||
                if (cylinders <= 1024 && heads <= 16 && sectors <= 63) {
 | 
					 | 
				
			||||||
                    /* No translation. */
 | 
					 | 
				
			||||||
                    translation = 0;
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    /* LBA translation. */
 | 
					 | 
				
			||||||
                    translation = 1;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                translation--;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            val |= translation << (i * 2);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    rtc_set_memory(s, 0x39, val);
 | 
					    rtc_set_memory(s, 0x39, val);
 | 
				
			||||||
@ -335,10 +328,8 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
 | 
				
			|||||||
                  ISADevice *floppy, BusState *idebus0, BusState *idebus1,
 | 
					                  ISADevice *floppy, BusState *idebus0, BusState *idebus1,
 | 
				
			||||||
                  ISADevice *s)
 | 
					                  ISADevice *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int val, nb, nb_heads, max_track, last_sect, i;
 | 
					    int val, nb, i;
 | 
				
			||||||
    FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
 | 
					    FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
 | 
				
			||||||
    FDriveRate rate;
 | 
					 | 
				
			||||||
    BlockDriverState *fd[MAX_FD];
 | 
					 | 
				
			||||||
    static pc_cmos_init_late_arg arg;
 | 
					    static pc_cmos_init_late_arg arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* various important CMOS locations needed by PC/Bochs bios */
 | 
					    /* various important CMOS locations needed by PC/Bochs bios */
 | 
				
			||||||
@ -381,13 +372,8 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* floppy type */
 | 
					    /* floppy type */
 | 
				
			||||||
    if (floppy) {
 | 
					    if (floppy) {
 | 
				
			||||||
        fdc_get_bs(fd, floppy);
 | 
					 | 
				
			||||||
        for (i = 0; i < 2; i++) {
 | 
					        for (i = 0; i < 2; i++) {
 | 
				
			||||||
            if (fd[i]) {
 | 
					            fd_type[i] = isa_fdc_get_drive_type(floppy, i);
 | 
				
			||||||
                bdrv_get_floppy_geometry_hint(fd[i], &nb_heads, &max_track,
 | 
					 | 
				
			||||||
                                              &last_sect, FDRIVE_DRV_NONE,
 | 
					 | 
				
			||||||
                                              &fd_type[i], &rate);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    val = (cmos_get_fd_drive_type(fd_type[0]) << 4) |
 | 
					    val = (cmos_get_fd_drive_type(fd_type[0]) << 4) |
 | 
				
			||||||
@ -418,8 +404,8 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* hard drives */
 | 
					    /* hard drives */
 | 
				
			||||||
    arg.rtc_state = s;
 | 
					    arg.rtc_state = s;
 | 
				
			||||||
    arg.idebus0 = idebus0;
 | 
					    arg.idebus[0] = idebus0;
 | 
				
			||||||
    arg.idebus1 = idebus1;
 | 
					    arg.idebus[1] = idebus1;
 | 
				
			||||||
    qemu_register_reset(pc_cmos_init_late, &arg);
 | 
					    qemu_register_reset(pc_cmos_init_late, &arg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@
 | 
				
			|||||||
#include "qdev.h"
 | 
					#include "qdev.h"
 | 
				
			||||||
#include "qerror.h"
 | 
					#include "qerror.h"
 | 
				
			||||||
#include "blockdev.h"
 | 
					#include "blockdev.h"
 | 
				
			||||||
 | 
					#include "hw/block-common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
 | 
					void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -10,6 +11,78 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
 | 
				
			|||||||
    return ptr;
 | 
					    return ptr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void get_pointer(Object *obj, Visitor *v, Property *prop,
 | 
				
			||||||
 | 
					                        const char *(*print)(void *ptr),
 | 
				
			||||||
 | 
					                        const char *name, Error **errp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    DeviceState *dev = DEVICE(obj);
 | 
				
			||||||
 | 
					    void **ptr = qdev_get_prop_ptr(dev, prop);
 | 
				
			||||||
 | 
					    char *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    p = (char *) (*ptr ? print(*ptr) : "");
 | 
				
			||||||
 | 
					    visit_type_str(v, &p, name, errp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void set_pointer(Object *obj, Visitor *v, Property *prop,
 | 
				
			||||||
 | 
					                        int (*parse)(DeviceState *dev, const char *str,
 | 
				
			||||||
 | 
					                                     void **ptr),
 | 
				
			||||||
 | 
					                        const char *name, Error **errp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    DeviceState *dev = DEVICE(obj);
 | 
				
			||||||
 | 
					    Error *local_err = NULL;
 | 
				
			||||||
 | 
					    void **ptr = qdev_get_prop_ptr(dev, prop);
 | 
				
			||||||
 | 
					    char *str;
 | 
				
			||||||
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (dev->state != DEV_STATE_CREATED) {
 | 
				
			||||||
 | 
					        error_set(errp, QERR_PERMISSION_DENIED);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    visit_type_str(v, &str, name, &local_err);
 | 
				
			||||||
 | 
					    if (local_err) {
 | 
				
			||||||
 | 
					        error_propagate(errp, local_err);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!*str) {
 | 
				
			||||||
 | 
					        g_free(str);
 | 
				
			||||||
 | 
					        *ptr = NULL;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    ret = parse(dev, str, ptr);
 | 
				
			||||||
 | 
					    error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
 | 
				
			||||||
 | 
					    g_free(str);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void get_enum(Object *obj, Visitor *v, void *opaque,
 | 
				
			||||||
 | 
					                     const char *name, Error **errp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    DeviceState *dev = DEVICE(obj);
 | 
				
			||||||
 | 
					    Property *prop = opaque;
 | 
				
			||||||
 | 
					    int *ptr = qdev_get_prop_ptr(dev, prop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    visit_type_enum(v, ptr, prop->info->enum_table,
 | 
				
			||||||
 | 
					                    prop->info->name, prop->name, errp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void set_enum(Object *obj, Visitor *v, void *opaque,
 | 
				
			||||||
 | 
					                     const char *name, Error **errp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    DeviceState *dev = DEVICE(obj);
 | 
				
			||||||
 | 
					    Property *prop = opaque;
 | 
				
			||||||
 | 
					    int *ptr = qdev_get_prop_ptr(dev, prop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (dev->state != DEV_STATE_CREATED) {
 | 
				
			||||||
 | 
					        error_set(errp, QERR_PERMISSION_DENIED);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    visit_type_enum(v, ptr, prop->info->enum_table,
 | 
				
			||||||
 | 
					                    prop->info->name, prop->name, errp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Bit */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint32_t qdev_get_prop_mask(Property *prop)
 | 
					static uint32_t qdev_get_prop_mask(Property *prop)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    assert(prop->info == &qdev_prop_bit);
 | 
					    assert(prop->info == &qdev_prop_bit);
 | 
				
			||||||
@ -26,8 +99,6 @@ static void bit_prop_set(DeviceState *dev, Property *props, bool val)
 | 
				
			|||||||
        *p &= ~mask;
 | 
					        *p &= ~mask;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Bit */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
 | 
					static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint32_t *p = qdev_get_prop_ptr(dev, prop);
 | 
					    uint32_t *p = qdev_get_prop_ptr(dev, prop);
 | 
				
			||||||
@ -435,48 +506,6 @@ static const char *print_drive(void *ptr)
 | 
				
			|||||||
    return bdrv_get_device_name(ptr);
 | 
					    return bdrv_get_device_name(ptr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void get_pointer(Object *obj, Visitor *v, Property *prop,
 | 
					 | 
				
			||||||
                        const char *(*print)(void *ptr),
 | 
					 | 
				
			||||||
                        const char *name, Error **errp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    DeviceState *dev = DEVICE(obj);
 | 
					 | 
				
			||||||
    void **ptr = qdev_get_prop_ptr(dev, prop);
 | 
					 | 
				
			||||||
    char *p;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    p = (char *) (*ptr ? print(*ptr) : "");
 | 
					 | 
				
			||||||
    visit_type_str(v, &p, name, errp);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void set_pointer(Object *obj, Visitor *v, Property *prop,
 | 
					 | 
				
			||||||
                        int (*parse)(DeviceState *dev, const char *str, void **ptr),
 | 
					 | 
				
			||||||
                        const char *name, Error **errp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    DeviceState *dev = DEVICE(obj);
 | 
					 | 
				
			||||||
    Error *local_err = NULL;
 | 
					 | 
				
			||||||
    void **ptr = qdev_get_prop_ptr(dev, prop);
 | 
					 | 
				
			||||||
    char *str;
 | 
					 | 
				
			||||||
    int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (dev->state != DEV_STATE_CREATED) {
 | 
					 | 
				
			||||||
        error_set(errp, QERR_PERMISSION_DENIED);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    visit_type_str(v, &str, name, &local_err);
 | 
					 | 
				
			||||||
    if (local_err) {
 | 
					 | 
				
			||||||
        error_propagate(errp, local_err);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (!*str) {
 | 
					 | 
				
			||||||
        g_free(str);
 | 
					 | 
				
			||||||
        *ptr = NULL;
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    ret = parse(dev, str, ptr);
 | 
					 | 
				
			||||||
    error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
 | 
					 | 
				
			||||||
    g_free(str);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void get_drive(Object *obj, Visitor *v, void *opaque,
 | 
					static void get_drive(Object *obj, Visitor *v, void *opaque,
 | 
				
			||||||
                      const char *name, Error **errp)
 | 
					                      const char *name, Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -735,7 +764,6 @@ PropertyInfo qdev_prop_macaddr = {
 | 
				
			|||||||
    .set   = set_mac,
 | 
					    .set   = set_mac,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
/* --- lost tick policy --- */
 | 
					/* --- lost tick policy --- */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
 | 
					static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
 | 
				
			||||||
@ -748,33 +776,6 @@ static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
 | 
					QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void get_enum(Object *obj, Visitor *v, void *opaque,
 | 
					 | 
				
			||||||
                     const char *name, Error **errp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    DeviceState *dev = DEVICE(obj);
 | 
					 | 
				
			||||||
    Property *prop = opaque;
 | 
					 | 
				
			||||||
    int *ptr = qdev_get_prop_ptr(dev, prop);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    visit_type_enum(v, ptr, prop->info->enum_table,
 | 
					 | 
				
			||||||
                    prop->info->name, prop->name, errp);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void set_enum(Object *obj, Visitor *v, void *opaque,
 | 
					 | 
				
			||||||
                     const char *name, Error **errp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    DeviceState *dev = DEVICE(obj);
 | 
					 | 
				
			||||||
    Property *prop = opaque;
 | 
					 | 
				
			||||||
    int *ptr = qdev_get_prop_ptr(dev, prop);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (dev->state != DEV_STATE_CREATED) {
 | 
					 | 
				
			||||||
        error_set(errp, QERR_PERMISSION_DENIED);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    visit_type_enum(v, ptr, prop->info->enum_table,
 | 
					 | 
				
			||||||
                    prop->info->name, prop->name, errp);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PropertyInfo qdev_prop_losttickpolicy = {
 | 
					PropertyInfo qdev_prop_losttickpolicy = {
 | 
				
			||||||
    .name  = "LostTickPolicy",
 | 
					    .name  = "LostTickPolicy",
 | 
				
			||||||
    .enum_table  = lost_tick_policy_table,
 | 
					    .enum_table  = lost_tick_policy_table,
 | 
				
			||||||
@ -782,6 +783,21 @@ PropertyInfo qdev_prop_losttickpolicy = {
 | 
				
			|||||||
    .set   = set_enum,
 | 
					    .set   = set_enum,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* --- BIOS CHS translation */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *bios_chs_trans_table[] = {
 | 
				
			||||||
 | 
					    [BIOS_ATA_TRANSLATION_AUTO] = "auto",
 | 
				
			||||||
 | 
					    [BIOS_ATA_TRANSLATION_NONE] = "none",
 | 
				
			||||||
 | 
					    [BIOS_ATA_TRANSLATION_LBA]  = "lba",
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PropertyInfo qdev_prop_bios_chs_trans = {
 | 
				
			||||||
 | 
					    .name = "bios-chs-trans",
 | 
				
			||||||
 | 
					    .enum_table = bios_chs_trans_table,
 | 
				
			||||||
 | 
					    .get = get_enum,
 | 
				
			||||||
 | 
					    .set = set_enum,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* --- pci address --- */
 | 
					/* --- pci address --- */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 | 
				
			|||||||
@ -232,6 +232,7 @@ extern PropertyInfo qdev_prop_chr;
 | 
				
			|||||||
extern PropertyInfo qdev_prop_ptr;
 | 
					extern PropertyInfo qdev_prop_ptr;
 | 
				
			||||||
extern PropertyInfo qdev_prop_macaddr;
 | 
					extern PropertyInfo qdev_prop_macaddr;
 | 
				
			||||||
extern PropertyInfo qdev_prop_losttickpolicy;
 | 
					extern PropertyInfo qdev_prop_losttickpolicy;
 | 
				
			||||||
 | 
					extern PropertyInfo qdev_prop_bios_chs_trans;
 | 
				
			||||||
extern PropertyInfo qdev_prop_drive;
 | 
					extern PropertyInfo qdev_prop_drive;
 | 
				
			||||||
extern PropertyInfo qdev_prop_netdev;
 | 
					extern PropertyInfo qdev_prop_netdev;
 | 
				
			||||||
extern PropertyInfo qdev_prop_vlan;
 | 
					extern PropertyInfo qdev_prop_vlan;
 | 
				
			||||||
@ -299,6 +300,8 @@ extern PropertyInfo qdev_prop_pci_host_devaddr;
 | 
				
			|||||||
#define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
 | 
					#define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
 | 
				
			||||||
    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_losttickpolicy, \
 | 
					    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_losttickpolicy, \
 | 
				
			||||||
                        LostTickPolicy)
 | 
					                        LostTickPolicy)
 | 
				
			||||||
 | 
					#define DEFINE_PROP_BIOS_CHS_TRANS(_n, _s, _f, _d) \
 | 
				
			||||||
 | 
					    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int)
 | 
				
			||||||
#define DEFINE_PROP_BLOCKSIZE(_n, _s, _f, _d) \
 | 
					#define DEFINE_PROP_BLOCKSIZE(_n, _s, _f, _d) \
 | 
				
			||||||
    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blocksize, uint16_t)
 | 
					    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blocksize, uint16_t)
 | 
				
			||||||
#define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \
 | 
					#define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \
 | 
				
			||||||
 | 
				
			|||||||
@ -402,6 +402,7 @@ static TypeInfo s390_virtio_net = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static Property s390_virtio_blk_properties[] = {
 | 
					static Property s390_virtio_blk_properties[] = {
 | 
				
			||||||
    DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, blk.conf),
 | 
					    DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, blk.conf),
 | 
				
			||||||
 | 
					    DEFINE_BLOCK_CHS_PROPERTIES(VirtIOS390Device, blk.conf),
 | 
				
			||||||
    DEFINE_PROP_STRING("serial", VirtIOS390Device, blk.serial),
 | 
					    DEFINE_PROP_STRING("serial", VirtIOS390Device, blk.serial),
 | 
				
			||||||
#ifdef __linux__
 | 
					#ifdef __linux__
 | 
				
			||||||
    DEFINE_PROP_BIT("scsi", VirtIOS390Device, blk.scsi, 0, true),
 | 
					    DEFINE_PROP_BIT("scsi", VirtIOS390Device, blk.scsi, 0, true),
 | 
				
			||||||
 | 
				
			|||||||
@ -34,6 +34,7 @@ do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
 | 
				
			|||||||
#include "scsi-defs.h"
 | 
					#include "scsi-defs.h"
 | 
				
			||||||
#include "sysemu.h"
 | 
					#include "sysemu.h"
 | 
				
			||||||
#include "blockdev.h"
 | 
					#include "blockdev.h"
 | 
				
			||||||
 | 
					#include "hw/block-common.h"
 | 
				
			||||||
#include "dma.h"
 | 
					#include "dma.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __linux
 | 
					#ifdef __linux
 | 
				
			||||||
@ -965,9 +966,6 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
 | 
				
			|||||||
        [MODE_PAGE_AUDIO_CTL]              = (1 << TYPE_ROM),
 | 
					        [MODE_PAGE_AUDIO_CTL]              = (1 << TYPE_ROM),
 | 
				
			||||||
        [MODE_PAGE_CAPABILITIES]           = (1 << TYPE_ROM),
 | 
					        [MODE_PAGE_CAPABILITIES]           = (1 << TYPE_ROM),
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					 | 
				
			||||||
    BlockDriverState *bdrv = s->qdev.conf.bs;
 | 
					 | 
				
			||||||
    int cylinders, heads, secs;
 | 
					 | 
				
			||||||
    uint8_t *p = *p_outbuf;
 | 
					    uint8_t *p = *p_outbuf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((mode_sense_valid[page] & (1 << s->qdev.type)) == 0) {
 | 
					    if ((mode_sense_valid[page] & (1 << s->qdev.type)) == 0) {
 | 
				
			||||||
@ -989,19 +987,18 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
 | 
				
			|||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        /* if a geometry hint is available, use it */
 | 
					        /* if a geometry hint is available, use it */
 | 
				
			||||||
        bdrv_guess_geometry(bdrv, &cylinders, &heads, &secs);
 | 
					        p[2] = (s->qdev.conf.cyls >> 16) & 0xff;
 | 
				
			||||||
        p[2] = (cylinders >> 16) & 0xff;
 | 
					        p[3] = (s->qdev.conf.cyls >> 8) & 0xff;
 | 
				
			||||||
        p[3] = (cylinders >> 8) & 0xff;
 | 
					        p[4] = s->qdev.conf.cyls & 0xff;
 | 
				
			||||||
        p[4] = cylinders & 0xff;
 | 
					        p[5] = s->qdev.conf.heads & 0xff;
 | 
				
			||||||
        p[5] = heads & 0xff;
 | 
					 | 
				
			||||||
        /* Write precomp start cylinder, disabled */
 | 
					        /* Write precomp start cylinder, disabled */
 | 
				
			||||||
        p[6] = (cylinders >> 16) & 0xff;
 | 
					        p[6] = (s->qdev.conf.cyls >> 16) & 0xff;
 | 
				
			||||||
        p[7] = (cylinders >> 8) & 0xff;
 | 
					        p[7] = (s->qdev.conf.cyls >> 8) & 0xff;
 | 
				
			||||||
        p[8] = cylinders & 0xff;
 | 
					        p[8] = s->qdev.conf.cyls & 0xff;
 | 
				
			||||||
        /* Reduced current start cylinder, disabled */
 | 
					        /* Reduced current start cylinder, disabled */
 | 
				
			||||||
        p[9] = (cylinders >> 16) & 0xff;
 | 
					        p[9] = (s->qdev.conf.cyls >> 16) & 0xff;
 | 
				
			||||||
        p[10] = (cylinders >> 8) & 0xff;
 | 
					        p[10] = (s->qdev.conf.cyls >> 8) & 0xff;
 | 
				
			||||||
        p[11] = cylinders & 0xff;
 | 
					        p[11] = s->qdev.conf.cyls & 0xff;
 | 
				
			||||||
        /* Device step rate [ns], 200ns */
 | 
					        /* Device step rate [ns], 200ns */
 | 
				
			||||||
        p[12] = 0;
 | 
					        p[12] = 0;
 | 
				
			||||||
        p[13] = 200;
 | 
					        p[13] = 200;
 | 
				
			||||||
@ -1023,18 +1020,17 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
 | 
				
			|||||||
        p[2] = 5000 >> 8;
 | 
					        p[2] = 5000 >> 8;
 | 
				
			||||||
        p[3] = 5000 & 0xff;
 | 
					        p[3] = 5000 & 0xff;
 | 
				
			||||||
        /* if a geometry hint is available, use it */
 | 
					        /* if a geometry hint is available, use it */
 | 
				
			||||||
        bdrv_guess_geometry(bdrv, &cylinders, &heads, &secs);
 | 
					        p[4] = s->qdev.conf.heads & 0xff;
 | 
				
			||||||
        p[4] = heads & 0xff;
 | 
					        p[5] = s->qdev.conf.secs & 0xff;
 | 
				
			||||||
        p[5] = secs & 0xff;
 | 
					 | 
				
			||||||
        p[6] = s->qdev.blocksize >> 8;
 | 
					        p[6] = s->qdev.blocksize >> 8;
 | 
				
			||||||
        p[8] = (cylinders >> 8) & 0xff;
 | 
					        p[8] = (s->qdev.conf.cyls >> 8) & 0xff;
 | 
				
			||||||
        p[9] = cylinders & 0xff;
 | 
					        p[9] = s->qdev.conf.cyls & 0xff;
 | 
				
			||||||
        /* Write precomp start cylinder, disabled */
 | 
					        /* Write precomp start cylinder, disabled */
 | 
				
			||||||
        p[10] = (cylinders >> 8) & 0xff;
 | 
					        p[10] = (s->qdev.conf.cyls >> 8) & 0xff;
 | 
				
			||||||
        p[11] = cylinders & 0xff;
 | 
					        p[11] = s->qdev.conf.cyls & 0xff;
 | 
				
			||||||
        /* Reduced current start cylinder, disabled */
 | 
					        /* Reduced current start cylinder, disabled */
 | 
				
			||||||
        p[12] = (cylinders >> 8) & 0xff;
 | 
					        p[12] = (s->qdev.conf.cyls >> 8) & 0xff;
 | 
				
			||||||
        p[13] = cylinders & 0xff;
 | 
					        p[13] = s->qdev.conf.cyls & 0xff;
 | 
				
			||||||
        /* Device step rate [100us], 100us */
 | 
					        /* Device step rate [100us], 100us */
 | 
				
			||||||
        p[14] = 0;
 | 
					        p[14] = 0;
 | 
				
			||||||
        p[15] = 1;
 | 
					        p[15] = 1;
 | 
				
			||||||
@ -1741,7 +1737,6 @@ static void scsi_disk_unit_attention_reported(SCSIDevice *dev)
 | 
				
			|||||||
static int scsi_initfn(SCSIDevice *dev)
 | 
					static int scsi_initfn(SCSIDevice *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
 | 
					    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
 | 
				
			||||||
    DriveInfo *dinfo;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!s->qdev.conf.bs) {
 | 
					    if (!s->qdev.conf.bs) {
 | 
				
			||||||
        error_report("drive property not set");
 | 
					        error_report("drive property not set");
 | 
				
			||||||
@ -1754,12 +1749,9 @@ static int scsi_initfn(SCSIDevice *dev)
 | 
				
			|||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!s->serial) {
 | 
					    blkconf_serial(&s->qdev.conf, &s->serial);
 | 
				
			||||||
        /* try to fall back to value set with legacy -drive serial=... */
 | 
					    if (blkconf_geometry(&dev->conf, NULL, 65535, 255, 255) < 0) {
 | 
				
			||||||
        dinfo = drive_get_by_blockdev(s->qdev.conf.bs);
 | 
					        return -1;
 | 
				
			||||||
        if (*dinfo->serial) {
 | 
					 | 
				
			||||||
            s->serial = g_strdup(dinfo->serial);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!s->version) {
 | 
					    if (!s->version) {
 | 
				
			||||||
@ -1974,6 +1966,7 @@ static Property scsi_hd_properties[] = {
 | 
				
			|||||||
    DEFINE_PROP_BIT("dpofua", SCSIDiskState, features,
 | 
					    DEFINE_PROP_BIT("dpofua", SCSIDiskState, features,
 | 
				
			||||||
                    SCSI_DISK_F_DPOFUA, false),
 | 
					                    SCSI_DISK_F_DPOFUA, false),
 | 
				
			||||||
    DEFINE_PROP_HEX64("wwn", SCSIDiskState, wwn, 0),
 | 
					    DEFINE_PROP_HEX64("wwn", SCSIDiskState, wwn, 0),
 | 
				
			||||||
 | 
					    DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf),
 | 
				
			||||||
    DEFINE_PROP_END_OF_LIST(),
 | 
					    DEFINE_PROP_END_OF_LIST(),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "qdev.h"
 | 
					#include "qdev.h"
 | 
				
			||||||
#include "block.h"
 | 
					#include "block.h"
 | 
				
			||||||
 | 
					#include "hw/block-common.h"
 | 
				
			||||||
#include "sysemu.h"
 | 
					#include "sysemu.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAX_SCSI_DEVS	255
 | 
					#define MAX_SCSI_DEVS	255
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								hw/usb.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								hw/usb.h
									
									
									
									
									
								
							@ -25,7 +25,6 @@
 | 
				
			|||||||
 * THE SOFTWARE.
 | 
					 * THE SOFTWARE.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "block.h"
 | 
					 | 
				
			||||||
#include "qdev.h"
 | 
					#include "qdev.h"
 | 
				
			||||||
#include "qemu-queue.h"
 | 
					#include "qemu-queue.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -532,13 +532,14 @@ static int usb_msd_initfn(USBDevice *dev)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    MSDState *s = DO_UPCAST(MSDState, dev, dev);
 | 
					    MSDState *s = DO_UPCAST(MSDState, dev, dev);
 | 
				
			||||||
    BlockDriverState *bs = s->conf.bs;
 | 
					    BlockDriverState *bs = s->conf.bs;
 | 
				
			||||||
    DriveInfo *dinfo;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!bs) {
 | 
					    if (!bs) {
 | 
				
			||||||
        error_report("drive property not set");
 | 
					        error_report("drive property not set");
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    blkconf_serial(&s->conf, &s->serial);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /*
 | 
					    /*
 | 
				
			||||||
     * Hack alert: this pretends to be a block device, but it's really
 | 
					     * Hack alert: this pretends to be a block device, but it's really
 | 
				
			||||||
     * a SCSI bus that can serve only a single device, which it
 | 
					     * a SCSI bus that can serve only a single device, which it
 | 
				
			||||||
@ -551,13 +552,6 @@ static int usb_msd_initfn(USBDevice *dev)
 | 
				
			|||||||
    bdrv_detach_dev(bs, &s->dev.qdev);
 | 
					    bdrv_detach_dev(bs, &s->dev.qdev);
 | 
				
			||||||
    s->conf.bs = NULL;
 | 
					    s->conf.bs = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!s->serial) {
 | 
					 | 
				
			||||||
        /* try to fall back to value set with legacy -drive serial=... */
 | 
					 | 
				
			||||||
        dinfo = drive_get_by_blockdev(bs);
 | 
					 | 
				
			||||||
        if (*dinfo->serial) {
 | 
					 | 
				
			||||||
            s->serial = strdup(dinfo->serial);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (s->serial) {
 | 
					    if (s->serial) {
 | 
				
			||||||
        usb_desc_set_string(dev, STR_SERIALNUMBER, s->serial);
 | 
					        usb_desc_set_string(dev, STR_SERIALNUMBER, s->serial);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
 | 
				
			|||||||
@ -14,6 +14,7 @@
 | 
				
			|||||||
#include "qemu-common.h"
 | 
					#include "qemu-common.h"
 | 
				
			||||||
#include "qemu-error.h"
 | 
					#include "qemu-error.h"
 | 
				
			||||||
#include "trace.h"
 | 
					#include "trace.h"
 | 
				
			||||||
 | 
					#include "hw/block-common.h"
 | 
				
			||||||
#include "blockdev.h"
 | 
					#include "blockdev.h"
 | 
				
			||||||
#include "virtio-blk.h"
 | 
					#include "virtio-blk.h"
 | 
				
			||||||
#include "scsi-defs.h"
 | 
					#include "scsi-defs.h"
 | 
				
			||||||
@ -478,19 +479,17 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
 | 
				
			|||||||
    VirtIOBlock *s = to_virtio_blk(vdev);
 | 
					    VirtIOBlock *s = to_virtio_blk(vdev);
 | 
				
			||||||
    struct virtio_blk_config blkcfg;
 | 
					    struct virtio_blk_config blkcfg;
 | 
				
			||||||
    uint64_t capacity;
 | 
					    uint64_t capacity;
 | 
				
			||||||
    int cylinders, heads, secs;
 | 
					 | 
				
			||||||
    int blk_size = s->conf->logical_block_size;
 | 
					    int blk_size = s->conf->logical_block_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bdrv_get_geometry(s->bs, &capacity);
 | 
					    bdrv_get_geometry(s->bs, &capacity);
 | 
				
			||||||
    bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs);
 | 
					 | 
				
			||||||
    memset(&blkcfg, 0, sizeof(blkcfg));
 | 
					    memset(&blkcfg, 0, sizeof(blkcfg));
 | 
				
			||||||
    stq_raw(&blkcfg.capacity, capacity);
 | 
					    stq_raw(&blkcfg.capacity, capacity);
 | 
				
			||||||
    stl_raw(&blkcfg.seg_max, 128 - 2);
 | 
					    stl_raw(&blkcfg.seg_max, 128 - 2);
 | 
				
			||||||
    stw_raw(&blkcfg.cylinders, cylinders);
 | 
					    stw_raw(&blkcfg.cylinders, s->conf->cyls);
 | 
				
			||||||
    stl_raw(&blkcfg.blk_size, blk_size);
 | 
					    stl_raw(&blkcfg.blk_size, blk_size);
 | 
				
			||||||
    stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
 | 
					    stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
 | 
				
			||||||
    stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
 | 
					    stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
 | 
				
			||||||
    blkcfg.heads = heads;
 | 
					    blkcfg.heads = s->conf->heads;
 | 
				
			||||||
    /*
 | 
					    /*
 | 
				
			||||||
     * We must ensure that the block device capacity is a multiple of
 | 
					     * We must ensure that the block device capacity is a multiple of
 | 
				
			||||||
     * the logical block size. If that is not the case, lets use
 | 
					     * the logical block size. If that is not the case, lets use
 | 
				
			||||||
@ -502,10 +501,10 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
 | 
				
			|||||||
     * divided by 512 - instead it is the amount of blk_size blocks
 | 
					     * divided by 512 - instead it is the amount of blk_size blocks
 | 
				
			||||||
     * per track (cylinder).
 | 
					     * per track (cylinder).
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    if (bdrv_getlength(s->bs) /  heads / secs % blk_size) {
 | 
					    if (bdrv_getlength(s->bs) /  s->conf->heads / s->conf->secs % blk_size) {
 | 
				
			||||||
        blkcfg.sectors = secs & ~s->sector_mask;
 | 
					        blkcfg.sectors = s->conf->secs & ~s->sector_mask;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        blkcfg.sectors = secs;
 | 
					        blkcfg.sectors = s->conf->secs;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    blkcfg.size_max = 0;
 | 
					    blkcfg.size_max = 0;
 | 
				
			||||||
    blkcfg.physical_block_exp = get_physical_block_exp(s->conf);
 | 
					    blkcfg.physical_block_exp = get_physical_block_exp(s->conf);
 | 
				
			||||||
@ -589,9 +588,7 @@ static const BlockDevOps virtio_block_ops = {
 | 
				
			|||||||
VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
 | 
					VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    VirtIOBlock *s;
 | 
					    VirtIOBlock *s;
 | 
				
			||||||
    int cylinders, heads, secs;
 | 
					 | 
				
			||||||
    static int virtio_blk_id;
 | 
					    static int virtio_blk_id;
 | 
				
			||||||
    DriveInfo *dinfo;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!blk->conf.bs) {
 | 
					    if (!blk->conf.bs) {
 | 
				
			||||||
        error_report("drive property not set");
 | 
					        error_report("drive property not set");
 | 
				
			||||||
@ -602,12 +599,9 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
 | 
				
			|||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!blk->serial) {
 | 
					    blkconf_serial(&blk->conf, &blk->serial);
 | 
				
			||||||
        /* try to fall back to value set with legacy -drive serial=... */
 | 
					    if (blkconf_geometry(&blk->conf, NULL, 65535, 255, 255) < 0) {
 | 
				
			||||||
        dinfo = drive_get_by_blockdev(blk->conf.bs);
 | 
					        return NULL;
 | 
				
			||||||
        if (*dinfo->serial) {
 | 
					 | 
				
			||||||
            blk->serial = strdup(dinfo->serial);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,
 | 
					    s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,
 | 
				
			||||||
@ -622,7 +616,6 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
 | 
				
			|||||||
    s->blk = blk;
 | 
					    s->blk = blk;
 | 
				
			||||||
    s->rq = NULL;
 | 
					    s->rq = NULL;
 | 
				
			||||||
    s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
 | 
					    s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
 | 
				
			||||||
    bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
 | 
					    s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,7 @@
 | 
				
			|||||||
#define _QEMU_VIRTIO_BLK_H
 | 
					#define _QEMU_VIRTIO_BLK_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "virtio.h"
 | 
					#include "virtio.h"
 | 
				
			||||||
#include "block.h"
 | 
					#include "hw/block-common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* from Linux's linux/virtio_blk.h */
 | 
					/* from Linux's linux/virtio_blk.h */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -887,6 +887,7 @@ static int virtio_balloon_exit_pci(PCIDevice *pci_dev)
 | 
				
			|||||||
static Property virtio_blk_properties[] = {
 | 
					static Property virtio_blk_properties[] = {
 | 
				
			||||||
    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
 | 
					    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
 | 
				
			||||||
    DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, blk.conf),
 | 
					    DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, blk.conf),
 | 
				
			||||||
 | 
					    DEFINE_BLOCK_CHS_PROPERTIES(VirtIOPCIProxy, blk.conf),
 | 
				
			||||||
    DEFINE_PROP_STRING("serial", VirtIOPCIProxy, blk.serial),
 | 
					    DEFINE_PROP_STRING("serial", VirtIOPCIProxy, blk.serial),
 | 
				
			||||||
#ifdef __linux__
 | 
					#ifdef __linux__
 | 
				
			||||||
    DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true),
 | 
					    DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true),
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,6 @@
 | 
				
			|||||||
#include "net.h"
 | 
					#include "net.h"
 | 
				
			||||||
#include "qdev.h"
 | 
					#include "qdev.h"
 | 
				
			||||||
#include "sysemu.h"
 | 
					#include "sysemu.h"
 | 
				
			||||||
#include "block.h"
 | 
					 | 
				
			||||||
#include "event_notifier.h"
 | 
					#include "event_notifier.h"
 | 
				
			||||||
#ifdef CONFIG_LINUX
 | 
					#ifdef CONFIG_LINUX
 | 
				
			||||||
#include "9p.h"
 | 
					#include "9p.h"
 | 
				
			||||||
 | 
				
			|||||||
@ -670,6 +670,7 @@ static int readv_f(int argc, char **argv)
 | 
				
			|||||||
    print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
 | 
					    print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
 | 
					    qemu_iovec_destroy(&qiov);
 | 
				
			||||||
    qemu_io_free(buf);
 | 
					    qemu_io_free(buf);
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -928,6 +929,7 @@ static int writev_f(int argc, char **argv)
 | 
				
			|||||||
    t2 = tsub(t2, t1);
 | 
					    t2 = tsub(t2, t1);
 | 
				
			||||||
    print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
 | 
					    print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
 | 
					    qemu_iovec_destroy(&qiov);
 | 
				
			||||||
    qemu_io_free(buf);
 | 
					    qemu_io_free(buf);
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1126,6 +1128,7 @@ static void aio_write_done(void *opaque, int ret)
 | 
				
			|||||||
                 ctx->qiov.size, 1, ctx->Cflag);
 | 
					                 ctx->qiov.size, 1, ctx->Cflag);
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
    qemu_io_free(ctx->buf);
 | 
					    qemu_io_free(ctx->buf);
 | 
				
			||||||
 | 
					    qemu_iovec_destroy(&ctx->qiov);
 | 
				
			||||||
    g_free(ctx);
 | 
					    g_free(ctx);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1166,6 +1169,7 @@ static void aio_read_done(void *opaque, int ret)
 | 
				
			|||||||
                 ctx->qiov.size, 1, ctx->Cflag);
 | 
					                 ctx->qiov.size, 1, ctx->Cflag);
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
    qemu_io_free(ctx->buf);
 | 
					    qemu_io_free(ctx->buf);
 | 
				
			||||||
 | 
					    qemu_iovec_destroy(&ctx->qiov);
 | 
				
			||||||
    g_free(ctx);
 | 
					    g_free(ctx);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -21,6 +21,7 @@ check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 | 
				
			|||||||
# All QTests for now are POSIX-only, but the dependencies are
 | 
					# All QTests for now are POSIX-only, but the dependencies are
 | 
				
			||||||
# really in libqtest, not in the testcases themselves.
 | 
					# really in libqtest, not in the testcases themselves.
 | 
				
			||||||
check-qtest-i386-y = tests/fdc-test$(EXESUF)
 | 
					check-qtest-i386-y = tests/fdc-test$(EXESUF)
 | 
				
			||||||
 | 
					check-qtest-i386-y += tests/hd-geo-test$(EXESUF)
 | 
				
			||||||
check-qtest-i386-y += tests/rtc-test$(EXESUF)
 | 
					check-qtest-i386-y += tests/rtc-test$(EXESUF)
 | 
				
			||||||
check-qtest-x86_64-y = $(check-qtest-i386-y)
 | 
					check-qtest-x86_64-y = $(check-qtest-i386-y)
 | 
				
			||||||
check-qtest-sparc-y = tests/m48t59-test$(EXESUF)
 | 
					check-qtest-sparc-y = tests/m48t59-test$(EXESUF)
 | 
				
			||||||
@ -72,6 +73,7 @@ tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(
 | 
				
			|||||||
tests/rtc-test$(EXESUF): tests/rtc-test.o $(trace-obj-y)
 | 
					tests/rtc-test$(EXESUF): tests/rtc-test.o $(trace-obj-y)
 | 
				
			||||||
tests/m48t59-test$(EXESUF): tests/m48t59-test.o $(trace-obj-y)
 | 
					tests/m48t59-test$(EXESUF): tests/m48t59-test.o $(trace-obj-y)
 | 
				
			||||||
tests/fdc-test$(EXESUF): tests/fdc-test.o tests/libqtest.o $(trace-obj-y)
 | 
					tests/fdc-test$(EXESUF): tests/fdc-test.o tests/libqtest.o $(trace-obj-y)
 | 
				
			||||||
 | 
					tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o tests/libqtest.o $(trace-obj-y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# QTest rules
 | 
					# QTest rules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -47,9 +47,11 @@ enum {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
    CMD_SENSE_INT   = 0x08,
 | 
					    CMD_SENSE_INT           = 0x08,
 | 
				
			||||||
    CMD_SEEK        = 0x0f,
 | 
					    CMD_SEEK                = 0x0f,
 | 
				
			||||||
    CMD_READ        = 0xe6,
 | 
					    CMD_READ                = 0xe6,
 | 
				
			||||||
 | 
					    CMD_RELATIVE_SEEK_OUT   = 0x8f,
 | 
				
			||||||
 | 
					    CMD_RELATIVE_SEEK_IN    = 0xcf,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
@ -91,12 +93,20 @@ static uint8_t floppy_recv(void)
 | 
				
			|||||||
    return inb(FLOPPY_BASE + reg_fifo);
 | 
					    return inb(FLOPPY_BASE + reg_fifo);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ack_irq(void)
 | 
					/* pcn: Present Cylinder Number */
 | 
				
			||||||
 | 
					static void ack_irq(uint8_t *pcn)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_assert(get_irq(FLOPPY_IRQ));
 | 
					    g_assert(get_irq(FLOPPY_IRQ));
 | 
				
			||||||
    floppy_send(CMD_SENSE_INT);
 | 
					    floppy_send(CMD_SENSE_INT);
 | 
				
			||||||
    floppy_recv();
 | 
					    floppy_recv();
 | 
				
			||||||
    floppy_recv();
 | 
					
 | 
				
			||||||
 | 
					    ret = floppy_recv();
 | 
				
			||||||
 | 
					    if (pcn != NULL) {
 | 
				
			||||||
 | 
					        *pcn = ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_assert(!get_irq(FLOPPY_IRQ));
 | 
					    g_assert(!get_irq(FLOPPY_IRQ));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -156,7 +166,7 @@ static uint8_t send_read_command(void)
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void send_step_pulse(int cyl)
 | 
					static void send_seek(int cyl)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int drive = 0;
 | 
					    int drive = 0;
 | 
				
			||||||
    int head = 0;
 | 
					    int head = 0;
 | 
				
			||||||
@ -165,7 +175,7 @@ static void send_step_pulse(int cyl)
 | 
				
			|||||||
    floppy_send(head << 2 | drive);
 | 
					    floppy_send(head << 2 | drive);
 | 
				
			||||||
    g_assert(!get_irq(FLOPPY_IRQ));
 | 
					    g_assert(!get_irq(FLOPPY_IRQ));
 | 
				
			||||||
    floppy_send(cyl);
 | 
					    floppy_send(cyl);
 | 
				
			||||||
    ack_irq();
 | 
					    ack_irq(NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint8_t cmos_read(uint8_t reg)
 | 
					static uint8_t cmos_read(uint8_t reg)
 | 
				
			||||||
@ -192,7 +202,7 @@ static void test_no_media_on_start(void)
 | 
				
			|||||||
    assert_bit_set(dir, DSKCHG);
 | 
					    assert_bit_set(dir, DSKCHG);
 | 
				
			||||||
    dir = inb(FLOPPY_BASE + reg_dir);
 | 
					    dir = inb(FLOPPY_BASE + reg_dir);
 | 
				
			||||||
    assert_bit_set(dir, DSKCHG);
 | 
					    assert_bit_set(dir, DSKCHG);
 | 
				
			||||||
    send_step_pulse(1);
 | 
					    send_seek(1);
 | 
				
			||||||
    dir = inb(FLOPPY_BASE + reg_dir);
 | 
					    dir = inb(FLOPPY_BASE + reg_dir);
 | 
				
			||||||
    assert_bit_set(dir, DSKCHG);
 | 
					    assert_bit_set(dir, DSKCHG);
 | 
				
			||||||
    dir = inb(FLOPPY_BASE + reg_dir);
 | 
					    dir = inb(FLOPPY_BASE + reg_dir);
 | 
				
			||||||
@ -223,14 +233,14 @@ static void test_media_change(void)
 | 
				
			|||||||
    dir = inb(FLOPPY_BASE + reg_dir);
 | 
					    dir = inb(FLOPPY_BASE + reg_dir);
 | 
				
			||||||
    assert_bit_set(dir, DSKCHG);
 | 
					    assert_bit_set(dir, DSKCHG);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    send_step_pulse(0);
 | 
					    send_seek(0);
 | 
				
			||||||
    dir = inb(FLOPPY_BASE + reg_dir);
 | 
					    dir = inb(FLOPPY_BASE + reg_dir);
 | 
				
			||||||
    assert_bit_set(dir, DSKCHG);
 | 
					    assert_bit_set(dir, DSKCHG);
 | 
				
			||||||
    dir = inb(FLOPPY_BASE + reg_dir);
 | 
					    dir = inb(FLOPPY_BASE + reg_dir);
 | 
				
			||||||
    assert_bit_set(dir, DSKCHG);
 | 
					    assert_bit_set(dir, DSKCHG);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Step to next track should clear DSKCHG bit. */
 | 
					    /* Step to next track should clear DSKCHG bit. */
 | 
				
			||||||
    send_step_pulse(1);
 | 
					    send_seek(1);
 | 
				
			||||||
    dir = inb(FLOPPY_BASE + reg_dir);
 | 
					    dir = inb(FLOPPY_BASE + reg_dir);
 | 
				
			||||||
    assert_bit_clear(dir, DSKCHG);
 | 
					    assert_bit_clear(dir, DSKCHG);
 | 
				
			||||||
    dir = inb(FLOPPY_BASE + reg_dir);
 | 
					    dir = inb(FLOPPY_BASE + reg_dir);
 | 
				
			||||||
@ -246,13 +256,13 @@ static void test_media_change(void)
 | 
				
			|||||||
    dir = inb(FLOPPY_BASE + reg_dir);
 | 
					    dir = inb(FLOPPY_BASE + reg_dir);
 | 
				
			||||||
    assert_bit_set(dir, DSKCHG);
 | 
					    assert_bit_set(dir, DSKCHG);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    send_step_pulse(0);
 | 
					    send_seek(0);
 | 
				
			||||||
    dir = inb(FLOPPY_BASE + reg_dir);
 | 
					    dir = inb(FLOPPY_BASE + reg_dir);
 | 
				
			||||||
    assert_bit_set(dir, DSKCHG);
 | 
					    assert_bit_set(dir, DSKCHG);
 | 
				
			||||||
    dir = inb(FLOPPY_BASE + reg_dir);
 | 
					    dir = inb(FLOPPY_BASE + reg_dir);
 | 
				
			||||||
    assert_bit_set(dir, DSKCHG);
 | 
					    assert_bit_set(dir, DSKCHG);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    send_step_pulse(1);
 | 
					    send_seek(1);
 | 
				
			||||||
    dir = inb(FLOPPY_BASE + reg_dir);
 | 
					    dir = inb(FLOPPY_BASE + reg_dir);
 | 
				
			||||||
    assert_bit_set(dir, DSKCHG);
 | 
					    assert_bit_set(dir, DSKCHG);
 | 
				
			||||||
    dir = inb(FLOPPY_BASE + reg_dir);
 | 
					    dir = inb(FLOPPY_BASE + reg_dir);
 | 
				
			||||||
@ -281,6 +291,35 @@ static void test_sense_interrupt(void)
 | 
				
			|||||||
    floppy_recv();
 | 
					    floppy_recv();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_relative_seek(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t drive = 0;
 | 
				
			||||||
 | 
					    uint8_t head = 0;
 | 
				
			||||||
 | 
					    uint8_t cyl = 1;
 | 
				
			||||||
 | 
					    uint8_t pcn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Send seek to track 0 */
 | 
				
			||||||
 | 
					    send_seek(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Send relative seek to increase track by 1 */
 | 
				
			||||||
 | 
					    floppy_send(CMD_RELATIVE_SEEK_IN);
 | 
				
			||||||
 | 
					    floppy_send(head << 2 | drive);
 | 
				
			||||||
 | 
					    g_assert(!get_irq(FLOPPY_IRQ));
 | 
				
			||||||
 | 
					    floppy_send(cyl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ack_irq(&pcn);
 | 
				
			||||||
 | 
					    g_assert(pcn == 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Send relative seek to decrease track by 1 */
 | 
				
			||||||
 | 
					    floppy_send(CMD_RELATIVE_SEEK_OUT);
 | 
				
			||||||
 | 
					    floppy_send(head << 2 | drive);
 | 
				
			||||||
 | 
					    g_assert(!get_irq(FLOPPY_IRQ));
 | 
				
			||||||
 | 
					    floppy_send(cyl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ack_irq(&pcn);
 | 
				
			||||||
 | 
					    g_assert(pcn == 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* success if no crash or abort */
 | 
					/* success if no crash or abort */
 | 
				
			||||||
static void fuzz_registers(void)
 | 
					static void fuzz_registers(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -329,6 +368,7 @@ int main(int argc, char **argv)
 | 
				
			|||||||
    qtest_add_func("/fdc/read_without_media", test_read_without_media);
 | 
					    qtest_add_func("/fdc/read_without_media", test_read_without_media);
 | 
				
			||||||
    qtest_add_func("/fdc/media_change", test_media_change);
 | 
					    qtest_add_func("/fdc/media_change", test_media_change);
 | 
				
			||||||
    qtest_add_func("/fdc/sense_interrupt", test_sense_interrupt);
 | 
					    qtest_add_func("/fdc/sense_interrupt", test_sense_interrupt);
 | 
				
			||||||
 | 
					    qtest_add_func("/fdc/relative_seek", test_relative_seek);
 | 
				
			||||||
    qtest_add_func("/fdc/fuzz-registers", fuzz_registers);
 | 
					    qtest_add_func("/fdc/fuzz-registers", fuzz_registers);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = g_test_run();
 | 
					    ret = g_test_run();
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										428
									
								
								tests/hd-geo-test.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										428
									
								
								tests/hd-geo-test.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,428 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Hard disk geometry test cases.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (c) 2012 Red Hat Inc.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Authors:
 | 
				
			||||||
 | 
					 *  Markus Armbruster <armbru@redhat.com>,
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 | 
				
			||||||
 | 
					 * See the COPYING file in the top-level directory.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Covers only IDE and tests only CMOS contents.  Better than nothing.
 | 
				
			||||||
 | 
					 * Improvements welcome.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <glib.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include "qemu-common.h"
 | 
				
			||||||
 | 
					#include "libqtest.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char test_image[] = "/tmp/qtest.XXXXXX";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char *create_test_img(int secs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    char *template = strdup("/tmp/qtest.XXXXXX");
 | 
				
			||||||
 | 
					    int fd, ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fd = mkstemp(template);
 | 
				
			||||||
 | 
					    g_assert(fd >= 0);
 | 
				
			||||||
 | 
					    ret = ftruncate(fd, (off_t)secs * 512);
 | 
				
			||||||
 | 
					    g_assert(ret == 0);
 | 
				
			||||||
 | 
					    close(fd);
 | 
				
			||||||
 | 
					    return template;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    int cyls, heads, secs, trans;
 | 
				
			||||||
 | 
					} CHST;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum {
 | 
				
			||||||
 | 
					    mbr_blank, mbr_lba, mbr_chs,
 | 
				
			||||||
 | 
					    mbr_last
 | 
				
			||||||
 | 
					} MBRcontents;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum {
 | 
				
			||||||
 | 
					    /* order is relevant */
 | 
				
			||||||
 | 
					    backend_small, backend_large, backend_empty,
 | 
				
			||||||
 | 
					    backend_last
 | 
				
			||||||
 | 
					} Backend;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const int img_secs[backend_last] = {
 | 
				
			||||||
 | 
					    [backend_small] = 61440,
 | 
				
			||||||
 | 
					    [backend_large] = 8388608,
 | 
				
			||||||
 | 
					    [backend_empty] = -1,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const CHST hd_chst[backend_last][mbr_last] = {
 | 
				
			||||||
 | 
					    [backend_small] = {
 | 
				
			||||||
 | 
					        [mbr_blank] = { 60, 16, 63, 0 },
 | 
				
			||||||
 | 
					        [mbr_lba]   = { 60, 16, 63, 2 },
 | 
				
			||||||
 | 
					        [mbr_chs]   = { 60, 16, 63, 0 }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    [backend_large] = {
 | 
				
			||||||
 | 
					        [mbr_blank] = { 8322, 16, 63, 1 },
 | 
				
			||||||
 | 
					        [mbr_lba]   = { 8322, 16, 63, 1 },
 | 
				
			||||||
 | 
					        [mbr_chs]   = { 8322, 16, 63, 0 }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *img_file_name[backend_last];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const CHST *cur_ide[4];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool is_hd(const CHST *expected_chst)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return expected_chst && expected_chst->cyls;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_cmos_byte(int reg, int expected)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    enum { cmos_base = 0x70 };
 | 
				
			||||||
 | 
					    int actual;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    outb(cmos_base + 0, reg);
 | 
				
			||||||
 | 
					    actual = inb(cmos_base + 1);
 | 
				
			||||||
 | 
					    g_assert(actual == expected);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_cmos_bytes(int reg0, int n, uint8_t expected[])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < 9; i++) {
 | 
				
			||||||
 | 
					        test_cmos_byte(reg0 + i, expected[i]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_cmos_disk_data(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    test_cmos_byte(0x12,
 | 
				
			||||||
 | 
					                   (is_hd(cur_ide[0]) ? 0xf0 : 0) |
 | 
				
			||||||
 | 
					                   (is_hd(cur_ide[1]) ? 0x0f : 0));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_cmos_drive_cyl(int reg0, const CHST *expected_chst)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (is_hd(expected_chst)) {
 | 
				
			||||||
 | 
					        int c = expected_chst->cyls;
 | 
				
			||||||
 | 
					        int h = expected_chst->heads;
 | 
				
			||||||
 | 
					        int s = expected_chst->secs;
 | 
				
			||||||
 | 
					        uint8_t expected_bytes[9] = {
 | 
				
			||||||
 | 
					            c & 0xff, c >> 8, h, 0xff, 0xff, 0xc0 | ((h > 8) << 3),
 | 
				
			||||||
 | 
					            c & 0xff, c >> 8, s
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        test_cmos_bytes(reg0, 9, expected_bytes);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (i = 0; i < 9; i++) {
 | 
				
			||||||
 | 
					            test_cmos_byte(reg0 + i, 0);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_cmos_drive1(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    test_cmos_byte(0x19, is_hd(cur_ide[0]) ? 47 : 0);
 | 
				
			||||||
 | 
					    test_cmos_drive_cyl(0x1b, cur_ide[0]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_cmos_drive2(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    test_cmos_byte(0x1a, is_hd(cur_ide[1]) ? 47 : 0);
 | 
				
			||||||
 | 
					    test_cmos_drive_cyl(0x24, cur_ide[1]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_cmos_disktransflag(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int val, i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    val = 0;
 | 
				
			||||||
 | 
					    for (i = 0; i < ARRAY_SIZE(cur_ide); i++) {
 | 
				
			||||||
 | 
					        if (is_hd(cur_ide[i])) {
 | 
				
			||||||
 | 
					            val |= cur_ide[i]->trans << (2 * i);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    test_cmos_byte(0x39, val);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_cmos(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    test_cmos_disk_data();
 | 
				
			||||||
 | 
					    test_cmos_drive1();
 | 
				
			||||||
 | 
					    test_cmos_drive2();
 | 
				
			||||||
 | 
					    test_cmos_disktransflag();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int append_arg(int argc, char *argv[], int argv_sz, char *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    g_assert(argc + 1 < argv_sz);
 | 
				
			||||||
 | 
					    argv[argc++] = arg;
 | 
				
			||||||
 | 
					    argv[argc] = NULL;
 | 
				
			||||||
 | 
					    return argc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int setup_common(char *argv[], int argv_sz)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    memset(cur_ide, 0, sizeof(cur_ide));
 | 
				
			||||||
 | 
					    return append_arg(0, argv, argv_sz,
 | 
				
			||||||
 | 
					                      g_strdup("-nodefaults -display none"));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void setup_mbr(int img_idx, MBRcontents mbr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static const uint8_t part_lba[16] = {
 | 
				
			||||||
 | 
					        /* chs 0,1,1 (lba 63) to chs 0,127,63 (8001 sectors) */
 | 
				
			||||||
 | 
					        0x80, 1, 1, 0, 6, 127, 63, 0, 63, 0, 0, 0, 0x41, 0x1F, 0, 0,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static const uint8_t part_chs[16] = {
 | 
				
			||||||
 | 
					        /* chs 0,1,1 (lba 63) to chs 7,15,63 (8001 sectors) */
 | 
				
			||||||
 | 
					        0x80, 1, 1, 0, 6,  15, 63, 7, 63, 0, 0, 0, 0x41, 0x1F, 0, 0,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    uint8_t buf[512];
 | 
				
			||||||
 | 
					    int fd, ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memset(buf, 0, sizeof(buf));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (mbr != mbr_blank) {
 | 
				
			||||||
 | 
					        buf[0x1fe] = 0x55;
 | 
				
			||||||
 | 
					        buf[0x1ff] = 0xAA;
 | 
				
			||||||
 | 
					        memcpy(buf + 0x1BE, mbr == mbr_lba ? part_lba : part_chs, 16);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fd = open(img_file_name[img_idx], O_WRONLY);
 | 
				
			||||||
 | 
					    g_assert(fd >= 0);
 | 
				
			||||||
 | 
					    ret = write(fd, buf, sizeof(buf));
 | 
				
			||||||
 | 
					    g_assert(ret == sizeof(buf));
 | 
				
			||||||
 | 
					    close(fd);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int setup_ide(int argc, char *argv[], int argv_sz,
 | 
				
			||||||
 | 
					                     int ide_idx, const char *dev, int img_idx,
 | 
				
			||||||
 | 
					                     MBRcontents mbr, const char *opts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    char *s1, *s2, *s3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s1 = g_strdup_printf("-drive id=drive%d,if=%s",
 | 
				
			||||||
 | 
					                         ide_idx, dev ? "none" : "ide");
 | 
				
			||||||
 | 
					    s2 = dev ? g_strdup("") : g_strdup_printf(",index=%d", ide_idx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (img_secs[img_idx] >= 0) {
 | 
				
			||||||
 | 
					        setup_mbr(img_idx, mbr);
 | 
				
			||||||
 | 
					        s3 = g_strdup_printf(",file=%s", img_file_name[img_idx]);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        s3 = g_strdup(",media=cdrom");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    argc = append_arg(argc, argv, argv_sz,
 | 
				
			||||||
 | 
					                      g_strdup_printf("%s%s%s%s", s1, s2, s3, opts));
 | 
				
			||||||
 | 
					    g_free(s1);
 | 
				
			||||||
 | 
					    g_free(s2);
 | 
				
			||||||
 | 
					    g_free(s3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (dev) {
 | 
				
			||||||
 | 
					        argc = append_arg(argc, argv, argv_sz,
 | 
				
			||||||
 | 
					                          g_strdup_printf("-device %s,drive=drive%d,"
 | 
				
			||||||
 | 
					                                          "bus=ide.%d,unit=%d",
 | 
				
			||||||
 | 
					                                          dev, ide_idx,
 | 
				
			||||||
 | 
					                                          ide_idx / 2, ide_idx % 2));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return argc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Test case: no IDE devices
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void test_ide_none(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    char *argv[256];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setup_common(argv, ARRAY_SIZE(argv));
 | 
				
			||||||
 | 
					    qtest_start(g_strjoinv(" ", argv));
 | 
				
			||||||
 | 
					    test_cmos();
 | 
				
			||||||
 | 
					    qtest_quit(global_qtest);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_ide_mbr(bool use_device, MBRcontents mbr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    char *argv[256];
 | 
				
			||||||
 | 
					    int argc;
 | 
				
			||||||
 | 
					    Backend i;
 | 
				
			||||||
 | 
					    const char *dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    argc = setup_common(argv, ARRAY_SIZE(argv));
 | 
				
			||||||
 | 
					    for (i = 0; i < backend_last; i++) {
 | 
				
			||||||
 | 
					        cur_ide[i] = &hd_chst[i][mbr];
 | 
				
			||||||
 | 
					        dev = use_device ? (is_hd(cur_ide[i]) ? "ide-hd" : "ide-cd") : NULL;
 | 
				
			||||||
 | 
					        argc = setup_ide(argc, argv, ARRAY_SIZE(argv), i, dev, i, mbr, "");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    qtest_start(g_strjoinv(" ", argv));
 | 
				
			||||||
 | 
					    test_cmos();
 | 
				
			||||||
 | 
					    qtest_quit(global_qtest);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Test case: IDE devices (if=ide) with blank MBRs
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void test_ide_drive_mbr_blank(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    test_ide_mbr(false, mbr_blank);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Test case: IDE devices (if=ide) with MBRs indicating LBA is in use
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void test_ide_drive_mbr_lba(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    test_ide_mbr(false, mbr_lba);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Test case: IDE devices (if=ide) with MBRs indicating CHS is in use
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void test_ide_drive_mbr_chs(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    test_ide_mbr(false, mbr_chs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Test case: IDE devices (if=none) with blank MBRs
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void test_ide_device_mbr_blank(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    test_ide_mbr(true, mbr_blank);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Test case: IDE devices (if=none) with MBRs indicating LBA is in use
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void test_ide_device_mbr_lba(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    test_ide_mbr(true, mbr_lba);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Test case: IDE devices (if=none) with MBRs indicating CHS is in use
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void test_ide_device_mbr_chs(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    test_ide_mbr(true, mbr_chs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_ide_drive_user(const char *dev, bool trans)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    char *argv[256], *opts;
 | 
				
			||||||
 | 
					    int argc;
 | 
				
			||||||
 | 
					    int secs = img_secs[backend_small];
 | 
				
			||||||
 | 
					    const CHST expected_chst = { secs / (4 * 32) , 4, 32, trans };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    argc = setup_common(argv, ARRAY_SIZE(argv));
 | 
				
			||||||
 | 
					    opts = g_strdup_printf("%s,%s%scyls=%d,heads=%d,secs=%d",
 | 
				
			||||||
 | 
					                           dev ?: "",
 | 
				
			||||||
 | 
					                           trans && dev ? "bios-chs-" : "",
 | 
				
			||||||
 | 
					                           trans ? "trans=lba," : "",
 | 
				
			||||||
 | 
					                           expected_chst.cyls, expected_chst.heads,
 | 
				
			||||||
 | 
					                           expected_chst.secs);
 | 
				
			||||||
 | 
					    cur_ide[0] = &expected_chst;
 | 
				
			||||||
 | 
					    argc = setup_ide(argc, argv, ARRAY_SIZE(argv),
 | 
				
			||||||
 | 
					                     0, dev ? opts : NULL, backend_small, mbr_chs,
 | 
				
			||||||
 | 
					                     dev ? "" : opts);
 | 
				
			||||||
 | 
					    g_free(opts);
 | 
				
			||||||
 | 
					    qtest_start(g_strjoinv(" ", argv));
 | 
				
			||||||
 | 
					    test_cmos();
 | 
				
			||||||
 | 
					    qtest_quit(global_qtest);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Test case: IDE device (if=ide) with explicit CHS
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void test_ide_drive_user_chs(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    test_ide_drive_user(NULL, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Test case: IDE device (if=ide) with explicit CHS and translation
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void test_ide_drive_user_chst(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    test_ide_drive_user(NULL, true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Test case: IDE device (if=none) with explicit CHS
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void test_ide_device_user_chs(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    test_ide_drive_user("ide-hd", false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Test case: IDE device (if=none) with explicit CHS and translation
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void test_ide_device_user_chst(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    test_ide_drive_user("ide-hd", true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Test case: IDE devices (if=ide), but use index=0 for CD-ROM
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void test_ide_drive_cd_0(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    char *argv[256];
 | 
				
			||||||
 | 
					    int argc, ide_idx;
 | 
				
			||||||
 | 
					    Backend i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    argc = setup_common(argv, ARRAY_SIZE(argv));
 | 
				
			||||||
 | 
					    for (i = 0; i <= backend_empty; i++) {
 | 
				
			||||||
 | 
					        ide_idx = backend_empty - i;
 | 
				
			||||||
 | 
					        cur_ide[ide_idx] = &hd_chst[i][mbr_blank];
 | 
				
			||||||
 | 
					        argc = setup_ide(argc, argv, ARRAY_SIZE(argv),
 | 
				
			||||||
 | 
					                         ide_idx, NULL, i, mbr_blank, "");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    qtest_start(g_strjoinv(" ", argv));
 | 
				
			||||||
 | 
					    test_cmos();
 | 
				
			||||||
 | 
					    qtest_quit(global_qtest);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char **argv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Backend i;
 | 
				
			||||||
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_test_init(&argc, &argv, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < backend_last; i++) {
 | 
				
			||||||
 | 
					        if (img_secs[i] >= 0) {
 | 
				
			||||||
 | 
					            img_file_name[i] = create_test_img(img_secs[i]);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            img_file_name[i] = NULL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qtest_add_func("hd-geo/ide/none", test_ide_none);
 | 
				
			||||||
 | 
					    qtest_add_func("hd-geo/ide/drive/mbr/blank", test_ide_drive_mbr_blank);
 | 
				
			||||||
 | 
					    qtest_add_func("hd-geo/ide/drive/mbr/lba", test_ide_drive_mbr_lba);
 | 
				
			||||||
 | 
					    qtest_add_func("hd-geo/ide/drive/mbr/chs", test_ide_drive_mbr_chs);
 | 
				
			||||||
 | 
					    qtest_add_func("hd-geo/ide/drive/user/chs", test_ide_drive_user_chs);
 | 
				
			||||||
 | 
					    qtest_add_func("hd-geo/ide/drive/user/chst", test_ide_drive_user_chst);
 | 
				
			||||||
 | 
					    qtest_add_func("hd-geo/ide/drive/cd_0", test_ide_drive_cd_0);
 | 
				
			||||||
 | 
					    qtest_add_func("hd-geo/ide/device/mbr/blank", test_ide_device_mbr_blank);
 | 
				
			||||||
 | 
					    qtest_add_func("hd-geo/ide/device/mbr/lba", test_ide_device_mbr_lba);
 | 
				
			||||||
 | 
					    qtest_add_func("hd-geo/ide/device/mbr/chs", test_ide_device_mbr_chs);
 | 
				
			||||||
 | 
					    qtest_add_func("hd-geo/ide/device/user/chs", test_ide_device_user_chs);
 | 
				
			||||||
 | 
					    qtest_add_func("hd-geo/ide/device/user/chst", test_ide_device_user_chst);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = g_test_run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < backend_last; i++) {
 | 
				
			||||||
 | 
					        unlink(img_file_name[i]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -41,6 +41,7 @@ sortme=false
 | 
				
			|||||||
expunge=true
 | 
					expunge=true
 | 
				
			||||||
have_test_arg=false
 | 
					have_test_arg=false
 | 
				
			||||||
randomize=false
 | 
					randomize=false
 | 
				
			||||||
 | 
					valgrind=false
 | 
				
			||||||
rm -f $tmp.list $tmp.tmp $tmp.sed
 | 
					rm -f $tmp.list $tmp.tmp $tmp.sed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export IMGFMT=raw
 | 
					export IMGFMT=raw
 | 
				
			||||||
@ -212,6 +213,11 @@ testlist options
 | 
				
			|||||||
	    xpand=false
 | 
						    xpand=false
 | 
				
			||||||
	    ;;
 | 
						    ;;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    -valgrind)
 | 
				
			||||||
 | 
					        valgrind=true
 | 
				
			||||||
 | 
						    xpand=false
 | 
				
			||||||
 | 
					        ;;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	-g)	# -g group ... pick from group file
 | 
						-g)	# -g group ... pick from group file
 | 
				
			||||||
	    group=true
 | 
						    group=true
 | 
				
			||||||
	    xpand=false
 | 
						    xpand=false
 | 
				
			||||||
@ -345,3 +351,8 @@ fi
 | 
				
			|||||||
[ "$QEMU" = "" ] && _fatal "qemu not found"
 | 
					[ "$QEMU" = "" ] && _fatal "qemu not found"
 | 
				
			||||||
[ "$QEMU_IMG" = "" ] && _fatal "qemu-img not found"
 | 
					[ "$QEMU_IMG" = "" ] && _fatal "qemu-img not found"
 | 
				
			||||||
[ "$QEMU_IO" = "" ] && _fatal "qemu-img not found"
 | 
					[ "$QEMU_IO" = "" ] && _fatal "qemu-img not found"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if $valgrind; then
 | 
				
			||||||
 | 
					    export REAL_QEMU_IO="$QEMU_IO_PROG"
 | 
				
			||||||
 | 
					    export QEMU_IO_PROG=valgrind_qemu_io
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
				
			|||||||
@ -53,6 +53,16 @@ else
 | 
				
			|||||||
    TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
 | 
					    TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function valgrind_qemu_io()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    valgrind --log-file=/tmp/$$.valgrind --error-exitcode=99 $REAL_QEMU_IO "$@"
 | 
				
			||||||
 | 
					    if [ $? != 0 ]; then
 | 
				
			||||||
 | 
					        cat /tmp/$$.valgrind
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    rm -f /tmp/$$.valgrind
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_optstr_add()
 | 
					_optstr_add()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if [ -n "$1" ]; then
 | 
					    if [ -n "$1" ]; then
 | 
				
			||||||
 | 
				
			|||||||
@ -141,6 +141,10 @@ ecc_mem_readl_ecr1(uint32_t ret) "Read event count 2 %08x"
 | 
				
			|||||||
ecc_diag_mem_writeb(uint64_t addr, uint32_t val) "Write diagnostic %"PRId64" = %02x"
 | 
					ecc_diag_mem_writeb(uint64_t addr, uint32_t val) "Write diagnostic %"PRId64" = %02x"
 | 
				
			||||||
ecc_diag_mem_readb(uint64_t addr, uint32_t ret) "Read diagnostic %"PRId64"= %02x"
 | 
					ecc_diag_mem_readb(uint64_t addr, uint32_t ret) "Read diagnostic %"PRId64"= %02x"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# hw/hd-geometry.c
 | 
				
			||||||
 | 
					hd_geometry_lchs_guess(void *bs, int cyls, int heads, int secs) "bs %p LCHS %d %d %d"
 | 
				
			||||||
 | 
					hd_geometry_guess(void *bs, uint32_t cyls, uint32_t heads, uint32_t secs, int trans) "bs %p CHS %u %u %u trans %d"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# hw/jazz-led.c
 | 
					# hw/jazz-led.c
 | 
				
			||||||
jazz_led_read(uint64_t addr, uint8_t val) "read addr=0x%"PRIx64": 0x%x"
 | 
					jazz_led_read(uint64_t addr, uint8_t val) "read addr=0x%"PRIx64": 0x%x"
 | 
				
			||||||
jazz_led_write(uint64_t addr, uint8_t new) "write addr=0x%"PRIx64": 0x%x"
 | 
					jazz_led_write(uint64_t addr, uint8_t new) "write addr=0x%"PRIx64": 0x%x"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								vl.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								vl.c
									
									
									
									
									
								
							@ -130,8 +130,8 @@ int main(int argc, char **argv)
 | 
				
			|||||||
#include "qemu-timer.h"
 | 
					#include "qemu-timer.h"
 | 
				
			||||||
#include "qemu-char.h"
 | 
					#include "qemu-char.h"
 | 
				
			||||||
#include "cache-utils.h"
 | 
					#include "cache-utils.h"
 | 
				
			||||||
#include "block.h"
 | 
					 | 
				
			||||||
#include "blockdev.h"
 | 
					#include "blockdev.h"
 | 
				
			||||||
 | 
					#include "hw/block-common.h"
 | 
				
			||||||
#include "block-migration.h"
 | 
					#include "block-migration.h"
 | 
				
			||||||
#include "dma.h"
 | 
					#include "dma.h"
 | 
				
			||||||
#include "audio/audio.h"
 | 
					#include "audio/audio.h"
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user