1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * SiS AGPGART routines. 3*1da177e4SLinus Torvalds */ 4*1da177e4SLinus Torvalds 5*1da177e4SLinus Torvalds #include <linux/module.h> 6*1da177e4SLinus Torvalds #include <linux/pci.h> 7*1da177e4SLinus Torvalds #include <linux/init.h> 8*1da177e4SLinus Torvalds #include <linux/agp_backend.h> 9*1da177e4SLinus Torvalds #include <linux/delay.h> 10*1da177e4SLinus Torvalds #include "agp.h" 11*1da177e4SLinus Torvalds 12*1da177e4SLinus Torvalds #define SIS_ATTBASE 0x90 13*1da177e4SLinus Torvalds #define SIS_APSIZE 0x94 14*1da177e4SLinus Torvalds #define SIS_TLBCNTRL 0x97 15*1da177e4SLinus Torvalds #define SIS_TLBFLUSH 0x98 16*1da177e4SLinus Torvalds 17*1da177e4SLinus Torvalds static int __devinitdata agp_sis_force_delay = 0; 18*1da177e4SLinus Torvalds static int __devinitdata agp_sis_agp_spec = -1; 19*1da177e4SLinus Torvalds 20*1da177e4SLinus Torvalds static int sis_fetch_size(void) 21*1da177e4SLinus Torvalds { 22*1da177e4SLinus Torvalds u8 temp_size; 23*1da177e4SLinus Torvalds int i; 24*1da177e4SLinus Torvalds struct aper_size_info_8 *values; 25*1da177e4SLinus Torvalds 26*1da177e4SLinus Torvalds pci_read_config_byte(agp_bridge->dev, SIS_APSIZE, &temp_size); 27*1da177e4SLinus Torvalds values = A_SIZE_8(agp_bridge->driver->aperture_sizes); 28*1da177e4SLinus Torvalds for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { 29*1da177e4SLinus Torvalds if ((temp_size == values[i].size_value) || 30*1da177e4SLinus Torvalds ((temp_size & ~(0x03)) == 31*1da177e4SLinus Torvalds (values[i].size_value & ~(0x03)))) { 32*1da177e4SLinus Torvalds agp_bridge->previous_size = 33*1da177e4SLinus Torvalds agp_bridge->current_size = (void *) (values + i); 34*1da177e4SLinus Torvalds 35*1da177e4SLinus Torvalds agp_bridge->aperture_size_idx = i; 36*1da177e4SLinus Torvalds return values[i].size; 37*1da177e4SLinus Torvalds } 38*1da177e4SLinus Torvalds } 39*1da177e4SLinus Torvalds 40*1da177e4SLinus Torvalds return 0; 41*1da177e4SLinus Torvalds } 42*1da177e4SLinus Torvalds 43*1da177e4SLinus Torvalds static void sis_tlbflush(struct agp_memory *mem) 44*1da177e4SLinus Torvalds { 45*1da177e4SLinus Torvalds pci_write_config_byte(agp_bridge->dev, SIS_TLBFLUSH, 0x02); 46*1da177e4SLinus Torvalds } 47*1da177e4SLinus Torvalds 48*1da177e4SLinus Torvalds static int sis_configure(void) 49*1da177e4SLinus Torvalds { 50*1da177e4SLinus Torvalds u32 temp; 51*1da177e4SLinus Torvalds struct aper_size_info_8 *current_size; 52*1da177e4SLinus Torvalds 53*1da177e4SLinus Torvalds current_size = A_SIZE_8(agp_bridge->current_size); 54*1da177e4SLinus Torvalds pci_write_config_byte(agp_bridge->dev, SIS_TLBCNTRL, 0x05); 55*1da177e4SLinus Torvalds pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); 56*1da177e4SLinus Torvalds agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); 57*1da177e4SLinus Torvalds pci_write_config_dword(agp_bridge->dev, SIS_ATTBASE, 58*1da177e4SLinus Torvalds agp_bridge->gatt_bus_addr); 59*1da177e4SLinus Torvalds pci_write_config_byte(agp_bridge->dev, SIS_APSIZE, 60*1da177e4SLinus Torvalds current_size->size_value); 61*1da177e4SLinus Torvalds return 0; 62*1da177e4SLinus Torvalds } 63*1da177e4SLinus Torvalds 64*1da177e4SLinus Torvalds static void sis_cleanup(void) 65*1da177e4SLinus Torvalds { 66*1da177e4SLinus Torvalds struct aper_size_info_8 *previous_size; 67*1da177e4SLinus Torvalds 68*1da177e4SLinus Torvalds previous_size = A_SIZE_8(agp_bridge->previous_size); 69*1da177e4SLinus Torvalds pci_write_config_byte(agp_bridge->dev, SIS_APSIZE, 70*1da177e4SLinus Torvalds (previous_size->size_value & ~(0x03))); 71*1da177e4SLinus Torvalds } 72*1da177e4SLinus Torvalds 73*1da177e4SLinus Torvalds static void sis_delayed_enable(struct agp_bridge_data *bridge, u32 mode) 74*1da177e4SLinus Torvalds { 75*1da177e4SLinus Torvalds struct pci_dev *device = NULL; 76*1da177e4SLinus Torvalds u32 command; 77*1da177e4SLinus Torvalds int rate; 78*1da177e4SLinus Torvalds 79*1da177e4SLinus Torvalds printk(KERN_INFO PFX "Found an AGP %d.%d compliant device at %s.\n", 80*1da177e4SLinus Torvalds agp_bridge->major_version, 81*1da177e4SLinus Torvalds agp_bridge->minor_version, 82*1da177e4SLinus Torvalds pci_name(agp_bridge->dev)); 83*1da177e4SLinus Torvalds 84*1da177e4SLinus Torvalds pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_STATUS, &command); 85*1da177e4SLinus Torvalds command = agp_collect_device_status(bridge, mode, command); 86*1da177e4SLinus Torvalds command |= AGPSTAT_AGP_ENABLE; 87*1da177e4SLinus Torvalds rate = (command & 0x7) << 2; 88*1da177e4SLinus Torvalds 89*1da177e4SLinus Torvalds for_each_pci_dev(device) { 90*1da177e4SLinus Torvalds u8 agp = pci_find_capability(device, PCI_CAP_ID_AGP); 91*1da177e4SLinus Torvalds if (!agp) 92*1da177e4SLinus Torvalds continue; 93*1da177e4SLinus Torvalds 94*1da177e4SLinus Torvalds printk(KERN_INFO PFX "Putting AGP V3 device at %s into %dx mode\n", 95*1da177e4SLinus Torvalds pci_name(device), rate); 96*1da177e4SLinus Torvalds 97*1da177e4SLinus Torvalds pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command); 98*1da177e4SLinus Torvalds 99*1da177e4SLinus Torvalds /* 100*1da177e4SLinus Torvalds * Weird: on some sis chipsets any rate change in the target 101*1da177e4SLinus Torvalds * command register triggers a 5ms screwup during which the master 102*1da177e4SLinus Torvalds * cannot be configured 103*1da177e4SLinus Torvalds */ 104*1da177e4SLinus Torvalds if (device->device == bridge->dev->device) { 105*1da177e4SLinus Torvalds printk(KERN_INFO PFX "SiS delay workaround: giving bridge time to recover.\n"); 106*1da177e4SLinus Torvalds msleep(10); 107*1da177e4SLinus Torvalds } 108*1da177e4SLinus Torvalds } 109*1da177e4SLinus Torvalds } 110*1da177e4SLinus Torvalds 111*1da177e4SLinus Torvalds static struct aper_size_info_8 sis_generic_sizes[7] = 112*1da177e4SLinus Torvalds { 113*1da177e4SLinus Torvalds {256, 65536, 6, 99}, 114*1da177e4SLinus Torvalds {128, 32768, 5, 83}, 115*1da177e4SLinus Torvalds {64, 16384, 4, 67}, 116*1da177e4SLinus Torvalds {32, 8192, 3, 51}, 117*1da177e4SLinus Torvalds {16, 4096, 2, 35}, 118*1da177e4SLinus Torvalds {8, 2048, 1, 19}, 119*1da177e4SLinus Torvalds {4, 1024, 0, 3} 120*1da177e4SLinus Torvalds }; 121*1da177e4SLinus Torvalds 122*1da177e4SLinus Torvalds struct agp_bridge_driver sis_driver = { 123*1da177e4SLinus Torvalds .owner = THIS_MODULE, 124*1da177e4SLinus Torvalds .aperture_sizes = sis_generic_sizes, 125*1da177e4SLinus Torvalds .size_type = U8_APER_SIZE, 126*1da177e4SLinus Torvalds .num_aperture_sizes = 7, 127*1da177e4SLinus Torvalds .configure = sis_configure, 128*1da177e4SLinus Torvalds .fetch_size = sis_fetch_size, 129*1da177e4SLinus Torvalds .cleanup = sis_cleanup, 130*1da177e4SLinus Torvalds .tlb_flush = sis_tlbflush, 131*1da177e4SLinus Torvalds .mask_memory = agp_generic_mask_memory, 132*1da177e4SLinus Torvalds .masks = NULL, 133*1da177e4SLinus Torvalds .agp_enable = agp_generic_enable, 134*1da177e4SLinus Torvalds .cache_flush = global_cache_flush, 135*1da177e4SLinus Torvalds .create_gatt_table = agp_generic_create_gatt_table, 136*1da177e4SLinus Torvalds .free_gatt_table = agp_generic_free_gatt_table, 137*1da177e4SLinus Torvalds .insert_memory = agp_generic_insert_memory, 138*1da177e4SLinus Torvalds .remove_memory = agp_generic_remove_memory, 139*1da177e4SLinus Torvalds .alloc_by_type = agp_generic_alloc_by_type, 140*1da177e4SLinus Torvalds .free_by_type = agp_generic_free_by_type, 141*1da177e4SLinus Torvalds .agp_alloc_page = agp_generic_alloc_page, 142*1da177e4SLinus Torvalds .agp_destroy_page = agp_generic_destroy_page, 143*1da177e4SLinus Torvalds }; 144*1da177e4SLinus Torvalds 145*1da177e4SLinus Torvalds static struct agp_device_ids sis_agp_device_ids[] __devinitdata = 146*1da177e4SLinus Torvalds { 147*1da177e4SLinus Torvalds { 148*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_5591_AGP, 149*1da177e4SLinus Torvalds .chipset_name = "5591", 150*1da177e4SLinus Torvalds }, 151*1da177e4SLinus Torvalds { 152*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_530, 153*1da177e4SLinus Torvalds .chipset_name = "530", 154*1da177e4SLinus Torvalds }, 155*1da177e4SLinus Torvalds { 156*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_540, 157*1da177e4SLinus Torvalds .chipset_name = "540", 158*1da177e4SLinus Torvalds }, 159*1da177e4SLinus Torvalds { 160*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_550, 161*1da177e4SLinus Torvalds .chipset_name = "550", 162*1da177e4SLinus Torvalds }, 163*1da177e4SLinus Torvalds { 164*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_620, 165*1da177e4SLinus Torvalds .chipset_name = "620", 166*1da177e4SLinus Torvalds }, 167*1da177e4SLinus Torvalds { 168*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_630, 169*1da177e4SLinus Torvalds .chipset_name = "630", 170*1da177e4SLinus Torvalds }, 171*1da177e4SLinus Torvalds { 172*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_635, 173*1da177e4SLinus Torvalds .chipset_name = "635", 174*1da177e4SLinus Torvalds }, 175*1da177e4SLinus Torvalds { 176*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_645, 177*1da177e4SLinus Torvalds .chipset_name = "645", 178*1da177e4SLinus Torvalds }, 179*1da177e4SLinus Torvalds { 180*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_646, 181*1da177e4SLinus Torvalds .chipset_name = "646", 182*1da177e4SLinus Torvalds }, 183*1da177e4SLinus Torvalds { 184*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_648, 185*1da177e4SLinus Torvalds .chipset_name = "648", 186*1da177e4SLinus Torvalds }, 187*1da177e4SLinus Torvalds { 188*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_650, 189*1da177e4SLinus Torvalds .chipset_name = "650", 190*1da177e4SLinus Torvalds }, 191*1da177e4SLinus Torvalds { 192*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_651, 193*1da177e4SLinus Torvalds .chipset_name = "651", 194*1da177e4SLinus Torvalds }, 195*1da177e4SLinus Torvalds { 196*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_655, 197*1da177e4SLinus Torvalds .chipset_name = "655", 198*1da177e4SLinus Torvalds }, 199*1da177e4SLinus Torvalds { 200*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_661, 201*1da177e4SLinus Torvalds .chipset_name = "661", 202*1da177e4SLinus Torvalds }, 203*1da177e4SLinus Torvalds { 204*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_730, 205*1da177e4SLinus Torvalds .chipset_name = "730", 206*1da177e4SLinus Torvalds }, 207*1da177e4SLinus Torvalds { 208*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_735, 209*1da177e4SLinus Torvalds .chipset_name = "735", 210*1da177e4SLinus Torvalds }, 211*1da177e4SLinus Torvalds { 212*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_740, 213*1da177e4SLinus Torvalds .chipset_name = "740", 214*1da177e4SLinus Torvalds }, 215*1da177e4SLinus Torvalds { 216*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_741, 217*1da177e4SLinus Torvalds .chipset_name = "741", 218*1da177e4SLinus Torvalds }, 219*1da177e4SLinus Torvalds { 220*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_745, 221*1da177e4SLinus Torvalds .chipset_name = "745", 222*1da177e4SLinus Torvalds }, 223*1da177e4SLinus Torvalds { 224*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_746, 225*1da177e4SLinus Torvalds .chipset_name = "746", 226*1da177e4SLinus Torvalds }, 227*1da177e4SLinus Torvalds { 228*1da177e4SLinus Torvalds .device_id = PCI_DEVICE_ID_SI_760, 229*1da177e4SLinus Torvalds .chipset_name = "760", 230*1da177e4SLinus Torvalds }, 231*1da177e4SLinus Torvalds { }, /* dummy final entry, always present */ 232*1da177e4SLinus Torvalds }; 233*1da177e4SLinus Torvalds 234*1da177e4SLinus Torvalds 235*1da177e4SLinus Torvalds // chipsets that require the 'delay hack' 236*1da177e4SLinus Torvalds static int sis_broken_chipsets[] __devinitdata = { 237*1da177e4SLinus Torvalds PCI_DEVICE_ID_SI_648, 238*1da177e4SLinus Torvalds PCI_DEVICE_ID_SI_746, 239*1da177e4SLinus Torvalds 0 // terminator 240*1da177e4SLinus Torvalds }; 241*1da177e4SLinus Torvalds 242*1da177e4SLinus Torvalds static void __devinit sis_get_driver(struct agp_bridge_data *bridge) 243*1da177e4SLinus Torvalds { 244*1da177e4SLinus Torvalds int i; 245*1da177e4SLinus Torvalds 246*1da177e4SLinus Torvalds for(i=0; sis_broken_chipsets[i]!=0; ++i) 247*1da177e4SLinus Torvalds if(bridge->dev->device==sis_broken_chipsets[i]) 248*1da177e4SLinus Torvalds break; 249*1da177e4SLinus Torvalds 250*1da177e4SLinus Torvalds if(sis_broken_chipsets[i] || agp_sis_force_delay) 251*1da177e4SLinus Torvalds sis_driver.agp_enable=sis_delayed_enable; 252*1da177e4SLinus Torvalds 253*1da177e4SLinus Torvalds // sis chipsets that indicate less than agp3.5 254*1da177e4SLinus Torvalds // are not actually fully agp3 compliant 255*1da177e4SLinus Torvalds if ((agp_bridge->major_version == 3 && agp_bridge->minor_version >= 5 256*1da177e4SLinus Torvalds && agp_sis_agp_spec!=0) || agp_sis_agp_spec==1) { 257*1da177e4SLinus Torvalds sis_driver.aperture_sizes = agp3_generic_sizes; 258*1da177e4SLinus Torvalds sis_driver.size_type = U16_APER_SIZE; 259*1da177e4SLinus Torvalds sis_driver.num_aperture_sizes = AGP_GENERIC_SIZES_ENTRIES; 260*1da177e4SLinus Torvalds sis_driver.configure = agp3_generic_configure; 261*1da177e4SLinus Torvalds sis_driver.fetch_size = agp3_generic_fetch_size; 262*1da177e4SLinus Torvalds sis_driver.cleanup = agp3_generic_cleanup; 263*1da177e4SLinus Torvalds sis_driver.tlb_flush = agp3_generic_tlbflush; 264*1da177e4SLinus Torvalds } 265*1da177e4SLinus Torvalds } 266*1da177e4SLinus Torvalds 267*1da177e4SLinus Torvalds 268*1da177e4SLinus Torvalds static int __devinit agp_sis_probe(struct pci_dev *pdev, 269*1da177e4SLinus Torvalds const struct pci_device_id *ent) 270*1da177e4SLinus Torvalds { 271*1da177e4SLinus Torvalds struct agp_device_ids *devs = sis_agp_device_ids; 272*1da177e4SLinus Torvalds struct agp_bridge_data *bridge; 273*1da177e4SLinus Torvalds u8 cap_ptr; 274*1da177e4SLinus Torvalds int j; 275*1da177e4SLinus Torvalds 276*1da177e4SLinus Torvalds cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); 277*1da177e4SLinus Torvalds if (!cap_ptr) 278*1da177e4SLinus Torvalds return -ENODEV; 279*1da177e4SLinus Torvalds 280*1da177e4SLinus Torvalds /* probe for known chipsets */ 281*1da177e4SLinus Torvalds for (j = 0; devs[j].chipset_name; j++) { 282*1da177e4SLinus Torvalds if (pdev->device == devs[j].device_id) { 283*1da177e4SLinus Torvalds printk(KERN_INFO PFX "Detected SiS %s chipset\n", 284*1da177e4SLinus Torvalds devs[j].chipset_name); 285*1da177e4SLinus Torvalds goto found; 286*1da177e4SLinus Torvalds } 287*1da177e4SLinus Torvalds } 288*1da177e4SLinus Torvalds 289*1da177e4SLinus Torvalds printk(KERN_ERR PFX "Unsupported SiS chipset (device id: %04x)\n", 290*1da177e4SLinus Torvalds pdev->device); 291*1da177e4SLinus Torvalds return -ENODEV; 292*1da177e4SLinus Torvalds 293*1da177e4SLinus Torvalds found: 294*1da177e4SLinus Torvalds bridge = agp_alloc_bridge(); 295*1da177e4SLinus Torvalds if (!bridge) 296*1da177e4SLinus Torvalds return -ENOMEM; 297*1da177e4SLinus Torvalds 298*1da177e4SLinus Torvalds bridge->driver = &sis_driver; 299*1da177e4SLinus Torvalds bridge->dev = pdev; 300*1da177e4SLinus Torvalds bridge->capndx = cap_ptr; 301*1da177e4SLinus Torvalds 302*1da177e4SLinus Torvalds get_agp_version(bridge); 303*1da177e4SLinus Torvalds 304*1da177e4SLinus Torvalds /* Fill in the mode register */ 305*1da177e4SLinus Torvalds pci_read_config_dword(pdev, bridge->capndx+PCI_AGP_STATUS, &bridge->mode); 306*1da177e4SLinus Torvalds sis_get_driver(bridge); 307*1da177e4SLinus Torvalds 308*1da177e4SLinus Torvalds pci_set_drvdata(pdev, bridge); 309*1da177e4SLinus Torvalds return agp_add_bridge(bridge); 310*1da177e4SLinus Torvalds } 311*1da177e4SLinus Torvalds 312*1da177e4SLinus Torvalds static void __devexit agp_sis_remove(struct pci_dev *pdev) 313*1da177e4SLinus Torvalds { 314*1da177e4SLinus Torvalds struct agp_bridge_data *bridge = pci_get_drvdata(pdev); 315*1da177e4SLinus Torvalds 316*1da177e4SLinus Torvalds agp_remove_bridge(bridge); 317*1da177e4SLinus Torvalds agp_put_bridge(bridge); 318*1da177e4SLinus Torvalds } 319*1da177e4SLinus Torvalds 320*1da177e4SLinus Torvalds static struct pci_device_id agp_sis_pci_table[] = { 321*1da177e4SLinus Torvalds { 322*1da177e4SLinus Torvalds .class = (PCI_CLASS_BRIDGE_HOST << 8), 323*1da177e4SLinus Torvalds .class_mask = ~0, 324*1da177e4SLinus Torvalds .vendor = PCI_VENDOR_ID_SI, 325*1da177e4SLinus Torvalds .device = PCI_ANY_ID, 326*1da177e4SLinus Torvalds .subvendor = PCI_ANY_ID, 327*1da177e4SLinus Torvalds .subdevice = PCI_ANY_ID, 328*1da177e4SLinus Torvalds }, 329*1da177e4SLinus Torvalds { } 330*1da177e4SLinus Torvalds }; 331*1da177e4SLinus Torvalds 332*1da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, agp_sis_pci_table); 333*1da177e4SLinus Torvalds 334*1da177e4SLinus Torvalds static struct pci_driver agp_sis_pci_driver = { 335*1da177e4SLinus Torvalds .name = "agpgart-sis", 336*1da177e4SLinus Torvalds .id_table = agp_sis_pci_table, 337*1da177e4SLinus Torvalds .probe = agp_sis_probe, 338*1da177e4SLinus Torvalds .remove = agp_sis_remove, 339*1da177e4SLinus Torvalds }; 340*1da177e4SLinus Torvalds 341*1da177e4SLinus Torvalds static int __init agp_sis_init(void) 342*1da177e4SLinus Torvalds { 343*1da177e4SLinus Torvalds if (agp_off) 344*1da177e4SLinus Torvalds return -EINVAL; 345*1da177e4SLinus Torvalds return pci_register_driver(&agp_sis_pci_driver); 346*1da177e4SLinus Torvalds } 347*1da177e4SLinus Torvalds 348*1da177e4SLinus Torvalds static void __exit agp_sis_cleanup(void) 349*1da177e4SLinus Torvalds { 350*1da177e4SLinus Torvalds pci_unregister_driver(&agp_sis_pci_driver); 351*1da177e4SLinus Torvalds } 352*1da177e4SLinus Torvalds 353*1da177e4SLinus Torvalds module_init(agp_sis_init); 354*1da177e4SLinus Torvalds module_exit(agp_sis_cleanup); 355*1da177e4SLinus Torvalds 356*1da177e4SLinus Torvalds module_param(agp_sis_force_delay, bool, 0); 357*1da177e4SLinus Torvalds MODULE_PARM_DESC(agp_sis_force_delay,"forces sis delay hack"); 358*1da177e4SLinus Torvalds module_param(agp_sis_agp_spec, int, 0); 359*1da177e4SLinus Torvalds MODULE_PARM_DESC(agp_sis_agp_spec,"0=force sis init, 1=force generic agp3 init, default: autodetect"); 360*1da177e4SLinus Torvalds MODULE_LICENSE("GPL and additional rights"); 361