public override bool InitServer() { System.Diagnostics.Debugger.Log(0, "pci", "hostbridge started with " + root.Count.ToString() + " properties"); /* Extract the resources we have been given */ vmems.Init(root); pmems.Init(root); ios.Init(root); acpiname = GetFirstProperty(root, "acpiname") as string; acpiconf = ACPIConfiguration.GetConfiguration(root); foreach (var res in root) { if (res.Name == "interrupt" && (res.Value is ACPIInterrupt)) { var acpi_int = res.Value as ACPIInterrupt; if (acpi_int.irq != -1) { isa_irqs[acpi_int.irq] = acpi_int; } } } DeviceDB.InitDeviceDB(this); /* Get CONFIG_DATA and CONFIG_ADDRESS ports */ CONFIG_ADDRESS = ios.AllocFixed(0xcf8, 4); CONFIG_DATA = ios.AllocFixed(0xcfc, 4); if (CONFIG_ADDRESS == null) { throw new Exception("Unable to obtain CONFIG_ADDRESS"); } if (CONFIG_DATA == null) { throw new Exception("Unable to obtain CONFIG_DATA"); } /* Get extra details from ACPI if available */ if (acpiname != null && acpiconf.ContainsKey(acpiname)) { /* Get a list of subdevices */ IList <ACPIName> subdevs = acpiconf[acpiname].GetDevices(1); foreach (var subdev in subdevs) { System.Diagnostics.Debugger.Log(0, "pci", "acpi reported subdevice: " + subdev); var adr = acpiconf[acpiname].EvaluateObject(subdev + "._ADR", ACPIObject.DataType.Integer); if (adr != null) { System.Diagnostics.Debugger.Log(0, "pci", "on device " + adr.IntegerData.ToString()); acpinames[(int)adr.IntegerData] = subdev; } } /* Evaluate _PRT object */ prts = acpiconf[acpiname].GetPRT(); } /* Enumerate the devices on this bus */ for (int dev = 0; dev < 32; dev++) { CheckDevice(0, dev, 0); } root.Add(new tysos.lib.File.Property { Name = "class", Value = "bus" }); Tags.Add("class"); return(true); }
private void CheckDevice(int bus, int dev, int func) { uint vendor_devID = ReadConfig(bus, dev, func, 0); uint vendorID = vendor_devID & 0xffff; if (vendorID == 0xffff) { return; } /* Get the basic fields of the device */ uint command_status = ReadConfig(bus, dev, func, 4); uint revID_progIF_subclass_class = ReadConfig(bus, dev, func, 8); uint cacheline_latency_ht_bist = ReadConfig(bus, dev, func, 0xc); /* We have found a valid device */ uint deviceID = vendor_devID >> 16; uint classcode = (revID_progIF_subclass_class >> 24) & 0xffU; uint subclasscode = (revID_progIF_subclass_class >> 16) & 0xffU; uint prog_IF = (revID_progIF_subclass_class >> 8) & 0xffU; uint revisionID = revID_progIF_subclass_class & 0xffU; System.Diagnostics.Debugger.Log(0, "pci", bus.ToString() + ":" + dev.ToString() + ":" + func.ToString() + " : " + vendorID.ToString("X4") + ":" + deviceID.ToString("X4") + " " + classcode.ToString("X2") + ":" + subclasscode.ToString("X2") + ":" + prog_IF.ToString("X2")); DeviceDBEntry details = DeviceDB.GetDeviceDetails(new DeviceDBKey { VendorID = vendorID, DeviceID = deviceID, RevisionID = revisionID, ClassCode = classcode, SubclassCode = subclasscode, ProgIF = prog_IF }); if (details == null) { System.Diagnostics.Debugger.Log(0, "pci", "unknown device"); } else { System.Diagnostics.Debugger.Log(0, "pci", details.ToString()); if (details.DriverName != null) { /* Build a device node */ List <tysos.lib.File.Property> props = new List <tysos.lib.File.Property>(); props.Add(new tysos.lib.File.Property { Name = "driver", Value = details.DriverName }); if (details.SubdriverName != null) { props.Add(new tysos.lib.File.Property { Name = "subdriver", Value = details.SubdriverName }); } if (details.HumanDeviceName != null) { props.Add(new tysos.lib.File.Property { Name = "name", Value = details.HumanDeviceName }); } if (details.HumanManufacturerName != null) { props.Add(new tysos.lib.File.Property { Name = "manufacturer", Value = details.HumanManufacturerName }); } PCIConfiguration conf = new PCIConfiguration(CONFIG_ADDRESS, CONFIG_DATA, bus, dev, func, this, details.BAROverrides); props.Add(new tysos.lib.File.Property { Name = "pciconf", Value = conf }); if (details.ExtraResources != null) { foreach (var res in details.ExtraResources) { if (res is tysos.Resources.InterruptLine) { props.Add(new tysos.lib.File.Property { Name = "interrupt", Value = res }); } else if (res is tysos.PhysicalMemoryResource64) { props.Add(new tysos.lib.File.Property { Name = "pmem", Value = res }); } else if (res is tysos.VirtualMemoryResource64) { props.Add(new tysos.lib.File.Property { Name = "vmem", Value = res }); } else if (res is tysos.x86_64.IOResource) { props.Add(new tysos.lib.File.Property { Name = "io", Value = res }); } } } /* Is the device enumerated in ACPI too? */ int dev_acpi = dev << 16 | func; int dev_acpi_all = dev << 16 | 0xffff; if (acpinames.ContainsKey(dev_acpi)) { props.Add(new tysos.lib.File.Property { Name = "acpiname", Value = acpinames[dev_acpi] }); } if (acpinames.ContainsKey(dev_acpi_all)) { props.Add(new tysos.lib.File.Property { Name = "acpiname", Value = acpinames[dev_acpi_all] }); } // Get interrupt pin number uint conf_3c = conf.ReadConfig(0x3c); uint pin = (conf_3c >> 8) & 0xffU; if (pin != 0) { int int_pin = (int)(pin - 1); if (prts.ContainsKey(dev_acpi)) { props.Add(new tysos.lib.File.Property { Name = "interrupt", Value = prts[dev_acpi][int_pin] }); } if (prts.ContainsKey(dev_acpi_all)) { props.Add(new tysos.lib.File.Property { Name = "interrupt", Value = prts[dev_acpi_all][int_pin] }); } } /* Generate a unique name for the device */ int dev_no = 0; StringBuilder sb = new StringBuilder(details.DriverName); if (details.SubdriverName != null) { sb.Append("_"); sb.Append(details.SubdriverName); } string base_dev = sb.ToString(); if (next_device_id.ContainsKey(base_dev)) { dev_no = next_device_id[base_dev]; } sb.Append("_"); sb.Append(dev_no.ToString()); next_device_id[base_dev] = dev_no + 1; string dev_name = sb.ToString(); children[dev_name] = props; foreach (var prop in props) { System.Diagnostics.Debugger.Log(0, "pci", " " + prop.Name + ": " + prop.Value.ToString()); } } } /* If header type == 0x80, it is a multifunction device */ uint header_type = (cacheline_latency_ht_bist >> 16) & 0xffU; if (header_type == 0x80 && func == 0) { for (int subfunc = 1; subfunc < 8; subfunc++) { CheckDevice(bus, dev, subfunc); } } }