Commit a5797c1f authored by Dave Jones's avatar Dave Jones

Merge bk://linux-dj.bkbits.net/agpgart

into delerium.codemonkey.org.uk:/mnt/data/src/bk/agpgart
parents 20e743bb 6cf5f82c
......@@ -20,6 +20,8 @@
#define AMD_TLBFLUSH 0x0c /* In mmio region (32-bit register) */
#define AMD_CACHEENTRY 0x10 /* In mmio region (32-bit register) */
static struct pci_device_id agp_amdk7_pci_table[];
struct amd_page_map {
unsigned long *real;
unsigned long *remapped;
......@@ -41,7 +43,7 @@ static int amd_create_page_map(struct amd_page_map *page_map)
SetPageReserved(virt_to_page(page_map->real));
global_cache_flush();
page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
PAGE_SIZE);
if (page_map->remapped == NULL) {
ClearPageReserved(virt_to_page(page_map->real));
......@@ -90,7 +92,7 @@ static int amd_create_gatt_pages(int nr_tables)
int retval = 0;
int i;
tables = kmalloc((nr_tables + 1) * sizeof(struct amd_page_map *),
tables = kmalloc((nr_tables + 1) * sizeof(struct amd_page_map *),
GFP_KERNEL);
if (tables == NULL)
return -ENOMEM;
......@@ -124,7 +126,7 @@ static int amd_create_gatt_pages(int nr_tables)
#define GET_PAGE_DIR_OFF(addr) (addr >> 22)
#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \
GET_PAGE_DIR_OFF(agp_bridge->gart_bus_addr))
#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12)
#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12)
#define GET_GATT(addr) (amd_irongate_private.gatt_pages[\
GET_PAGE_DIR_IDX(addr)]->remapped)
......@@ -174,7 +176,7 @@ static int amd_create_gatt_table(void)
static int amd_free_gatt_table(void)
{
struct amd_page_map page_dir;
page_dir.real = (unsigned long *)agp_bridge->gatt_table_real;
page_dir.remapped = (unsigned long *)agp_bridge->gatt_table;
......@@ -224,9 +226,9 @@ static int amd_irongate_configure(void)
/* Write the Sync register */
pci_write_config_byte(agp_bridge->dev, AMD_MODECNTL, 0x80);
/* Set indexing mode */
pci_write_config_byte(agp_bridge->dev, AMD_MODECNTL2, 0x00);
/* Set indexing mode */
pci_write_config_byte(agp_bridge->dev, AMD_MODECNTL2, 0x00);
/* Write the enable register */
enable_reg = INREG16(amd_irongate_private.registers, AMD_GARTENABLE);
......@@ -394,7 +396,6 @@ static struct agp_device_ids amd_agp_device_ids[] __devinitdata =
static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct agp_device_ids *devs = amd_agp_device_ids;
struct agp_bridge_data *bridge;
u8 cap_ptr;
int j;
......@@ -403,19 +404,10 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
if (!cap_ptr)
return -ENODEV;
for (j = 0; devs[j].chipset_name; j++) {
if (pdev->device == devs[j].device_id) {
printk (KERN_INFO PFX "Detected AMD %s chipset\n",
devs[j].chipset_name);
goto found;
}
}
printk(KERN_ERR PFX "Unsupported AMD chipset (device id: %04x)\n",
pdev->device);
return -ENODEV;
j = ent - agp_amdk7_pci_table;
printk(KERN_INFO PFX "Detected AMD %s chipset\n",
amd_agp_device_ids[j].chipset_name);
found:
bridge = agp_alloc_bridge();
if (!bridge)
return -ENOMEM;
......@@ -442,12 +434,29 @@ static void __devexit agp_amdk7_remove(struct pci_dev *pdev)
agp_put_bridge(bridge);
}
/* must be the same order as name table above */
static struct pci_device_id agp_amdk7_pci_table[] = {
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0,
.vendor = PCI_VENDOR_ID_AMD,
.device = PCI_ANY_ID,
.device = PCI_DEVICE_ID_AMD_FE_GATE_7006,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0,
.vendor = PCI_VENDOR_ID_AMD,
.device = PCI_DEVICE_ID_AMD_FE_GATE_700E,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0,
.vendor = PCI_VENDOR_ID_AMD,
.device = PCI_DEVICE_ID_AMD_FE_GATE_700C,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
......
/*
/*
* Copyright 2001-2003 SuSE Labs.
* Distributed under the GNU public license, v2.
*
*
* This is a GART driver for the AMD Opteron/Athlon64 on-CPU northbridge.
* It also includes support for the AMD 8151 AGP bridge,
* although it doesn't actually do much, as all the real
......@@ -194,7 +194,7 @@ static u64 amd64_configure (struct pci_dev *hammer, u64 gatt_table)
/* keep CPU's coherent. */
flush_amd64_tlb (hammer);
return aper_base;
}
......@@ -261,53 +261,53 @@ struct agp_bridge_driver amd_8151_driver = {
/* Some basic sanity checks for the aperture. */
static int __devinit aperture_valid(u64 aper, u32 size)
{
{
u32 pfn, c;
if (aper == 0) {
if (aper == 0) {
printk(KERN_ERR PFX "No aperture\n");
return 0;
return 0;
}
if (size < 32*1024*1024) {
printk(KERN_ERR PFX "Aperture too small (%d MB)\n", size>>20);
return 0;
}
if (aper + size > 0xffffffff) {
printk(KERN_ERR PFX "Aperture out of bounds\n");
if (aper + size > 0xffffffff) {
printk(KERN_ERR PFX "Aperture out of bounds\n");
return 0;
}
}
pfn = aper >> PAGE_SHIFT;
for (c = 0; c < size/PAGE_SIZE; c++) {
for (c = 0; c < size/PAGE_SIZE; c++) {
if (!pfn_valid(pfn + c))
break;
if (!PageReserved(pfn_to_page(pfn + c))) {
if (!PageReserved(pfn_to_page(pfn + c))) {
printk(KERN_ERR PFX "Aperture pointing to RAM\n");
return 0;
}
}
/* Request the Aperture. This catches cases when someone else
already put a mapping in there - happens with some very broken BIOS
already put a mapping in there - happens with some very broken BIOS
Maybe better to use pci_assign_resource/pci_enable_device instead trusting
the bridges? */
Maybe better to use pci_assign_resource/pci_enable_device instead
trusting the bridges? */
if (!aperture_resource &&
!(aperture_resource = request_mem_region(aper, size, "aperture"))) {
printk(KERN_ERR PFX "Aperture conflicts with PCI mapping.\n");
printk(KERN_ERR PFX "Aperture conflicts with PCI mapping.\n");
return 0;
}
return 1;
}
}
/*
/*
* W*s centric BIOS sometimes only set up the aperture in the AGP
* bridge, not the northbridge. On AMD64 this is handled early
* bridge, not the northbridge. On AMD64 this is handled early
* in aperture.c, but when GART_IOMMU is not enabled or we run
* on a 32bit kernel this needs to be redone.
* on a 32bit kernel this needs to be redone.
* Unfortunately it is impossible to fix the aperture here because it's too late
* to allocate that much memory. But at least error out cleanly instead of
* crashing.
*/
static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp,
*/
static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp,
u16 cap)
{
u32 aper_low, aper_hi;
......@@ -316,38 +316,38 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp,
u32 nb_order, nb_base;
u16 apsize;
pci_read_config_dword(nb, 0x90, &nb_order);
pci_read_config_dword(nb, 0x90, &nb_order);
nb_order = (nb_order >> 1) & 7;
pci_read_config_dword(nb, 0x94, &nb_base);
nb_aper = nb_base << 25;
if (aperture_valid(nb_aper, (32*1024*1024)<<nb_order)) {
pci_read_config_dword(nb, 0x94, &nb_base);
nb_aper = nb_base << 25;
if (aperture_valid(nb_aper, (32*1024*1024)<<nb_order)) {
return 0;
}
/* Northbridge seems to contain crap. Try the AGP bridge. */
pci_read_config_word(agp, cap+0x14, &apsize);
if (apsize == 0xffff)
return -1;
pci_read_config_word(agp, cap+0x14, &apsize);
if (apsize == 0xffff)
return -1;
apsize &= 0xfff;
/* Some BIOS use weird encodings not in the AGPv3 table. */
if (apsize & 0xff)
apsize |= 0xf00;
order = 7 - hweight16(apsize);
if (apsize & 0xff)
apsize |= 0xf00;
order = 7 - hweight16(apsize);
pci_read_config_dword(agp, 0x10, &aper_low);
pci_read_config_dword(agp, 0x14, &aper_hi);
aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32);
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 -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)
{
......@@ -355,19 +355,19 @@ static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr)
int i = 0;
/* cache pci_devs of northbridges. */
while ((loop_dev = pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev))
while ((loop_dev = pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev))
!= NULL) {
if (i == MAX_HAMMER_GARTS) {
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) {
if (fix_northbridge(loop_dev, pdev, cap_ptr) < 0) {
printk(KERN_ERR PFX "No usable aperture found.\n");
#ifdef __x86_64__
#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;
#endif
return -1;
}
hammers[i++] = loop_dev;
}
......@@ -377,8 +377,7 @@ static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr)
/* Handle AMD 8151 quirks */
static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge)
{
{
char *revstring;
u8 rev_id;
......@@ -417,12 +416,12 @@ static struct aper_size_info_32 nforce3_sizes[5] =
/* 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)
{
static int __devinit nforce3_agp_init(struct pci_dev *pdev)
{
u32 tmp, apbase, apbar, aplimit;
struct pci_dev *dev1;
struct pci_dev *dev1;
int i;
unsigned size = amd64_fetch_size();
unsigned size = amd64_fetch_size();
printk(KERN_INFO PFX "Setting up Nforce3 AGP.\n");
......@@ -432,17 +431,17 @@ static int __devinit nforce3_agp_init(struct pci_dev *pdev)
"nForce3 chipset, but could not find "
"the secondary device.\n");
return -ENODEV;
}
}
for (i = 0; i < ARRAY_SIZE(nforce3_sizes); i++)
for (i = 0; i < ARRAY_SIZE(nforce3_sizes); i++)
if (nforce3_sizes[i].size == size)
break;
break;
if (i == ARRAY_SIZE(nforce3_sizes)) {
printk(KERN_INFO PFX "No NForce3 size found for %d\n", size);
return -ENODEV;
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;
......@@ -491,8 +490,7 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev,
pdev->device == PCI_DEVICE_ID_AMD_8151_0) {
amd8151_init(pdev, bridge);
} else {
printk(KERN_INFO PFX "Detected AGP bridge %x\n",
pdev->devfn);
printk(KERN_INFO PFX "Detected AGP bridge %x\n", pdev->devfn);
}
bridge->driver = &amd_8151_driver;
......@@ -507,10 +505,10 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev,
return -ENODEV;
}
if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) {
if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) {
int ret = nforce3_agp_init(pdev);
if (ret) {
agp_put_bridge(bridge);
if (ret) {
agp_put_bridge(bridge);
return ret;
}
}
......@@ -523,8 +521,8 @@ 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);
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);
}
......@@ -581,6 +579,15 @@ static struct pci_device_id agp_amd64_pci_table[] = {
.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,
},
{ }
};
......@@ -600,15 +607,15 @@ int __init agp_amd64_init(void)
int err = 0;
if (agp_off)
return -EINVAL;
if (pci_module_init(&agp_amd64_pci_driver) > 0) {
if (pci_module_init(&agp_amd64_pci_driver) > 0) {
struct pci_dev *dev;
if (!agp_try_unsupported && !agp_try_unsupported_boot) {
if (!agp_try_unsupported && !agp_try_unsupported_boot) {
printk(KERN_INFO PFX "No supported AGP bridge found.\n");
#ifdef MODULE
#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
#endif
return -ENODEV;
}
......@@ -622,12 +629,12 @@ int __init agp_amd64_init(void)
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 */
/* Only one bridge supported right now */
if (agp_amd64_probe(dev, NULL) == 0) {
err = 0;
break;
}
}
}
}
}
return err;
}
......
......@@ -131,6 +131,7 @@ static int ati_create_gatt_pages(int nr_tables)
i--;
}
kfree (tables);
tables = NULL;
retval = -ENOMEM;
break;
}
......
......@@ -238,11 +238,14 @@ void agp_put_bridge(struct agp_bridge_data *bridge)
}
EXPORT_SYMBOL(agp_put_bridge);
int agp_add_bridge(struct agp_bridge_data *bridge)
{
int error;
if (agp_off)
return -ENODEV;
if (!bridge->dev) {
printk (KERN_DEBUG PFX "Erk, registering with no pci_dev!\n");
return -EINVAL;
......@@ -308,9 +311,9 @@ EXPORT_SYMBOL(agp_try_unsupported_boot);
static int __init agp_init(void)
{
if (!agp_off)
printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Dave Jones\n",
AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR);
if (!agp_off)
printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Dave Jones\n",
AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR);
return 0;
}
......@@ -325,7 +328,7 @@ static __init int agp_setup(char *s)
agp_off = 1;
if (!strcmp(s,"try_unsupported"))
agp_try_unsupported_boot = 1;
return 1;
return 1;
}
__setup("agp=", agp_setup);
#endif
......
......@@ -1233,7 +1233,7 @@ static int find_i810(u16 device, const char *name)
name);
return 0;
}
intel_i810_private.i810_dev = i810_dev;
return 1;
}
......@@ -1382,8 +1382,10 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
name = "E7205";
break;
default:
printk(KERN_ERR PFX "Unsupported Intel chipset (device id: %04x)\n",
if (cap_ptr)
printk(KERN_WARNING PFX "Unsupported Intel chipset (device id: %04x)\n",
pdev->device);
agp_put_bridge(bridge);
return -ENODEV;
};
......@@ -1406,7 +1408,8 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
if (!r->start && r->end) {
if(pci_assign_resource(pdev, 0)) {
printk(KERN_ERR PFX "could not assign resource 0\n");
return (-ENODEV);
agp_put_bridge(bridge);
return -ENODEV;
}
}
......@@ -1417,7 +1420,8 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
*/
if (pci_enable_device(pdev)) {
printk(KERN_ERR PFX "Unable to Enable PCI device\n");
return (-ENODEV);
agp_put_bridge(bridge);
return -ENODEV;
}
/* Fill in the mode register */
......@@ -1442,14 +1446,11 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev)
agp_put_bridge(bridge);
}
static int agp_intel_suspend(struct pci_dev *dev, u32 state)
{
return 0;
}
static int agp_intel_resume(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
pci_restore_state(pdev, pdev->saved_config_space);
if (bridge->driver == &intel_generic_driver)
intel_configure();
......@@ -1462,14 +1463,36 @@ static int agp_intel_resume(struct pci_dev *pdev)
}
static struct pci_device_id agp_intel_pci_table[] = {
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0,
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
#define ID(x) \
{ \
.class = (PCI_CLASS_BRIDGE_HOST << 8), \
.class_mask = ~0, \
.vendor = PCI_VENDOR_ID_INTEL, \
.device = x, \
.subvendor = PCI_ANY_ID, \
.subdevice = PCI_ANY_ID, \
}
ID(PCI_DEVICE_ID_INTEL_82443LX_0),
ID(PCI_DEVICE_ID_INTEL_82443BX_0),
ID(PCI_DEVICE_ID_INTEL_82443GX_0),
ID(PCI_DEVICE_ID_INTEL_82810_MC1),
ID(PCI_DEVICE_ID_INTEL_82810_MC3),
ID(PCI_DEVICE_ID_INTEL_82810E_MC),
ID(PCI_DEVICE_ID_INTEL_82815_MC),
ID(PCI_DEVICE_ID_INTEL_82820_HB),
ID(PCI_DEVICE_ID_INTEL_82820_UP_HB),
ID(PCI_DEVICE_ID_INTEL_82830_HB),
ID(PCI_DEVICE_ID_INTEL_82840_HB),
ID(PCI_DEVICE_ID_INTEL_82845_HB),
ID(PCI_DEVICE_ID_INTEL_82845G_HB),
ID(PCI_DEVICE_ID_INTEL_82850_HB),
ID(PCI_DEVICE_ID_INTEL_82855PM_HB),
ID(PCI_DEVICE_ID_INTEL_82855GM_HB),
ID(PCI_DEVICE_ID_INTEL_82860_HB),
ID(PCI_DEVICE_ID_INTEL_82865_HB),
ID(PCI_DEVICE_ID_INTEL_82875_HB),
ID(PCI_DEVICE_ID_INTEL_7505_0),
ID(PCI_DEVICE_ID_INTEL_7205_0),
{ }
};
......@@ -1480,7 +1503,6 @@ static struct pci_driver agp_intel_pci_driver = {
.id_table = agp_intel_pci_table,
.probe = agp_intel_probe,
.remove = agp_intel_remove,
.suspend = agp_intel_suspend,
.resume = agp_intel_resume,
};
......
......@@ -491,10 +491,9 @@ static int __devinit agp_intelmch_probe(struct pci_dev *pdev,
char *name = "(unknown)";
u8 cap_ptr = 0;
if (!boot_cpu_has(X86_FEATURE_LM))
return -ENODEV;
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
if (!cap_ptr)
return -ENODEV;
bridge = agp_alloc_bridge();
if (!bridge)
......@@ -570,14 +569,11 @@ static void __devexit agp_intelmch_remove(struct pci_dev *pdev)
agp_put_bridge(bridge);
}
static int agp_intelmch_suspend(struct pci_dev *dev, u32 state)
{
return 0;
}
static int agp_intelmch_resume(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
pci_restore_state(pdev, pdev->saved_config_space);
if (bridge->driver == &intel_845_driver)
intel_845_configure();
......@@ -590,7 +586,15 @@ static struct pci_device_id agp_intelmch_pci_table[] = {
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0,
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_ANY_ID,
.device = PCI_DEVICE_ID_INTEL_82865_HB,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0,
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_82875_HB,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
......@@ -604,7 +608,6 @@ static struct pci_driver agp_intelmch_pci_driver = {
.id_table = agp_intelmch_pci_table,
.probe = agp_intelmch_probe,
.remove = agp_intelmch_remove,
.suspend = agp_intelmch_suspend,
.resume = agp_intelmch_resume,
};
......
......@@ -380,7 +380,15 @@ static struct pci_device_id agp_nvidia_pci_table[] = {
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0,
.vendor = PCI_VENDOR_ID_NVIDIA,
.device = PCI_ANY_ID,
.device = PCI_DEVICE_ID_NVIDIA_NFORCE,
.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_NFORCE2,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
......
......@@ -13,6 +13,8 @@
#define SIS_TLBCNTRL 0x97
#define SIS_TLBFLUSH 0x98
static int __devinitdata agp_sis_force_delay = 0;
static int __devinitdata agp_sis_agp_spec = -1;
static int sis_fetch_size(void)
{
......@@ -67,7 +69,7 @@ static void sis_cleanup(void)
(previous_size->size_value & ~(0x03)));
}
static void sis_648_enable(u32 mode)
static void sis_delayed_enable(u32 mode)
{
struct pci_dev *device = NULL;
u32 command;
......@@ -94,13 +96,12 @@ static void sis_648_enable(u32 mode)
pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command);
/*
* Weird: on 648(fx) and 746(fx) chipsets any rate change in the target
* Weird: on some sis chipsets any rate change in the target
* command register triggers a 5ms screwup during which the master
* cannot be configured
*/
if (device->device == PCI_DEVICE_ID_SI_648 ||
device->device == PCI_DEVICE_ID_SI_746) {
printk(KERN_INFO PFX "SiS chipset with AGP problems detected. Giving bridge time to recover.\n");
if (device->device == agp_bridge->dev->device) {
printk(KERN_INFO PFX "SiS delay workaround: giving bridge time to recover.\n");
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout (1+(HZ*10)/1000);
}
......@@ -223,28 +224,35 @@ static struct agp_device_ids sis_agp_device_ids[] __devinitdata =
};
// chipsets that require the 'delay hack'
static int sis_broken_chipsets[] __devinitdata = {
PCI_DEVICE_ID_SI_648,
PCI_DEVICE_ID_SI_746,
0 // terminator
};
static void __devinit sis_get_driver(struct agp_bridge_data *bridge)
{
if (bridge->dev->device == PCI_DEVICE_ID_SI_648) {
sis_driver.agp_enable=sis_648_enable;
if (agp_bridge->major_version == 3) {
sis_driver.aperture_sizes = agp3_generic_sizes;
sis_driver.size_type = U16_APER_SIZE;
sis_driver.num_aperture_sizes = AGP_GENERIC_SIZES_ENTRIES;
sis_driver.configure = agp3_generic_configure;
sis_driver.fetch_size = agp3_generic_fetch_size;
sis_driver.cleanup = agp3_generic_cleanup;
sis_driver.tlb_flush = agp3_generic_tlbflush;
}
}
int i;
if (bridge->dev->device == PCI_DEVICE_ID_SI_746) {
/*
* We don't know enough about the 746 to enable it properly.
* Though we do know that it needs the 'delay' hack to settle
* after changing modes.
*/
sis_driver.agp_enable=sis_648_enable;
for(i=0; sis_broken_chipsets[i]!=0; ++i)
if(bridge->dev->device==sis_broken_chipsets[i])
break;
if(sis_broken_chipsets[i] || agp_sis_force_delay)
sis_driver.agp_enable=sis_delayed_enable;
// sis chipsets that indicate less than agp3.5
// are not actually fully agp3 compliant
if ((agp_bridge->major_version == 3 && agp_bridge->minor_version >= 5
&& agp_sis_agp_spec!=0) || agp_sis_agp_spec==1) {
sis_driver.aperture_sizes = agp3_generic_sizes;
sis_driver.size_type = U16_APER_SIZE;
sis_driver.num_aperture_sizes = AGP_GENERIC_SIZES_ENTRIES;
sis_driver.configure = agp3_generic_configure;
sis_driver.fetch_size = agp3_generic_fetch_size;
sis_driver.cleanup = agp3_generic_cleanup;
sis_driver.tlb_flush = agp3_generic_tlbflush;
}
}
......@@ -335,4 +343,8 @@ static void __exit agp_sis_cleanup(void)
module_init(agp_sis_init);
module_exit(agp_sis_cleanup);
MODULE_PARM(agp_sis_force_delay,"i");
MODULE_PARM_DESC(agp_sis_force_delay,"forces sis delay hack");
MODULE_PARM(agp_sis_agp_spec,"i");
MODULE_PARM_DESC(agp_sis_agp_spec,"0=force sis init, 1=force generic agp3 init, default: autodetect");
MODULE_LICENSE("GPL and additional rights");
......@@ -248,26 +248,13 @@ static int serverworks_fetch_size(void)
*/
static void serverworks_tlbflush(struct agp_memory *temp)
{
unsigned long end;
OUTREG8(serverworks_private.registers, SVWRKS_POSTFLUSH, 0x01);
end = jiffies + 3*HZ;
while(INREG8(serverworks_private.registers,
SVWRKS_POSTFLUSH) == 0x01) {
if((signed)(end - jiffies) <= 0) {
printk(KERN_ERR PFX "Posted write buffer flush took more"
"then 3 seconds\n");
}
}
OUTREG32(serverworks_private.registers, SVWRKS_DIRFLUSH, 0x00000001);
end = jiffies + 3*HZ;
while(INREG32(serverworks_private.registers,
SVWRKS_DIRFLUSH) == 0x00000001) {
if((signed)(end - jiffies) <= 0) {
printk(KERN_ERR PFX "TLB flush took more"
"then 3 seconds\n");
}
}
OUTREG8(serverworks_private.registers, SVWRKS_POSTFLUSH, 1);
while(INREG8(serverworks_private.registers, SVWRKS_POSTFLUSH) == 1)
cpu_relax();
OUTREG32(serverworks_private.registers, SVWRKS_DIRFLUSH, 1);
while(INREG32(serverworks_private.registers, SVWRKS_DIRFLUSH) == 1)
cpu_relax();
}
static int serverworks_configure(void)
......
......@@ -9,6 +9,8 @@
#include <linux/agp_backend.h>
#include "agp.h"
static struct pci_device_id agp_via_pci_table[];
#define VIA_GARTCTRL 0x80
#define VIA_APSIZE 0x84
#define VIA_ATTBASE 0x88
......@@ -378,20 +380,9 @@ static int __devinit agp_via_probe(struct pci_dev *pdev,
if (!cap_ptr)
return -ENODEV;
/* probe for known chipsets */
for (j = 0; devs[j].chipset_name; j++) {
if (pdev->device == devs[j].device_id) {
printk (KERN_INFO PFX "Detected VIA %s chipset\n",
devs[j].chipset_name);
goto found;
}
}
printk(KERN_ERR PFX "Unsupported VIA chipset (device id: %04x)\n",
pdev->device);
return -ENODEV;
j = ent - agp_via_pci_table;
printk (KERN_INFO PFX "Detected VIA %s chipset\n", devs[j].chipset_name);
found:
bridge = agp_alloc_bridge();
if (!bridge)
return -ENOMEM;
......@@ -432,15 +423,40 @@ static void __devexit agp_via_remove(struct pci_dev *pdev)
agp_put_bridge(bridge);
}
/* must be the same order as name table above */
static struct pci_device_id agp_via_pci_table[] = {
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
#define ID(x) \
{ \
.class = (PCI_CLASS_BRIDGE_HOST << 8), \
.class_mask = ~0, \
.vendor = PCI_VENDOR_ID_VIA, \
.device = x, \
.subvendor = PCI_ANY_ID, \
.subdevice = PCI_ANY_ID, \
}
ID(PCI_DEVICE_ID_VIA_82C598_0),
ID(PCI_DEVICE_ID_VIA_8501_0),
ID(PCI_DEVICE_ID_VIA_8601_0),
ID(PCI_DEVICE_ID_VIA_82C691_0),
ID(PCI_DEVICE_ID_VIA_8371_0),
ID(PCI_DEVICE_ID_VIA_8633_0),
ID(PCI_DEVICE_ID_VIA_XN266),
ID(PCI_DEVICE_ID_VIA_8361),
ID(PCI_DEVICE_ID_VIA_8363_0),
ID(PCI_DEVICE_ID_VIA_8753_0),
ID(PCI_DEVICE_ID_VIA_8367_0),
ID(PCI_DEVICE_ID_VIA_8653_0),
ID(PCI_DEVICE_ID_VIA_XM266),
ID(PCI_DEVICE_ID_VIA_862X_0),
ID(PCI_DEVICE_ID_VIA_8377_0),
ID(PCI_DEVICE_ID_VIA_8605_0),
ID(PCI_DEVICE_ID_VIA_8703_51_0),
ID(PCI_DEVICE_ID_VIA_8754C_0),
ID(PCI_DEVICE_ID_VIA_8763_0),
ID(PCI_DEVICE_ID_VIA_8378_0),
ID(PCI_DEVICE_ID_VIA_PT880),
ID(PCI_DEVICE_ID_VIA_8783_0),
ID(PCI_DEVICE_ID_VIA_PX8X0_0),
{ }
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment