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