ACPICA missing support for device I/O port ranges

John Baldwin jhb at freebsd.org
Wed Nov 22 19:47:14 UTC 2017


On Saturday, November 18, 2017 06:52:54 PM Harald Böhm wrote:
> Hi all,
> 
> I've been working on a device driver lately and was having trouble
> allocating its resources using bus_alloc_resource_any(), although its
> I/O ports can be read from its _CRS.
> 
> This is the output of acpidump -td:
> 
> Device (GMUX)
> {
>     ...
>     Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
>     {
>         IO (Decode16,
>             0x0700,             // Range Minimum
>             0x07FF,             // Range Maximum
>             0x01,               // Alignment
>             0xFF,               // Length
>             )
>     })
>     ...
> }
> 
> After digging into the code in /sys/dev/acpica/acpi_resources.c I was
> able to find the problem. The function acpi_res_set_iorange(), which
> seems to be responsible for calling bus_set_resource() is just a
> function stub that prints a message that I/O ranges are not supported.
> 
> static void
> acpi_res_set_iorange(device_t dev, void *context, uint64_t low,
> 		     uint64_t high, uint64_t length, uint64_t align)
> {
>     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
> 
>     if (cp == NULL)
> 	return;
>     device_printf(dev, "I/O range not supported\n");
> }
> 
> After adding a call to bus_set_resource() to that function, I was able
> to allocate the device's resources.
> 
> Does anyone know, why the function has not been implemented or why I/O
> ranges are not supported?

IO ranges are not supposed to be in _CRS.  An IO range is used for relocatable
resources and would be in _PRS to say "you can use I/O ports at addresses, A,
B, or C".  Specifically, the "Range" of an I/O port is the range of the
starting addresses.  Normal I/O addresses in _CRS are set to a fixed range
with the same values for Range Min and Range Max.  For example:

                IO (Decode16,
                    0x0CF8,             // Range Minimum
                    0x0CF8,             // Range Maximum
                    0x01,               // Alignment
                    0x08,               // Length
                    )

This says it uses the '8' (Length) I/O ports starting at 0xcf8 and that they
are fixed at 0xcf8 because the starting address has to be >= 0xcf8 (range min)
and <= 0xcf8 (range max).  The _CRS blob from your dump says that it wants to
allocate 255 I/O ports with a starting address of 0x700, 0x701, 0x702, 0x703,
.... , 0x7fd, 0x7fe, or 0x7ff, but it doesn't tell us _which_ of those ranges
it is actually using (e.g. is it using 0x700 -> 0x7ff or is it using 0x780 ->
0x88f, etc.).  Probably it's just a bug in your BIOS and it means to use
0x700 -> 0x7ff and the BIOS author doesn't understand what Range Maximum means.
It is not the end address of the full I/O port addresses reserved, but the
maximum starting address (I agree this is a bit odd, but this is what the
spec says).

Assuming the BIOS is buggy, we can add a hack for iorange that adds the
resource if max == min + length and emit a warning under bootverbose about
the BIOS being buggy.

-- 
John Baldwin


More information about the freebsd-hackers mailing list