> Date: Tue, 7 Dec 2021 11:30:48 +0100
> From: Anton Lindqvist <[email protected]>
>
> On Mon, Dec 06, 2021 at 10:25:34PM +0100, Mark Kettenis wrote:
> > > Date: Mon, 6 Dec 2021 21:45:03 +0100
> > > From: Anton Lindqvist <[email protected]>
> > >
> > > On Mon, Dec 06, 2021 at 09:23:45PM +0100, Mark Kettenis wrote:
> > > > > Date: Mon, 6 Dec 2021 21:08:04 +0100
> > > > > From: Patrick Wildt <[email protected]>
> > > > >
> > > > > Hi,
> > > > >
> > > > > On one machine I had the pleasure of having to try and use the
> > > > > Serial-over-LAN feature which shows up as just another com(4)
> > > > > device. Instead of having to manually add a com(4) at isa(4)
> > > > > I figured it would be nicer to have them attach via ACPI. At
> > > > > least on that machine, the SOL definitely shows up in the DSDT.
> > > > >
> > > > > Since I don't want to break any legacy machines, I figured I'd
> > > > > keep ignoring the isa(4) addresses specified in amd64's GENERIC.
> > > > >
> > > > > Right now this diff is more about putting it out there, not about
> > > > > asking for OKs, as amd64 isn't really my strong suit. If people
> > > > > are interested, I can definitely put in all the feedback there is.
> > > > >
> > > > > Patrick
> > > >
> > > > anton@ has a better diff he's working on
> > >
> > > Here's the diff in its current state. There's one thing I haven't had
> > > the time to figure out yet: in order to get interrupts working on my
> > > apu2 I had to explicit pass LR_EXTIRQ_MODE (aaa_irq_flags is zero) to
> > > acpi_intr_establish() which causes IST_EDGE to be passed to
> > > intr_establish(). Worth noting is that this matches what com at isa
> > > already does. This was however not necessary on my amd64 build machine
> > > where aaa_irq_flags also is zero.
> >
> > Actually, it seems we're parsing the ACPI interrupt resource
> > descriptor wrong. The decompiled DSDTs I have here seem to use
> > IRQNoFlags() for the interrupts, which apparently implies the
> > interrupt is edge-triggered.
> >
> > Let me see if I can cook a diff.
>
> Updated diff now that kettenis@ fixed parsing of the irq flags.
A few comments below.
> diff --git share/man/man4/com.4 share/man/man4/com.4
> index 73b421f2ca7..e54255fe0d6 100644
> --- share/man/man4/com.4
> +++ share/man/man4/com.4
> @@ -61,11 +61,13 @@
> .Cd "com0 at isa? port 0x3f8 irq 4"
> .Cd "com1 at isa? port 0x2f8 irq 3"
> .Pp
> +.Cd "# arm64 and amd64"
> +.Cd "com* at acpi?"
> +.Pp
> .Cd "# armv7"
> .Cd "com* at fdt?"
> .Pp
> .Cd "# arm64"
> -.Cd "com* at acpi?"
> .Cd "com* at fdt?"
The armv7 and arm64 entries can be combined now
> .Pp
> .Cd "# hppa"
> diff --git sys/arch/amd64/conf/GENERIC sys/arch/amd64/conf/GENERIC
> index ecccd1323d9..87fcaced306 100644
> --- sys/arch/amd64/conf/GENERIC
> +++ sys/arch/amd64/conf/GENERIC
> @@ -65,6 +65,11 @@ amdgpio* at acpi?
> aplgpio* at acpi?
> bytgpio* at acpi?
> chvgpio* at acpi?
> +com0 at acpi?
> +com1 at acpi?
> +com2 at acpi?
> +com3 at acpi?
> +com* at acpi?
> glkgpio* at acpi?
> pchgpio* at acpi?
> sdhc* at acpi?
> diff --git sys/arch/amd64/conf/RAMDISK sys/arch/amd64/conf/RAMDISK
> index 6041293b287..a5f10b357dd 100644
> --- sys/arch/amd64/conf/RAMDISK
> +++ sys/arch/amd64/conf/RAMDISK
> @@ -34,6 +34,9 @@ acpipci* at acpi?
> acpiprt* at acpi?
> acpimadt0 at acpi?
> #acpitz* at acpi?
> +com0 at acpi?
> +com1 at acpi?
> +com* at acpi?
>
> mpbios0 at bios0
As Theo pointed out, this may not be entirely fool-proof. We probe
acpi(4) before isa(4), which is good. Since we prevent ISA devices
from attaching to addresses that have been claimed by something else,
this means that we won't attach a com(4) to isa(4) if we have attached
an ACPI com(4) attached at the same address. But if there is no ACPI
com(4) at an address the an ISA com(4) may still attach. As long as
the ACPI serial ports are listed in canonical order and use the
standard IRQ, everything should be fine. If the ACPI com(4) ports are
not in canonical order any additional ISA com(4) may no longer attach.
For example, if there is a single ACPI com(4) at address 0x2f8, we
will now attach it as com0. But since com0 is now attached, the
isa(4) code will skip its com0 and won't probe com(4) at address
0x3f8. I think this is fine. I expect ACPI to list all usable com(4)
ports so any ports sucessfully probed by isa(4) would be "ghost" ports
that aren't actually connected.
The case of non-standard IRQs is also interesting. Suppose we have an
ACPI com(4) at address 0x3f8 but with the non-standard IRQ 3. We may
still end up probing an ISA com(4) at address 0x2f8. This probe would
succeed if the hardware responds to the probe. But establishing the
interrupt at IRQ 3 would fail since sharing of edge-triggered
interrupts isn't allowed. So the attach should fail in that case.
And that should be fine.
So I think this approach is actually fine. If it turns out there are
corner cases that we actually care about, there are ways to address
this.
> diff --git sys/arch/amd64/conf/RAMDISK_CD sys/arch/amd64/conf/RAMDISK_CD
> index 8bd646b4ea3..d007c0102d0 100644
> --- sys/arch/amd64/conf/RAMDISK_CD
> +++ sys/arch/amd64/conf/RAMDISK_CD
> @@ -51,6 +51,10 @@ bytgpio* at acpi?
> sdhc* at acpi?
> acpihve* at acpi?
> chvgpio* at acpi?
> +com0 at acpi?
> +com1 at acpi?
> +com2 at acpi?
> +com* at acpi?
> glkgpio* at acpi?
>
> mpbios0 at bios0
> diff --git sys/dev/acpi/acpi.c sys/dev/acpi/acpi.c
> index 7577424e8a2..e89869aedbd 100644
> --- sys/dev/acpi/acpi.c
> +++ sys/dev/acpi/acpi.c
> @@ -3140,7 +3140,6 @@ const char *acpi_isa_hids[] = {
> "PNP0303", /* IBM Enhanced Keyboard (101/102-key, PS/2 Mouse) */
> "PNP0400", /* Standard LPT Parallel Port */
> "PNP0401", /* ECP Parallel Port */
> - "PNP0501", /* 16550A-compatible COM Serial Port */
> "PNP0700", /* PC-class Floppy Disk Controller */
> "PNP0F03", /* Microsoft PS/2-style Mouse */
> "PNP0F13", /* PS/2 Mouse */
> diff --git sys/dev/acpi/com_acpi.c sys/dev/acpi/com_acpi.c
> index 852be6c71b3..e4001861032 100644
> --- sys/dev/acpi/com_acpi.c
> +++ sys/dev/acpi/com_acpi.c
> @@ -49,10 +49,12 @@ struct cfattach com_acpi_ca = {
>
> const char *com_hids[] = {
> "HISI0031",
> + "PNP0501",
> NULL
> };
>
> int com_acpi_is_console(struct com_acpi_softc *);
> +int com_acpi_is_designware(const char *);
> int com_acpi_intr_designware(void *);
>
> int
> @@ -69,7 +71,7 @@ com_acpi_attach(struct device *parent, struct device *self,
> void *aux)
> {
> struct com_acpi_softc *sc = (struct com_acpi_softc *)self;
> struct acpi_attach_args *aaa = aux;
> - uint32_t freq;
> + int (*intrfn)(void *) = comintr;
>
> sc->sc_acpi = (struct acpi_softc *)parent;
> sc->sc_node = aaa->aaa_node;
> @@ -85,34 +87,43 @@ com_acpi_attach(struct device *parent, struct device
> *self, void *aux)
> return;
> }
>
> - printf(" addr 0x%llx/0x%llx", aaa->aaa_addr[0], aaa->aaa_size[0]);
> + printf(" addr 0x%llx/%llu", aaa->aaa_addr[0], aaa->aaa_size[0]);
I would like to keep printing of ACPI addresses/sizes consistent. So
please drop this.
> printf(" irq %d", aaa->aaa_irq[0]);
>
> - freq = acpi_getpropint(sc->sc_node, "clock-frequency", 0);
> -
> sc->sc.sc_iot = aaa->aaa_bst[0];
> sc->sc.sc_iobase = aaa->aaa_addr[0];
> - sc->sc.sc_uarttype = COM_UART_16550;
> - sc->sc.sc_frequency = freq ? freq : COM_FREQ;
I'd prefer if you'd keep the frequency code here; it isn't really
specific to the Designware code.
> -
> - sc->sc.sc_reg_width = acpi_getpropint(sc->sc_node, "reg-io-width", 4);
> - sc->sc.sc_reg_shift = acpi_getpropint(sc->sc_node, "reg-shift", 2);
> -
> - if (com_acpi_is_console(sc)) {
> - SET(sc->sc.sc_hwflags, COM_HW_CONSOLE);
> - SET(sc->sc.sc_swflags, COM_SW_SOFTCAR);
> - comconsfreq = sc->sc.sc_frequency;
> - comconsrate = B115200;
> + sc->sc.sc_frequency = COM_FREQ;
> +
> + if (com_acpi_is_designware(aaa->aaa_dev)) {
> + intrfn = com_acpi_intr_designware;
> + sc->sc.sc_uarttype = COM_UART_16550;
> + sc->sc.sc_frequency = acpi_getpropint(sc->sc_node,
> + "clock-frequency", COM_FREQ);
> + sc->sc.sc_reg_width = acpi_getpropint(sc->sc_node,
> + "reg-io-width", 4);
> + sc->sc.sc_reg_shift = acpi_getpropint(sc->sc_node,
> + "reg-shift", 2);
> +
> + if (com_acpi_is_console(sc)) {
> + SET(sc->sc.sc_hwflags, COM_HW_CONSOLE);
> + SET(sc->sc.sc_swflags, COM_SW_SOFTCAR);
> + comconsfreq = sc->sc.sc_frequency;
> + comconsrate = B115200;
> + }
> }
>
> - if (bus_space_map(sc->sc.sc_iot, aaa->aaa_addr[0], aaa->aaa_size[0],
> - 0, &sc->sc.sc_ioh)) {
> - printf(": can't map registers\n");
> - return;
> + if (sc->sc.sc_iobase == comconsaddr) {
> + sc->sc.sc_ioh = comconsioh;
> + } else {
> + if (bus_space_map(sc->sc.sc_iot,
> + aaa->aaa_addr[0], aaa->aaa_size[0], 0, &sc->sc.sc_ioh)) {
> + printf(": can't map registers\n");
> + return;
> + }
> }
>
> sc->sc_ih = acpi_intr_establish(aaa->aaa_irq[0], aaa->aaa_irq_flags[0],
> - IPL_TTY, com_acpi_intr_designware, sc, sc->sc.sc_dev.dv_xname);
> + IPL_TTY, intrfn, sc, sc->sc.sc_dev.dv_xname);
> if (sc->sc_ih == NULL) {
> printf(": can't establish interrupt\n");
> return;
> @@ -144,6 +155,12 @@ com_acpi_is_console(struct com_acpi_softc *sc)
> return 0;
> }
>
> +int
> +com_acpi_is_designware(const char *hid)
> +{
> + return strcmp("HISI0031", hid) == 0;
> +}
> +
> int
> com_acpi_intr_designware(void *cookie)
> {
>
This will have to be tested on arm64. Patrick, do you have an mcbin
up and running that you could try a (revised) diff on?