📄 amd64-agp.c
字号:
aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32); printk(KERN_INFO PFX "Aperture from AGP @ %Lx size %u MB\n", aper, 32 << order); if (order < 0 || !aperture_valid(aper, (32*1024*1024)<<order)) return -1; pci_write_config_dword(nb, 0x90, order << 1); pci_write_config_dword(nb, 0x94, aper >> 25); return 0;}static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr){ struct pci_dev *loop_dev = NULL; int i = 0; /* cache pci_devs of northbridges. */ while ((loop_dev = pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev)) != NULL) { if (i == MAX_HAMMER_GARTS) { printk(KERN_ERR PFX "Too many northbridges for AGP\n"); return -1; } if (fix_northbridge(loop_dev, pdev, cap_ptr) < 0) { printk(KERN_ERR PFX "No usable aperture found.\n");#ifdef __x86_64__ /* should port this to i386 */ printk(KERN_ERR PFX "Consider rebooting with iommu=memaper=2 to get a good aperture.\n");#endif return -1; } hammers[i++] = loop_dev; } nr_garts = i; return i == 0 ? -1 : 0;}/* Handle AMD 8151 quirks */static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge){ char *revstring; u8 rev_id; pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); switch (rev_id) { case 0x01: revstring="A0"; break; case 0x02: revstring="A1"; break; case 0x11: revstring="B0"; break; case 0x12: revstring="B1"; break; case 0x13: revstring="B2"; break; case 0x14: revstring="B3"; break; default: revstring="??"; break; } printk (KERN_INFO PFX "Detected AMD 8151 AGP Bridge rev %s\n", revstring); /* * Work around errata. * Chips before B2 stepping incorrectly reporting v3.5 */ if (rev_id < 0x13) { printk (KERN_INFO PFX "Correcting AGP revision (reports 3.5, is really 3.0)\n"); bridge->major_version = 3; bridge->minor_version = 0; }}static struct aper_size_info_32 nforce3_sizes[5] ={ {512, 131072, 7, 0x00000000 }, {256, 65536, 6, 0x00000008 }, {128, 32768, 5, 0x0000000C }, {64, 16384, 4, 0x0000000E }, {32, 8192, 3, 0x0000000F }};/* Handle shadow device of the Nvidia NForce3 *//* CHECK-ME original 2.4 version set up some IORRs. Check if that is needed. */static int __devinit nforce3_agp_init(struct pci_dev *pdev){ u32 tmp, apbase, apbar, aplimit; struct pci_dev *dev1; int i; unsigned size = amd64_fetch_size(); printk(KERN_INFO PFX "Setting up Nforce3 AGP.\n"); dev1 = pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(11, 0)); if (dev1 == NULL) { printk(KERN_INFO PFX "agpgart: Detected an NVIDIA " "nForce3 chipset, but could not find " "the secondary device.\n"); return -ENODEV; } for (i = 0; i < ARRAY_SIZE(nforce3_sizes); i++) if (nforce3_sizes[i].size == size) break; if (i == ARRAY_SIZE(nforce3_sizes)) { printk(KERN_INFO PFX "No NForce3 size found for %d\n", size); return -ENODEV; } pci_read_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, &tmp); tmp &= ~(0xf); tmp |= nforce3_sizes[i].size_value; pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp); /* shadow x86-64 registers into NVIDIA registers */ pci_read_config_dword (hammers[0], AMD64_GARTAPERTUREBASE, &apbase); /* if x86-64 aperture base is beyond 4G, exit here */ if ( (apbase & 0x7fff) >> (32 - 25) ) return -ENODEV; apbase = (apbase & 0x7fff) << 25; pci_read_config_dword(pdev, NVIDIA_X86_64_0_APBASE, &apbar); apbar &= ~PCI_BASE_ADDRESS_MEM_MASK; apbar |= apbase; pci_write_config_dword(pdev, NVIDIA_X86_64_0_APBASE, apbar); aplimit = apbase + (size * 1024 * 1024) - 1; pci_write_config_dword(dev1, NVIDIA_X86_64_1_APBASE1, apbase); pci_write_config_dword(dev1, NVIDIA_X86_64_1_APLIMIT1, aplimit); pci_write_config_dword(dev1, NVIDIA_X86_64_1_APBASE2, apbase); pci_write_config_dword(dev1, NVIDIA_X86_64_1_APLIMIT2, aplimit); return 0;}static int __devinit agp_amd64_probe(struct pci_dev *pdev, const struct pci_device_id *ent){ struct agp_bridge_data *bridge; u8 cap_ptr; cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); if (!cap_ptr) return -ENODEV; /* Could check for AGPv3 here */ bridge = agp_alloc_bridge(); if (!bridge) return -ENOMEM; if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == PCI_DEVICE_ID_AMD_8151_0) { amd8151_init(pdev, bridge); } else { printk(KERN_INFO PFX "Detected AGP bridge %x\n", pdev->devfn); } bridge->driver = &amd_8151_driver; bridge->dev = pdev; bridge->capndx = cap_ptr; /* Fill in the mode register */ pci_read_config_dword(pdev, bridge->capndx+PCI_AGP_STATUS, &bridge->mode); if (cache_nbs(pdev, cap_ptr) == -1) { agp_put_bridge(bridge); return -ENODEV; } if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) { int ret = nforce3_agp_init(pdev); if (ret) { agp_put_bridge(bridge); return ret; } } pci_set_drvdata(pdev, bridge); return agp_add_bridge(bridge);}static void __devexit agp_amd64_remove(struct pci_dev *pdev){ struct agp_bridge_data *bridge = pci_get_drvdata(pdev); release_mem_region(virt_to_phys(bridge->gatt_table_real), amd64_aperture_sizes[bridge->aperture_size_idx].size); agp_remove_bridge(bridge); agp_put_bridge(bridge);}static struct pci_device_id agp_amd64_pci_table[] = { { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, .vendor = PCI_VENDOR_ID_AMD, .device = PCI_DEVICE_ID_AMD_8151_0, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, /* VIA K8T800Pro */ { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, .vendor = PCI_VENDOR_ID_VIA, .device = PCI_DEVICE_ID_VIA_K8T800PRO_0, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, /* VIA K8T800 */ { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, .vendor = PCI_VENDOR_ID_VIA, .device = PCI_DEVICE_ID_VIA_8385_0, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, /* VIA K8M800 / K8N800 */ { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, .vendor = PCI_VENDOR_ID_VIA, .device = PCI_DEVICE_ID_VIA_8380_0, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, /* VIA K8T890 */ { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, .vendor = PCI_VENDOR_ID_VIA, .device = PCI_DEVICE_ID_VIA_3238_0, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, /* VIA K8T800/K8M800/K8N800 */ { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, .vendor = PCI_VENDOR_ID_VIA, .device = PCI_DEVICE_ID_VIA_838X_1, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, /* NForce3 */ { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NFORCE3, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NFORCE3S, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, /* SIS 755 */ { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, .vendor = PCI_VENDOR_ID_SI, .device = PCI_DEVICE_ID_SI_755, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, { }};MODULE_DEVICE_TABLE(pci, agp_amd64_pci_table);static struct pci_driver agp_amd64_pci_driver = { .name = "agpgart-amd64", .id_table = agp_amd64_pci_table, .probe = agp_amd64_probe, .remove = agp_amd64_remove,};/* Not static due to IOMMU code calling it early. */int __init agp_amd64_init(void){ int err = 0; if (agp_off) return -EINVAL; if (pci_module_init(&agp_amd64_pci_driver) > 0) { struct pci_dev *dev; if (!agp_try_unsupported && !agp_try_unsupported_boot) { printk(KERN_INFO PFX "No supported AGP bridge found.\n");#ifdef MODULE printk(KERN_INFO PFX "You can try agp_try_unsupported=1\n");#else printk(KERN_INFO PFX "You can boot with agp=try_unsupported\n");#endif return -ENODEV; } /* First check that we have at least one AMD64 NB */ if (!pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, NULL)) return -ENODEV; /* Look for any AGP bridge */ dev = NULL; err = -ENODEV; while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev))) { if (!pci_find_capability(dev, PCI_CAP_ID_AGP)) continue; /* Only one bridge supported right now */ if (agp_amd64_probe(dev, NULL) == 0) { err = 0; break; } } } return err;}static void __exit agp_amd64_cleanup(void){ if (aperture_resource) release_resource(aperture_resource); pci_unregister_driver(&agp_amd64_pci_driver);}/* On AMD64 the PCI driver needs to initialize this driver early for the IOMMU, so it has to be called via a backdoor. */#ifndef CONFIG_GART_IOMMUmodule_init(agp_amd64_init);module_exit(agp_amd64_cleanup);#endifMODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>, Andi Kleen");MODULE_PARM(agp_try_unsupported, "1i");MODULE_LICENSE("GPL and additional rights");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -