1 /* 2 * Common code for block device models 3 * 4 * Copyright (C) 2012 Red Hat, Inc. 5 * 6 * This work is licensed under the terms of the GNU GPL, version 2 or 7 * later. See the COPYING file in the top-level directory. 8 */ 9 10 #include "qemu/osdep.h" 11 #include "sysemu/blockdev.h" 12 #include "sysemu/block-backend.h" 13 #include "hw/block/block.h" 14 #include "qemu/error-report.h" 15 16 void blkconf_serial(BlockConf *conf, char **serial) 17 { 18 DriveInfo *dinfo; 19 20 if (!*serial) { 21 /* try to fall back to value set with legacy -drive serial=... */ 22 dinfo = blk_legacy_dinfo(conf->blk); 23 if (dinfo) { 24 *serial = g_strdup(dinfo->serial); 25 } 26 } 27 } 28 29 void blkconf_blocksizes(BlockConf *conf) 30 { 31 BlockBackend *blk = conf->blk; 32 BlockSizes blocksizes; 33 int backend_ret; 34 35 backend_ret = blk_probe_blocksizes(blk, &blocksizes); 36 /* fill in detected values if they are not defined via qemu command line */ 37 if (!conf->physical_block_size) { 38 if (!backend_ret) { 39 conf->physical_block_size = blocksizes.phys; 40 } else { 41 conf->physical_block_size = BDRV_SECTOR_SIZE; 42 } 43 } 44 if (!conf->logical_block_size) { 45 if (!backend_ret) { 46 conf->logical_block_size = blocksizes.log; 47 } else { 48 conf->logical_block_size = BDRV_SECTOR_SIZE; 49 } 50 } 51 } 52 53 void blkconf_geometry(BlockConf *conf, int *ptrans, 54 unsigned cyls_max, unsigned heads_max, unsigned secs_max, 55 Error **errp) 56 { 57 DriveInfo *dinfo; 58 59 if (!conf->cyls && !conf->heads && !conf->secs) { 60 /* try to fall back to value set with legacy -drive cyls=... */ 61 dinfo = blk_legacy_dinfo(conf->blk); 62 if (dinfo) { 63 conf->cyls = dinfo->cyls; 64 conf->heads = dinfo->heads; 65 conf->secs = dinfo->secs; 66 if (ptrans) { 67 *ptrans = dinfo->trans; 68 } 69 } 70 } 71 if (!conf->cyls && !conf->heads && !conf->secs) { 72 hd_geometry_guess(conf->blk, 73 &conf->cyls, &conf->heads, &conf->secs, 74 ptrans); 75 } else if (ptrans && *ptrans == BIOS_ATA_TRANSLATION_AUTO) { 76 *ptrans = hd_bios_chs_auto_trans(conf->cyls, conf->heads, conf->secs); 77 } 78 if (conf->cyls || conf->heads || conf->secs) { 79 if (conf->cyls < 1 || conf->cyls > cyls_max) { 80 error_setg(errp, "cyls must be between 1 and %u", cyls_max); 81 return; 82 } 83 if (conf->heads < 1 || conf->heads > heads_max) { 84 error_setg(errp, "heads must be between 1 and %u", heads_max); 85 return; 86 } 87 if (conf->secs < 1 || conf->secs > secs_max) { 88 error_setg(errp, "secs must be between 1 and %u", secs_max); 89 return; 90 } 91 } 92 } 93