On Mon, 9 Oct 2023, Bernhard Beschow wrote:
Am 8. Oktober 2023 11:08:58 UTC schrieb BALATON Zoltan <bala...@eik.bme.hu>:
On Sun, 8 Oct 2023, Mark Cave-Ayland wrote:
On 05/10/2023 23:13, BALATON Zoltan wrote:
The initial value for BARs were set in reset method for emulating
legacy mode at start but this does not work because PCI code resets
BARs after calling device reset method.
This is certainly something I've noticed when testing previous versions of the
VIA patches. Perhaps it's worth a separate thread to the PCI devs?
I think I brought up this back then but was told current PCI code won't change
and since that could break everything else that makes sense so this is
something that we should take as given and accomodate that.
Additionally the values
written to BARs were also wrong.
I don't believe this is correct: according to the datasheet the values on reset
are the ones given in the current reset code, so even if the reset function is
overridden at a later data during PCI bus reset, I would leave these for now
since it is a different issue.
Those values are missing the IO space bit for one so they can't be correct as a
BAR value no matter what the datasheet says. And since they are ineffective now
I think it's best to remove them to avoid confusion.
Move setting the BARs to a callback on writing the PCI config regsiter
that sets the compatibility mode (which firmwares needing this mode
seem to do) and fix their values to program it to use legacy port
numbers. As noted in a comment, we only do this when the BARs were
unset before, because logs from real machine show this is how real
chip works, even if it contradicts the data sheet which is not very
clear about this.
Signed-off-by: BALATON Zoltan <bala...@eik.bme.hu>
---
hw/ide/via.c | 35 ++++++++++++++++++++++++++++++-----
1 file changed, 30 insertions(+), 5 deletions(-)
diff --git a/hw/ide/via.c b/hw/ide/via.c
index fff23803a6..8186190207 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -132,11 +132,6 @@ static void via_ide_reset(DeviceState *dev)
pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_FAST_BACK |
PCI_STATUS_DEVSEL_MEDIUM);
- pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, 0x000001f0);
- pci_set_long(pci_conf + PCI_BASE_ADDRESS_1, 0x000003f4);
- pci_set_long(pci_conf + PCI_BASE_ADDRESS_2, 0x00000170);
- pci_set_long(pci_conf + PCI_BASE_ADDRESS_3, 0x00000374);
- pci_set_long(pci_conf + PCI_BASE_ADDRESS_4, 0x0000cc01); /* BMIBA: 20-23h
*/
pci_set_long(pci_conf + PCI_INTERRUPT_LINE, 0x0000010e);
/* IDE chip enable, IDE configuration 1/2, IDE FIFO Configuration*/
@@ -159,6 +154,35 @@ static void via_ide_reset(DeviceState *dev)
pci_set_long(pci_conf + 0xc0, 0x00020001);
}
+static void via_ide_cfg_write(PCIDevice *pd, uint32_t addr,
+ uint32_t val, int len)
+{
+ pci_default_write_config(pd, addr, val, len);
+ /*
+ * Only set BARs if they are unset. Logs from real hardware show that
+ * writing class_prog to enable compatibility mode after BARs were set
+ * (possibly by firmware) it will use ports set by BARs not ISA ports
+ * (e.g. pegasos2 Linux does this and calls it non-100% native mode).
Can you remind me again where the references are to non-100% native mode? The only thing
I can find in Linux is
https://github.com/torvalds/linux/blob/master/arch/powerpc/platforms/chrp/pci.c#L360 but
that simply forces a switch to legacy mode, with no mention of "non-100% native
mode".
It was discussed somewhere in the via-ide thread we had when this was last
touched for pegasos2 in March 2020. Basically the non-100% native mode is when
ports are set by BARs but IRQs are still hard coded to 14-15. Linux can work
with all 3 possible modes: legacy (both ports and IRQs are hard coded to ISA
values), native (using BARs and PCI config 0x3c for a single interrupt for both
channels, vt82c686 data sheet does not document this but vt8231 has a comment
saying native mode only) and non-100% native mode where BARs are effective to
set port addresses but IRQs don't respect 0x3c but use 14-15 as in legacy mode.
Some machines only work in non-100% native mode such as pegasos2 and Linux has
some quirks for this. Other OSes running on this machine work with what the
firmware has set up and can't work with anything else so we need to emulate
what those OSes want (which matches real hardware) because Linux can usually
cope anyway. On pegasso2 MorphOS uses BARs but expects IRQ 14-1
5 which is what the firmware also sets up by setting mode to native in the PCI
config of the IDE func yet IRQs are fixed at 14-15. Linux forces its driver to
use legacy interrupts by setting mode back to legacy but it still uses BARs and
this is what it calls non-100% native mode. On amigaone firmware sets legacy
mode and AmigaOS does not change this but uses it with legacy ports and IRQs.
Linux finds the same and uses legacy mode on amigaone.
+ * But if 0x8a is written after reset without setting BARs then we want
+ * legacy ports (this is done by AmigaOne firmware for example).
+ */
What should happen here is that writing 0x8a should *always* switch to legacy
mode, so the BARs are unused...
Yes, but as we've found before that can't be emulated in QEMU due to ISA
emulation being static and only allows adding ports but not removing them later
so we can't switch between legacy ISA and PCI here so we use the BARs for
legacy ports as well to emulate that. The reason we only do this if BARs are
not yet set is because Linux changes this back to legacy mode on pegasos2 but
still uses BARs
Just curious: How can you tell the difference in real hardware whether
"raw" IO ports vs. BARs mapped to IO space are used?
Not sure what you mean but if you see ports not matching legacy ports then
you can be fairly sure they are BARs. The chip may internally implement
legacy mode by just fixing BARs at legacy values (the same as this patch
does) but the data sheet does not tell how it works so we don't know that.
as shown in boot logs from real hardware
Could you provide links to such logs? That would be very helpful to have
-- even in the code -- for documentation.
I think if you don't believe me you can just try the emulated pegasos2
with its original firmware and see how it configures the IDE device then
boot Linux with that and see how it detects that. The relevant lines in
the Linux dmesg are:
[ 0.066337] pci 0000:00:0c.1: Fixing VIA IDE, force legacy mode on
[ 0.514351] pata_via 0000:00:0c.1: version 0.3.4
[ 0.536431] scsi0 : pata_via
[ 0.557917] scsi1 : pata_via
[ 0.558249] ata1: PATA max UDMA/100 cmd 0x1000 ctl 0x100c bmdma 0x1020 irq 14
[ 0.558272] ata2: PATA max UDMA/100 cmd 0x1010 ctl 0x101c bmdma 0x1028 irq 15
These are from real machine but emulated one shold do the same with
original firmware. The comments near the IDE fixup in Linux source is
misleading as it says the controller only works in legacy mode but what it
should say is that it uses legacy interrupts even in native mode as seen
from the above logs. The ports are still as mapped by BARs but IRQs aren't
the 9 that the firmware writes to 0x3c PCI config reg for all devices but
14-15 as in legacy mode. This is the non-100% native mode that I think
older Linux versions printed in this case and what's MorphOS and AmigaOS
expect so happen on pegasos2 irrespective of what's in the device tree.
Also the forcing legacy mode quirk in Linux may only edit the device tree
so the driver uses legacy interrupts, I'm not sure, it's been a while I've
looked at this and it was already discussed to death back when I've added
the pegasos2 machine so I don't want to get back to that again. This patch
is tested to allow amigaone to work while not breaking pegasos2 so I'd go
with this for now.
Regards,
BALATON Zoltan