Hi,
Porting LinuxBIOS to new motherboards has become easier and easier over the last period of time. There's almost no need for assembler coding anymore, Hypertransport featured systems do a completely automatical setup of their non coherent devices. On K8 systems even the coherent devices get initialized automatically. But there is still one major drawback when it comes to boot an operating system: Passing the information.
No, this is not going to be a discussion about whether this or that table is preferred. The problem is simply that for each motherboard these tables have to be redone over and over: The pirq table, the mp table and the acpi tables.
This leads to hand made tables that often contain errors or have to be adapted with architectural changes that might have consequences wrt the bus numbering for instance.
* pirq tables do need knowledge that is not provided in the config files yet (wiring)
* MP tables contain a static "compatibility part" and have to have entries for devices on the bus and their interrupts. This is very similar to the pirq table. But they also need information on available APICs. These could be provided from the device tree. We know we have an 8131 in there, so we know 2 IOAPICs belong on the list. We also know what busses hang off that 8131, so we can generate most of the interrupt tables.
* ACPI tables need information on the Apics as well. Now the ACPI implementation I wrote a longer while ago is completely static and basically only works for systems with a single IOAPIC and not very well even on those.
Autocreation of those tables should belong to the driver code of each supported device. The information about the 8131 should come from the 8131 code, the information for the 8111 should come from the 8111 code, and so on.
The solution could be to enhance the struct device_operations by an additional member write_tables(device_t dev, table_t id) which can be subsequently called by each of the write_*_tables() functions, adding their part to the table.
This would also allow to extend the generic information provided by the bridges, by adding such functionality to the mainboard specific code, so we won't end up with something that is worse than now in any case.
Roughly thinking, table_t could look like:
enum { MPTABLE_CPUS, MPTABLE_APICS, MPTABLE_BUSSES, MPTABLE_DEVICES, ACPI_APICS, ACPI_COMPLETE_TABLES, } table_t;
and dev::write_tables() would look similar to this:
static void amd8111_write_tables(device_t dev, table_t id) { struct resource *res;
switch (id) { case MPTABLE_BUSSES: smp_write_bus(mc, dev.link.secondary, "PCI "); [...] break; case MPTABLE_APICS: res = find_resource(dev, PCI_BASE_ADDRESS_0); if (!res) break; smp_write_ioapic(mc, last_ioapic()+1, AMD8131_IOAPIC_VERSION, res->base); [...] break; case ACPI_COMPLETE_TABLES: acpi_create_hpet(...); [...] break; case ACPI_APICS: // We're adding an APIC to an ACPI MADT: acpi_create_madt_ioapic(...); [...] break; default: // all unneeded and unknown table types are ignored. break; } }
Since everything is a device in LinuxBIOS, we could create these tables in a nice and ordered manner.
Comments? Flames? Better ideas?
Stefan