sis-agp.c revision e5524f355a0d272ba5233537a896a668db1f3008
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SiS AGPGART routines. 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/agp_backend.h> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "agp.h" 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SIS_ATTBASE 0x90 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SIS_APSIZE 0x94 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SIS_TLBCNTRL 0x97 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SIS_TLBFLUSH 0x98 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __devinitdata agp_sis_force_delay = 0; 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __devinitdata agp_sis_agp_spec = -1; 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sis_fetch_size(void) 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 temp_size; 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aper_size_info_8 *values; 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_byte(agp_bridge->dev, SIS_APSIZE, &temp_size); 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds values = A_SIZE_8(agp_bridge->driver->aperture_sizes); 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((temp_size == values[i].size_value) || 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((temp_size & ~(0x03)) == 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (values[i].size_value & ~(0x03)))) { 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_bridge->previous_size = 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_bridge->current_size = (void *) (values + i); 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_bridge->aperture_size_idx = i; 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return values[i].size; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sis_tlbflush(struct agp_memory *mem) 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_byte(agp_bridge->dev, SIS_TLBFLUSH, 0x02); 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sis_configure(void) 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 temp; 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aper_size_info_8 *current_size; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_size = A_SIZE_8(agp_bridge->current_size); 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_byte(agp_bridge->dev, SIS_TLBCNTRL, 0x05); 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_dword(agp_bridge->dev, SIS_ATTBASE, 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_bridge->gatt_bus_addr); 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_byte(agp_bridge->dev, SIS_APSIZE, 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_size->size_value); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sis_cleanup(void) 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct aper_size_info_8 *previous_size; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds previous_size = A_SIZE_8(agp_bridge->previous_size); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_byte(agp_bridge->dev, SIS_APSIZE, 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (previous_size->size_value & ~(0x03))); 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sis_delayed_enable(struct agp_bridge_data *bridge, u32 mode) 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev *device = NULL; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 command; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rate; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO PFX "Found an AGP %d.%d compliant device at %s.\n", 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_bridge->major_version, 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_bridge->minor_version, 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_name(agp_bridge->dev)); 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_STATUS, &command); 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds command = agp_collect_device_status(bridge, mode, command); 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds command |= AGPSTAT_AGP_ENABLE; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rate = (command & 0x7) << 2; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for_each_pci_dev(device) { 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 agp = pci_find_capability(device, PCI_CAP_ID_AGP); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!agp) 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO PFX "Putting AGP V3 device at %s into %dx mode\n", 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_name(device), rate); 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command); 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Weird: on some sis chipsets any rate change in the target 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * command register triggers a 5ms screwup during which the master 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cannot be configured 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (device->device == bridge->dev->device) { 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO PFX "SiS delay workaround: giving bridge time to recover.\n"); 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msleep(10); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111e5524f355a0d272ba5233537a896a668db1f3008Dave Jonesstatic const struct aper_size_info_8 sis_generic_sizes[7] = 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {256, 65536, 6, 99}, 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {128, 32768, 5, 83}, 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {64, 16384, 4, 67}, 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {32, 8192, 3, 51}, 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {16, 4096, 2, 35}, 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {8, 2048, 1, 19}, 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {4, 1024, 0, 3} 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 122408b664a7d394a5e4315fbd14aca49b042cb2b08Adrian Bunkstatic struct agp_bridge_driver sis_driver = { 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 1246a92a4e0d201aea6d7c83f100d77310676b2e049Dave Jones .aperture_sizes = sis_generic_sizes, 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .size_type = U8_APER_SIZE, 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .num_aperture_sizes = 7, 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .configure = sis_configure, 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fetch_size = sis_fetch_size, 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .cleanup = sis_cleanup, 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .tlb_flush = sis_tlbflush, 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mask_memory = agp_generic_mask_memory, 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .masks = NULL, 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .agp_enable = agp_generic_enable, 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .cache_flush = global_cache_flush, 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .create_gatt_table = agp_generic_create_gatt_table, 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .free_gatt_table = agp_generic_free_gatt_table, 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .insert_memory = agp_generic_insert_memory, 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .remove_memory = agp_generic_remove_memory, 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .alloc_by_type = agp_generic_alloc_by_type, 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .free_by_type = agp_generic_free_by_type, 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .agp_alloc_page = agp_generic_alloc_page, 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .agp_destroy_page = agp_generic_destroy_page, 143bf1e5989aa5783726c6a94931f92b34aa387ec30Thomas Hellstrom .agp_type_to_mask_type = agp_generic_type_to_mask_type, 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct agp_device_ids sis_agp_device_ids[] __devinitdata = 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_5591_AGP, 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "5591", 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_530, 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "530", 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_540, 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "540", 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_550, 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "550", 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_620, 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "620", 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_630, 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "630", 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_635, 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "635", 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_645, 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "645", 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_646, 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "646", 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_648, 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "648", 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_650, 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "650", 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_651, 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "651", 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_655, 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "655", 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_661, 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "661", 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_730, 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "730", 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_735, 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "735", 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_740, 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "740", 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_741, 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "741", 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_745, 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "745", 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_746, 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "746", 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device_id = PCI_DEVICE_ID_SI_760, 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .chipset_name = "760", 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { }, /* dummy final entry, always present */ 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// chipsets that require the 'delay hack' 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sis_broken_chipsets[] __devinitdata = { 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PCI_DEVICE_ID_SI_648, 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PCI_DEVICE_ID_SI_746, 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0 // terminator 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __devinit sis_get_driver(struct agp_bridge_data *bridge) 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2476a92a4e0d201aea6d7c83f100d77310676b2e049Dave Jones for (i=0; sis_broken_chipsets[i]!=0; ++i) 2486a92a4e0d201aea6d7c83f100d77310676b2e049Dave Jones if (bridge->dev->device==sis_broken_chipsets[i]) 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2516a92a4e0d201aea6d7c83f100d77310676b2e049Dave Jones if (sis_broken_chipsets[i] || agp_sis_force_delay) 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sis_driver.agp_enable=sis_delayed_enable; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // sis chipsets that indicate less than agp3.5 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // are not actually fully agp3 compliant 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((agp_bridge->major_version == 3 && agp_bridge->minor_version >= 5 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && agp_sis_agp_spec!=0) || agp_sis_agp_spec==1) { 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sis_driver.aperture_sizes = agp3_generic_sizes; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sis_driver.size_type = U16_APER_SIZE; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sis_driver.num_aperture_sizes = AGP_GENERIC_SIZES_ENTRIES; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sis_driver.configure = agp3_generic_configure; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sis_driver.fetch_size = agp3_generic_fetch_size; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sis_driver.cleanup = agp3_generic_cleanup; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sis_driver.tlb_flush = agp3_generic_tlbflush; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __devinit agp_sis_probe(struct pci_dev *pdev, 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct pci_device_id *ent) 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_device_ids *devs = sis_agp_device_ids; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_bridge_data *bridge; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 cap_ptr; 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int j; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!cap_ptr) 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* probe for known chipsets */ 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (j = 0; devs[j].chipset_name; j++) { 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pdev->device == devs[j].device_id) { 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO PFX "Detected SiS %s chipset\n", 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devs[j].chipset_name); 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto found; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR PFX "Unsupported SiS chipset (device id: %04x)\n", 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdev->device); 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfound: 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bridge = agp_alloc_bridge(); 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!bridge) 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bridge->driver = &sis_driver; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bridge->dev = pdev; 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bridge->capndx = cap_ptr; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds get_agp_version(bridge); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Fill in the mode register */ 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_dword(pdev, bridge->capndx+PCI_AGP_STATUS, &bridge->mode); 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sis_get_driver(bridge); 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_set_drvdata(pdev, bridge); 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return agp_add_bridge(bridge); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __devexit agp_sis_remove(struct pci_dev *pdev) 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_bridge_data *bridge = pci_get_drvdata(pdev); 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_remove_bridge(bridge); 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_put_bridge(bridge); 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_device_id agp_sis_pci_table[] = { 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .class = (PCI_CLASS_BRIDGE_HOST << 8), 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .class_mask = ~0, 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .vendor = PCI_VENDOR_ID_SI, 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device = PCI_ANY_ID, 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .subvendor = PCI_ANY_ID, 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .subdevice = PCI_ANY_ID, 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { } 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, agp_sis_pci_table); 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver agp_sis_pci_driver = { 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "agpgart-sis", 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = agp_sis_pci_table, 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = agp_sis_probe, 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .remove = agp_sis_remove, 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init agp_sis_init(void) 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (agp_off) 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return pci_register_driver(&agp_sis_pci_driver); 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit agp_sis_cleanup(void) 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unregister_driver(&agp_sis_pci_driver); 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(agp_sis_init); 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(agp_sis_cleanup); 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(agp_sis_force_delay, bool, 0); 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(agp_sis_force_delay,"forces sis delay hack"); 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(agp_sis_agp_spec, int, 0); 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(agp_sis_agp_spec,"0=force sis init, 1=force generic agp3 init, default: autodetect"); 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL and additional rights"); 362