My ram initialization appears to work, at least enough to get me out of the romcc section.
I am having quite a bit of difficulty getting the bios to run smoothly though. I am currently stuck somewhere either in filo or somewhere in elfboot. I think (once again) this has to do with the way LinuxBIOS understands the ram, and me not properly giving it the information it needs.
As of right now if I put in code that looks more correct to me, the BIOS dies earlier than if I put in code that looks less correct. I'm guess that it is a lucky coincidence the less correct code works better, but it could be that I don't understand what is happening.
In src/northbridge/intel/i855gm/northbridge.c (This northbridge isn't in the main tree but is based off of i855pm) I have see the following,
mc_dev = dev->link[0].children;
Which I've deduced will give me the PCI device 0:0.0, which is NOT the MCH for my northbridge. This is used by the line that says
tomk = ((unsigned long)pci_read_config8(mc_dev, 0x63)) << 15;
this will give tomk a value of 0, since that happens to always be in that register. Obviously I have more than 0 KiB of ram.
To give what I think is the more correct value I modify it to say
mc_dev = dev->link[0].children->sibling;
This will give it the PCI device 0:0.1, which is the MCH. I then modify the read so it says
tomk = ((unsigned long)pci_read_config8(mc_dev, 0x43)) << 15;
which is the correct register holding the top of the memory (the shift just puts it into KiB).
Now without my modifications the BIOS makes it into filo and can do some stuff before dying. With my modifications it dies within elfboot. With these statements at the end of the log:
Jumping to boot code at 0x10af40 entry = 0x0010af40 lb_start = 0x00004000 lb_size = 0x00014000 adjust = 0x3ffe8000 buffer = 0x3ffd8000 elf_boot_notes = 0x0000eb80 adjusted_boot_notes = 0x3fff6b80
In the unmodified form these log statements look like
Jumping to boot code at 0x10af40 entry = 0x0010af40 lb_start = 0x00004000 lb_size = 0x00014000 adjust = 0xfffe8000 buffer = 0xfffd8000 elf_boot_notes = 0x0000ec00 adjusted_boot_notes = 0xffff6c00
I am at a loss for what is going wrong here and would appreciate any insight that anyone has. Below is the unmodified form of the function. I commented out the pci_write's because those registers are not documented in my datasheet, nor is there any mention of low memory.
Thanks for any help!
static void pci_domain_set_resources(device_t dev) { device_t mc_dev; uint32_t pci_tolm;
pci_tolm = find_pci_tolm(&dev->link[0]); mc_dev = dev->link[0].children; printk_debug("MC dev vid = %x\n", mc_dev->vendor); printk_debug("MC dev did = %x\n", mc_dev->device); if (mc_dev) { /* Figure out which areas are/should be occupied by RAM. * This is all computed in kilobytes and converted to/from * the memory controller right at the edges. * Having different variables in different units is * too confusing to get right. Kilobytes are good up to * 4 Terabytes of RAM... */ uint16_t tolm_r, remapbase_r, remaplimit_r; unsigned long tomk, tolmk; unsigned long remapbasek, remaplimitk; int idx;
/* Get the value of the highest DRB. This tells the end of * the physical memory. The units are ticks of 64MB * i.e. 1 means 64MB. */ tomk = ((unsigned long)pci_read_config8(mc_dev, 0x63)) << 15; /* Compute the top of Low memory */ tolmk = pci_tolm >> 10; if (tolmk >= tomk) { /* The PCI hole does not overlap memory * we won't use the remap window. */ tolmk = tomk; remapbasek = 0x3ff << 15; remaplimitk = 0 << 15; } else { /* The PCI memory hole overlaps memory * setup the remap window. */ /* Find the bottom of the remap window * is it above 4G? */ remapbasek = 4*1024*1024; if (tomk > remapbasek) { remapbasek = tomk; } /* Find the limit of the remap window */ remaplimitk = (remapbasek + (4*1024*1024 - tolmk) - (1 << 15)); } /* Write the ram configuration registers, * preserving the reserved bits. */ /* tolm_r = pci_read_config16(mc_dev, 0xc4); tolm_r = ((tolmk >> 17) << 11) | (tolm_r & 0x7ff); pci_write_config16(mc_dev, 0xc4, tolm_r);
remapbase_r = pci_read_config16(mc_dev, 0xc6); remapbase_r = (remapbasek >> 16) | (remapbase_r & 0xfc00); pci_write_config16(mc_dev, 0xc6, remapbase_r); remaplimit_r = pci_read_config16(mc_dev, 0xc8); remaplimit_r = (remaplimitk >> 16) | (remaplimit_r & 0xfc00); pci_write_config16(mc_dev, 0xc8, remaplimit_r); */ /* Report the memory regions */ printk_debug("tomk = %d\n", tomk); printk_debug("tolmk = %d\n", tolmk); printk_debug("remaplimitk = %d\n", remaplimitk); printk_debug("remapbasek = %d\n", remapbasek);
idx = 10; ram_resource(dev, idx++, 0, 640); ram_resource(dev, idx++, 768, tolmk - 768); if (tomk > 4*1024*1024) { ram_resource(dev, idx++, 4096*1024, tomk - 4*1024*1024); } if (remaplimitk >= remapbasek) { ram_resource(dev, idx++, remapbasek, (remaplimitk + 64*1024) - remapbasek); } } assign_resources(&dev->link[0]); }