* [Qemu-devel] [RFC 0/2] update CMOS for single hand-created ISA-FDC
@ 2015-06-20 2:43 Laszlo Ersek
2015-06-20 2:43 ` [Qemu-devel] [RFC 1/2] hw/i386/pc: factor out pc_cmos_init_floppy() Laszlo Ersek
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Laszlo Ersek @ 2015-06-20 2:43 UTC (permalink / raw)
To: qemu-devel, lersek; +Cc: John Snow, Jan Tomko, Markus Armbruster, Paolo Bonzini
This is for the other pc-q35-2.4 ISA-FDC problem reported by Jan.
Jan, can you give it a try pls?
Cc: Jan Tomko <jtomko@redhat.com>
Cc: John Snow <jsnow@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Laszlo Ersek (2):
hw/i386/pc: factor out pc_cmos_init_floppy()
hw/i386/pc: reflect an explicitly created, sole FDC in the CMOS
hw/i386/pc.c | 113 ++++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 84 insertions(+), 29 deletions(-)
--
1.8.3.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Qemu-devel] [RFC 1/2] hw/i386/pc: factor out pc_cmos_init_floppy()
2015-06-20 2:43 [Qemu-devel] [RFC 0/2] update CMOS for single hand-created ISA-FDC Laszlo Ersek
@ 2015-06-20 2:43 ` Laszlo Ersek
2015-06-20 2:43 ` [Qemu-devel] [RFC 2/2] hw/i386/pc: reflect an explicitly created, sole FDC in the CMOS Laszlo Ersek
2015-06-22 11:01 ` [Qemu-devel] [RFC 0/2] update CMOS for single hand-created ISA-FDC Ján Tomko
2 siblings, 0 replies; 5+ messages in thread
From: Laszlo Ersek @ 2015-06-20 2:43 UTC (permalink / raw)
To: qemu-devel, lersek; +Cc: John Snow, Jan Tomko, Markus Armbruster, Paolo Bonzini
Extract the pc_cmos_init_floppy() function from pc_cmos_init(). The
function sets two RTC registers: floppy drive types (0x10), overwriting
the earlier value in there), and REG_EQUIPMENT_BYTE (0x14), setting bits
in the prior value.
Cc: Jan Tomko <jtomko@redhat.com>
Cc: John Snow <jsnow@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---
hw/i386/pc.c | 67 ++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 38 insertions(+), 29 deletions(-)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 3f0d435..1ca0cdd 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -294,6 +294,42 @@ static void pc_boot_set(void *opaque, const char *boot_device, Error **errp)
set_boot_dev(opaque, boot_device, errp);
}
+static void pc_cmos_init_floppy(ISADevice *rtc_state, ISADevice *floppy)
+{
+ int val, nb, i;
+ FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
+
+ /* floppy type */
+ if (floppy) {
+ for (i = 0; i < 2; i++) {
+ fd_type[i] = isa_fdc_get_drive_type(floppy, i);
+ }
+ }
+ val = (cmos_get_fd_drive_type(fd_type[0]) << 4) |
+ cmos_get_fd_drive_type(fd_type[1]);
+ rtc_set_memory(rtc_state, 0x10, val);
+
+ val = rtc_get_memory(rtc_state, REG_EQUIPMENT_BYTE);
+ nb = 0;
+ if (fd_type[0] < FDRIVE_DRV_NONE) {
+ nb++;
+ }
+ if (fd_type[1] < FDRIVE_DRV_NONE) {
+ nb++;
+ }
+ switch (nb) {
+ case 0:
+ break;
+ case 1:
+ val |= 0x01; /* 1 drive, ready for boot */
+ break;
+ case 2:
+ val |= 0x41; /* 2 drives, ready for boot */
+ break;
+ }
+ rtc_set_memory(rtc_state, REG_EQUIPMENT_BYTE, val);
+}
+
typedef struct pc_cmos_init_late_arg {
ISADevice *rtc_state;
BusState *idebus[2];
@@ -344,8 +380,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
ISADevice *floppy, BusState *idebus0, BusState *idebus1,
ISADevice *s)
{
- int val, nb, i;
- FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
+ int val;
static pc_cmos_init_late_arg arg;
PCMachineState *pc_machine = PC_MACHINE(machine);
Error *local_err = NULL;
@@ -402,37 +437,11 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
exit(1);
}
- /* floppy type */
- if (floppy) {
- for (i = 0; i < 2; i++) {
- fd_type[i] = isa_fdc_get_drive_type(floppy, i);
- }
- }
- val = (cmos_get_fd_drive_type(fd_type[0]) << 4) |
- cmos_get_fd_drive_type(fd_type[1]);
- rtc_set_memory(s, 0x10, val);
-
val = 0;
- nb = 0;
- if (fd_type[0] < FDRIVE_DRV_NONE) {
- nb++;
- }
- if (fd_type[1] < FDRIVE_DRV_NONE) {
- nb++;
- }
- switch (nb) {
- case 0:
- break;
- case 1:
- val |= 0x01; /* 1 drive, ready for boot */
- break;
- case 2:
- val |= 0x41; /* 2 drives, ready for boot */
- break;
- }
val |= 0x02; /* FPU is there */
val |= 0x04; /* PS/2 mouse installed */
rtc_set_memory(s, REG_EQUIPMENT_BYTE, val);
+ pc_cmos_init_floppy(s, floppy);
/* hard drives */
arg.rtc_state = s;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [RFC 2/2] hw/i386/pc: reflect an explicitly created, sole FDC in the CMOS
2015-06-20 2:43 [Qemu-devel] [RFC 0/2] update CMOS for single hand-created ISA-FDC Laszlo Ersek
2015-06-20 2:43 ` [Qemu-devel] [RFC 1/2] hw/i386/pc: factor out pc_cmos_init_floppy() Laszlo Ersek
@ 2015-06-20 2:43 ` Laszlo Ersek
2015-06-20 9:54 ` Markus Armbruster
2015-06-22 11:01 ` [Qemu-devel] [RFC 0/2] update CMOS for single hand-created ISA-FDC Ján Tomko
2 siblings, 1 reply; 5+ messages in thread
From: Laszlo Ersek @ 2015-06-20 2:43 UTC (permalink / raw)
To: qemu-devel, lersek; +Cc: John Snow, Jan Tomko, Markus Armbruster, Paolo Bonzini
With the pc-q35-2.4 machine type, if the user creates an ISA FDC manually:
-device isa-fdc,driveA=drive-fdc0-0-0 \
-drive file=...,if=none,id=drive-fdc0-0-0,format=raw
then the board-default FDC will be skipped, and only the explicitly
requested FDC will exist. qtree-wise, this is correct; however such an FDC
is currently not registered in the CMOS, because that code is only reached
for the board-default FDC.
The pc_cmos_init_late() one-shot reset handler -- one-shot because the
CMOS is not reprogrammed during warm reset -- should search for a single,
explicitly created ISA FDC device, if there has been no board default, and
reprogram the CMOS if found.
Cc: Jan Tomko <jtomko@redhat.com>
Cc: John Snow <jsnow@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Reported-by: Jan Tomko <jtomko@redhat.com>
Suggested-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---
hw/i386/pc.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 1ca0cdd..47a3082 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -333,8 +333,30 @@ static void pc_cmos_init_floppy(ISADevice *rtc_state, ISADevice *floppy)
typedef struct pc_cmos_init_late_arg {
ISADevice *rtc_state;
BusState *idebus[2];
+ ISADevice *board_floppy;
} pc_cmos_init_late_arg;
+typedef struct check_fdc_state {
+ ISADevice *floppy;
+ bool multiple;
+} CheckFdcState;
+
+static int check_fdc(Object *obj, void *opaque)
+{
+ CheckFdcState *state = opaque;
+ Object *fdc;
+
+ fdc = object_dynamic_cast(obj, TYPE_ISA_FDC);
+ if (fdc) {
+ if (state->floppy) {
+ state->multiple = true;
+ } else {
+ state->floppy = ISA_DEVICE(obj);
+ }
+ }
+ return 0;
+}
+
static void pc_cmos_init_late(void *opaque)
{
pc_cmos_init_late_arg *arg = opaque;
@@ -372,6 +394,29 @@ static void pc_cmos_init_late(void *opaque)
}
rtc_set_memory(s, 0x39, val);
+ /*
+ * If the board initialization code created no FDC, but exactly one FDC has
+ * been created since then explicitly, then we configure the CMOS registers
+ * now, in accordance with that one FDC.
+ */
+ if (arg->board_floppy == NULL) {
+ static const char * const paths[] = { "/peripheral",
+ "/peripheral-anon", NULL };
+ const char * const * path;
+ CheckFdcState state = { 0 };
+
+ for (path = paths; *path; ++path) {
+ Object *container;
+
+ container = container_get(qdev_get_machine(), *path);
+ object_child_foreach(container, check_fdc, &state);
+ }
+
+ if (state.floppy && !state.multiple) {
+ pc_cmos_init_floppy(s, state.floppy);
+ }
+ }
+
qemu_unregister_reset(pc_cmos_init_late, opaque);
}
@@ -447,6 +492,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
arg.rtc_state = s;
arg.idebus[0] = idebus0;
arg.idebus[1] = idebus1;
+ arg.board_floppy = floppy;
qemu_register_reset(pc_cmos_init_late, &arg);
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [RFC 2/2] hw/i386/pc: reflect an explicitly created, sole FDC in the CMOS
2015-06-20 2:43 ` [Qemu-devel] [RFC 2/2] hw/i386/pc: reflect an explicitly created, sole FDC in the CMOS Laszlo Ersek
@ 2015-06-20 9:54 ` Markus Armbruster
0 siblings, 0 replies; 5+ messages in thread
From: Markus Armbruster @ 2015-06-20 9:54 UTC (permalink / raw)
To: Laszlo Ersek; +Cc: Jan Tomko, John Snow, qemu-devel, Paolo Bonzini
Wow, that was quick!
Laszlo Ersek <lersek@redhat.com> writes:
> With the pc-q35-2.4 machine type, if the user creates an ISA FDC manually:
>
> -device isa-fdc,driveA=drive-fdc0-0-0 \
> -drive file=...,if=none,id=drive-fdc0-0-0,format=raw
>
> then the board-default FDC will be skipped, and only the explicitly
> requested FDC will exist. qtree-wise, this is correct; however such an FDC
> is currently not registered in the CMOS, because that code is only reached
> for the board-default FDC.
>
> The pc_cmos_init_late() one-shot reset handler -- one-shot because the
> CMOS is not reprogrammed during warm reset -- should search for a single,
> explicitly created ISA FDC device, if there has been no board default, and
> reprogram the CMOS if found.
I don't think we want "single". We want the isa-fdc at I/O address
0x3f0.
Test case:
-M q35 -device isa-fdc,id=fdc1 -device isa-fdc,id=fdc2,iobase=0x370
should work, and CMOS should be set according to fdc1.
> Cc: Jan Tomko <jtomko@redhat.com>
> Cc: John Snow <jsnow@redhat.com>
> Cc: Markus Armbruster <armbru@redhat.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Reported-by: Jan Tomko <jtomko@redhat.com>
> Suggested-by: Markus Armbruster <armbru@redhat.com>
> Signed-off-by: Laszlo Ersek <lersek@redhat.com>
> ---
> hw/i386/pc.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 46 insertions(+)
>
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index 1ca0cdd..47a3082 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -333,8 +333,30 @@ static void pc_cmos_init_floppy(ISADevice *rtc_state, ISADevice *floppy)
> typedef struct pc_cmos_init_late_arg {
> ISADevice *rtc_state;
> BusState *idebus[2];
> + ISADevice *board_floppy;
> } pc_cmos_init_late_arg;
>
> +typedef struct check_fdc_state {
> + ISADevice *floppy;
> + bool multiple;
> +} CheckFdcState;
> +
> +static int check_fdc(Object *obj, void *opaque)
> +{
> + CheckFdcState *state = opaque;
> + Object *fdc;
> +
> + fdc = object_dynamic_cast(obj, TYPE_ISA_FDC);
> + if (fdc) {
> + if (state->floppy) {
> + state->multiple = true;
> + } else {
> + state->floppy = ISA_DEVICE(obj);
> + }
> + }
Something like
fdc = object_dynamic_cast(obj, TYPE_ISA_FDC);
if (fdc
&& object_property_get_int(obj, "iobase", &error_abort) == 0x3f0) {
assert(!state->floppy);
state->floppy = ISA_DEVICE(obj);
}
The &error_abort is probably wrong, but I trust you get the general
idea.
The assertion is only valid if we actually prevent multiple ISA devices
claiming the same I/O port. Checking... crap, multiple -device isa-fdc
are accepted. No idea which one actually gets the port.
Two solutions:
* Find a way to determine whether the device is in possession of the
port. If it is, pick it and stop the search. If not, continue the
search.
Alternative: always continue the search, assert that we pick at most
one (because if we pick more, our "is in posession of the port" test
is broken).
* Pick one that's easy to pick. Might be the wrong one when there's
more than one. Feel free to print a warning then. I'd happily accept
such a stupid solution, as long as its stupidity is reasonably
documented.
> + return 0;
> +}
> +
> static void pc_cmos_init_late(void *opaque)
> {
> pc_cmos_init_late_arg *arg = opaque;
> @@ -372,6 +394,29 @@ static void pc_cmos_init_late(void *opaque)
> }
> rtc_set_memory(s, 0x39, val);
>
> + /*
> + * If the board initialization code created no FDC, but exactly one FDC has
> + * been created since then explicitly, then we configure the CMOS registers
> + * now, in accordance with that one FDC.
> + */
> + if (arg->board_floppy == NULL) {
> + static const char * const paths[] = { "/peripheral",
> + "/peripheral-anon", NULL };
> + const char * const * path;
> + CheckFdcState state = { 0 };
> +
> + for (path = paths; *path; ++path) {
> + Object *container;
> +
> + container = container_get(qdev_get_machine(), *path);
> + object_child_foreach(container, check_fdc, &state);
> + }
> +
> + if (state.floppy && !state.multiple) {
> + pc_cmos_init_floppy(s, state.floppy);
> + }
> + }
> +
> qemu_unregister_reset(pc_cmos_init_late, opaque);
> }
This assumes that the onboard isa-fdc wins the fight over the I/O port.
Perhaps passing the onboard isa-fdc to check_fdc() would be cleaner.
> @@ -447,6 +492,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
> arg.rtc_state = s;
> arg.idebus[0] = idebus0;
> arg.idebus[1] = idebus1;
> + arg.board_floppy = floppy;
> qemu_register_reset(pc_cmos_init_late, &arg);
> }
Thanks for tackling this!
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [RFC 0/2] update CMOS for single hand-created ISA-FDC
2015-06-20 2:43 [Qemu-devel] [RFC 0/2] update CMOS for single hand-created ISA-FDC Laszlo Ersek
2015-06-20 2:43 ` [Qemu-devel] [RFC 1/2] hw/i386/pc: factor out pc_cmos_init_floppy() Laszlo Ersek
2015-06-20 2:43 ` [Qemu-devel] [RFC 2/2] hw/i386/pc: reflect an explicitly created, sole FDC in the CMOS Laszlo Ersek
@ 2015-06-22 11:01 ` Ján Tomko
2 siblings, 0 replies; 5+ messages in thread
From: Ján Tomko @ 2015-06-22 11:01 UTC (permalink / raw)
To: Laszlo Ersek; +Cc: Paolo Bonzini, John Snow, qemu-devel, Markus Armbruster
[-- Attachment #1: Type: text/plain, Size: 920 bytes --]
On Sat, Jun 20, 2015 at 04:43:46AM +0200, Laszlo Ersek wrote:
> This is for the other pc-q35-2.4 ISA-FDC problem reported by Jan.
>
> Jan, can you give it a try pls?
>
Works for me.
I tried the following command line with a Fedora 21 guest:
-device isa-fdc,driveA=drive-fdc0-0-0
-drive file=/var/lib/libvirt/images/floppy,if=none,id=drive-fdc0-0-0,format=raw
and I could see the floppy drive inside the guest.
Thanks!
Jan
> Cc: Jan Tomko <jtomko@redhat.com>
> Cc: John Snow <jsnow@redhat.com>
> Cc: Markus Armbruster <armbru@redhat.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
>
> Laszlo Ersek (2):
> hw/i386/pc: factor out pc_cmos_init_floppy()
> hw/i386/pc: reflect an explicitly created, sole FDC in the CMOS
>
> hw/i386/pc.c | 113 ++++++++++++++++++++++++++++++++++++++++++++---------------
> 1 file changed, 84 insertions(+), 29 deletions(-)
>
> --
> 1.8.3.1
>
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2015-06-22 11:01 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-06-20 2:43 [Qemu-devel] [RFC 0/2] update CMOS for single hand-created ISA-FDC Laszlo Ersek
2015-06-20 2:43 ` [Qemu-devel] [RFC 1/2] hw/i386/pc: factor out pc_cmos_init_floppy() Laszlo Ersek
2015-06-20 2:43 ` [Qemu-devel] [RFC 2/2] hw/i386/pc: reflect an explicitly created, sole FDC in the CMOS Laszlo Ersek
2015-06-20 9:54 ` Markus Armbruster
2015-06-22 11:01 ` [Qemu-devel] [RFC 0/2] update CMOS for single hand-created ISA-FDC Ján Tomko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).