From patchwork Tue Jun 26 12:49:34 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 167400 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id C18B1B700D for ; Tue, 26 Jun 2012 22:50:00 +1000 (EST) Received: from localhost ([::1]:34103 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SjVDR-0004DP-In for incoming@patchwork.ozlabs.org; Tue, 26 Jun 2012 08:49:57 -0400 Received: from eggs.gnu.org ([208.118.235.92]:53297) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SjVDF-0004D8-Pa for qemu-devel@nongnu.org; Tue, 26 Jun 2012 08:49:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SjVDA-0005Tz-LH for qemu-devel@nongnu.org; Tue, 26 Jun 2012 08:49:45 -0400 Received: from cantor2.suse.de ([195.135.220.15]:60745 helo=mx2.suse.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SjVDA-0005Ss-CN for qemu-devel@nongnu.org; Tue, 26 Jun 2012 08:49:40 -0400 Received: from relay1.suse.de (unknown [195.135.220.254]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx2.suse.de (Postfix) with ESMTP id 6BCA6A5584; Tue, 26 Jun 2012 14:49:38 +0200 (CEST) From: Alexander Graf To: qemu-devel qemu-devel Date: Tue, 26 Jun 2012 14:49:34 +0200 Message-Id: <1340714974-25489-1-git-send-email-agraf@suse.de> X-Mailer: git-send-email 1.6.0.2 MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4-2.6 X-Received-From: 195.135.220.15 Cc: Kevin Wolf , Markus Armbruster Subject: [Qemu-devel] [PATCH v2] ahci: add -drive support X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org We've had support for creating AHCI devices using -device for a while now, but it's cumbersome to users. We really should provide an easier way for them to leverage the power of AHCI! So let's introduce a new if= option to -drive, giving users the same command line experience as for scsi or ide. Signed-off-by: Alexander Graf --- v1 -> v2: - support more than a single drive per adapter - support index= option - treat IF_AHCI the same as IF_IDE - add is_ata() helper to match AHCI || IDE --- blockdev.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++---- blockdev.h | 7 +++++++ qemu-options.hx | 7 ++++++- vl.c | 2 ++ 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/blockdev.c b/blockdev.c index 9e0a72a..744a886 100644 --- a/blockdev.c +++ b/blockdev.c @@ -32,6 +32,7 @@ static const char *const if_name[IF_COUNT] = { [IF_SD] = "sd", [IF_VIRTIO] = "virtio", [IF_XEN] = "xen", + [IF_AHCI] = "ahci", }; static const int if_max_devs[IF_COUNT] = { @@ -51,6 +52,7 @@ static const int if_max_devs[IF_COUNT] = { */ [IF_IDE] = 2, [IF_SCSI] = 7, + [IF_AHCI] = 6, }; /* @@ -330,15 +332,15 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) max_devs = if_max_devs[type]; if (cyls || heads || secs) { - if (cyls < 1 || (type == IF_IDE && cyls > 16383)) { + if (cyls < 1 || (is_ata(type) && cyls > 16383)) { error_report("invalid physical cyls number"); return NULL; } - if (heads < 1 || (type == IF_IDE && heads > 16)) { + if (heads < 1 || (is_ata(type) && heads > 16)) { error_report("invalid physical heads number"); return NULL; } - if (secs < 1 || (type == IF_IDE && secs > 63)) { + if (secs < 1 || (is_ata(type) && secs > 63)) { error_report("invalid physical secs number"); return NULL; } @@ -516,7 +518,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) } else { /* no id supplied -> create one */ dinfo->id = g_malloc0(32); - if (type == IF_IDE || type == IF_SCSI) + if (is_ata(type) || type == IF_SCSI) mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd"; if (max_devs) snprintf(dinfo->id, 32, "%s%i%s%i", @@ -546,6 +548,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) case IF_IDE: case IF_SCSI: case IF_XEN: + case IF_AHCI: case IF_NONE: switch(media) { case MEDIA_DISK: @@ -628,6 +631,49 @@ err: return NULL; } +static void drive_populate_ahci(void) +{ + int bus; + QemuOpts *opts; + + for (bus = 0; bus <= drive_get_max_bus(IF_AHCI); bus++) { + char devname[] = "ahciXXX"; + int dev; + snprintf(devname, sizeof(devname), "ahci%d", bus); + + /* add ahci host controller */ + opts = qemu_opts_create(qemu_find_opts("device"), devname, 0, NULL); + qemu_opt_set(opts, "driver", "ich9-ahci"); + for (dev = 0; dev < if_max_devs[IF_AHCI]; dev++) { + DriveInfo *dinfo = drive_get(IF_AHCI, bus, dev); + char busname[] = "ahciXXX.XXX"; + + if (!dinfo) { + continue; + } + snprintf(busname, sizeof(busname), "ahci%d.%d", bus, dev); + + /* attach this ata disk to its bus */ + opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0, NULL); + qemu_opt_set(opts, "driver", "ide-drive"); + qemu_opt_set(opts, "bus", busname); + qemu_opt_set(opts, "drive", dinfo->id); + } + } +} + +/* + * This function creates -device options out of IF_xxx elements, + * so that we don't have to mess with user friendly syntax parsing + * in device emulation code. + * + * For now, only AHCI is implemented here. + */ +void drive_populate(void) +{ + drive_populate_ahci(); +} + void do_commit(Monitor *mon, const QDict *qdict) { const char *device = qdict_get_str(qdict, "device"); diff --git a/blockdev.h b/blockdev.h index 260e16b..9d79558 100644 --- a/blockdev.h +++ b/blockdev.h @@ -23,6 +23,7 @@ typedef enum { IF_DEFAULT = -1, /* for use with drive_add() only */ IF_NONE, IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN, + IF_AHCI, IF_COUNT } BlockInterfaceType; @@ -53,6 +54,12 @@ QemuOpts *drive_def(const char *optstr); QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file, const char *optstr); DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi); +void drive_populate(void); + +static inline bool is_ata(int type) +{ + return (type == IF_IDE) || (type == IF_AHCI); +} /* device-hotplug */ diff --git a/qemu-options.hx b/qemu-options.hx index 8b66264..9527c51 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -160,7 +160,7 @@ Special files such as iSCSI devices can be specified using protocol specific URLs. See the section for "Device URL Syntax" for more information. @item if=@var{interface} This option defines on which type on interface the drive is connected. -Available types are: ide, scsi, sd, mtd, floppy, pflash, virtio. +Available types are: ide, scsi, sd, mtd, floppy, pflash, virtio, ahci. @item bus=@var{bus},unit=@var{unit} These options define where is connected the drive by defining the bus number and the unit id. @@ -260,6 +260,11 @@ You can connect a SCSI disk with unit ID 6 on the bus #0: qemu-system-i386 -drive file=file,if=scsi,bus=0,unit=6 @end example +You can attach a SATA disk using AHCI: +@example +qemu-system-i386 -drive file=file,if=ahci +@end example + Instead of @option{-fda}, @option{-fdb}, you can use: @example qemu-system-i386 -drive file=file,index=0,if=floppy diff --git a/vl.c b/vl.c index 1329c30..65410a0 100644 --- a/vl.c +++ b/vl.c @@ -3438,6 +3438,8 @@ int main(int argc, char **argv, char **envp) default_drive(default_sdcard, snapshot, machine->use_scsi, IF_SD, 0, SD_OPTS); + drive_populate(); + register_savevm_live(NULL, "ram", 0, 4, NULL, ram_save_live, NULL, ram_load, NULL);