Allow a hardcoded address to be specified in cbfs files with a prefix of "etc/sdcard". Some real-world devices have valid SDHCI controllers that do not show up as PCI devices.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- docs/Runtime_config.md | 1 + src/hw/sdcard.c | 48 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 12 deletions(-)
diff --git a/docs/Runtime_config.md b/docs/Runtime_config.md index 962a8a9..40b4e73 100644 --- a/docs/Runtime_config.md +++ b/docs/Runtime_config.md @@ -189,3 +189,4 @@ There are several additional configuration options available in the | floppy0 | Set this to the type of the first floppy drive in the system (only type 4 for 3.5 inch drives is supported). | floppy1 | The type of the second floppy drive in the system. See the description of **floppy0** for more info. | threads | By default, SeaBIOS will parallelize hardware initialization during bootup to reduce boot time. Multiple hardware devices can be initialized in parallel between vga initialization and option rom initialization. One can set this file to a value of zero to force hardware initialization to run serially. Alternatively, one can set this file to 2 to enable early hardware initialization that runs in parallel with vga, option rom initialization, and the boot menu. +| sdcard* | One may create one or more files with an "sdcard" prefix (eg, "etc/sdcard0") with the physical memory address of an SDHCI controller (one memory address per file). This may be useful for SDHCI controllers that do not appear as PCI devices, but are mapped to a consistent memory address. diff --git a/src/hw/sdcard.c b/src/hw/sdcard.c index 540e97c..8e7e954 100644 --- a/src/hw/sdcard.c +++ b/src/hw/sdcard.c @@ -10,6 +10,7 @@ #include "pci.h" // pci_config_readl #include "pci_ids.h" // PCI_CLASS_SYSTEM_SDHCI #include "pci_regs.h" // PCI_BASE_ADDRESS_0 +#include "romfile.h" // romfile_findprefix #include "stacks.h" // wait_preempt #include "std/disk.h" // DISK_RET_SUCCESS #include "string.h" // memset @@ -416,15 +417,8 @@ sdcard_set_frequency(struct sdhci_s *regs, u32 khz)
// Setup and configure an SD card controller static void -sdcard_controller_setup(void *data) +sdcard_controller_setup(struct sdhci_s *regs, int prio) { - struct pci_device *pci = data; - u16 bdf = pci->bdf; - wait_preempt(); // Avoid pci_config_readl when preempting - struct sdhci_s *regs = (void*)pci_config_readl(bdf, PCI_BASE_ADDRESS_0); - pci_config_maskw(bdf, PCI_COMMAND, 0, - PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - // Initialize controller u32 present_state = readl(®s->present_state); if (!(present_state & SP_CARD_INSERTED)) @@ -470,27 +464,57 @@ sdcard_controller_setup(void *data) drive->regs = regs; drive->card_type = card_type;
- dprintf(1, "Found SD Card at %02x:%02x.%x\n" - , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf)); + dprintf(1, "Found SD Card at %p\n", regs); char *desc = znprintf(MAXDESCSIZE, "SD Card"); // XXX - boot_add_hd(&drive->drive, desc, bootprio_find_pci_device(pci)); + boot_add_hd(&drive->drive, desc, prio); return; fail: writeb(®s->power_control, 0); writew(®s->clock_control, 0); }
+static void +sdcard_pci_setup(void *data) +{ + struct pci_device *pci = data; + wait_preempt(); // Avoid pci_config_readl when preempting + // XXX - bars dependent on slot index register in pci config space + u32 regs = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0); + pci_config_maskw(pci->bdf, PCI_COMMAND, 0, + PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + int prio = bootprio_find_pci_device(pci); + sdcard_controller_setup((void*)regs, prio); +} + +static void +sdcard_romfile_setup(void *data) +{ + struct romfile_s *file = data; + int prio = bootprio_find_named_rom(file->name, 0); + u32 addr = romfile_loadint(file->name, 0); + dprintf(1, "Starting sdcard controller check at addr %x\n", addr); + sdcard_controller_setup((void*)addr, prio); +} + void sdcard_setup(void) { if (!CONFIG_SDCARD) return;
+ struct romfile_s *file = NULL; + for (;;) { + file = romfile_findprefix("etc/sdcard", file); + if (!file) + break; + run_thread(sdcard_romfile_setup, file); + } + struct pci_device *pci; foreachpci(pci) { if (pci->class != PCI_CLASS_SYSTEM_SDHCI || pci->prog_if >= 2) // Not an SDHCI controller following SDHCI spec continue; - run_thread(sdcard_controller_setup, pci); + run_thread(sdcard_pci_setup, pci); } }