Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * SiS AGPGART routines.
0003  */
0004 
0005 #include <linux/module.h>
0006 #include <linux/pci.h>
0007 #include <linux/init.h>
0008 #include <linux/agp_backend.h>
0009 #include <linux/delay.h>
0010 #include "agp.h"
0011 
0012 #define SIS_ATTBASE 0x90
0013 #define SIS_APSIZE  0x94
0014 #define SIS_TLBCNTRL    0x97
0015 #define SIS_TLBFLUSH    0x98
0016 
0017 #define PCI_DEVICE_ID_SI_662    0x0662
0018 #define PCI_DEVICE_ID_SI_671    0x0671
0019 
0020 static bool agp_sis_force_delay = 0;
0021 static int agp_sis_agp_spec = -1;
0022 
0023 static int sis_fetch_size(void)
0024 {
0025     u8 temp_size;
0026     int i;
0027     struct aper_size_info_8 *values;
0028 
0029     pci_read_config_byte(agp_bridge->dev, SIS_APSIZE, &temp_size);
0030     values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
0031     for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
0032         if ((temp_size == values[i].size_value) ||
0033             ((temp_size & ~(0x07)) ==
0034              (values[i].size_value & ~(0x07)))) {
0035             agp_bridge->previous_size =
0036                 agp_bridge->current_size = (void *) (values + i);
0037 
0038             agp_bridge->aperture_size_idx = i;
0039             return values[i].size;
0040         }
0041     }
0042 
0043     return 0;
0044 }
0045 
0046 static void sis_tlbflush(struct agp_memory *mem)
0047 {
0048     pci_write_config_byte(agp_bridge->dev, SIS_TLBFLUSH, 0x02);
0049 }
0050 
0051 static int sis_configure(void)
0052 {
0053     struct aper_size_info_8 *current_size;
0054 
0055     current_size = A_SIZE_8(agp_bridge->current_size);
0056     pci_write_config_byte(agp_bridge->dev, SIS_TLBCNTRL, 0x05);
0057     agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
0058                             AGP_APERTURE_BAR);
0059     pci_write_config_dword(agp_bridge->dev, SIS_ATTBASE,
0060                    agp_bridge->gatt_bus_addr);
0061     pci_write_config_byte(agp_bridge->dev, SIS_APSIZE,
0062                   current_size->size_value);
0063     return 0;
0064 }
0065 
0066 static void sis_cleanup(void)
0067 {
0068     struct aper_size_info_8 *previous_size;
0069 
0070     previous_size = A_SIZE_8(agp_bridge->previous_size);
0071     pci_write_config_byte(agp_bridge->dev, SIS_APSIZE,
0072                   (previous_size->size_value & ~(0x03)));
0073 }
0074 
0075 static void sis_delayed_enable(struct agp_bridge_data *bridge, u32 mode)
0076 {
0077     struct pci_dev *device = NULL;
0078     u32 command;
0079     int rate;
0080 
0081     dev_info(&agp_bridge->dev->dev, "AGP %d.%d bridge\n",
0082          agp_bridge->major_version, agp_bridge->minor_version);
0083 
0084     pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_STATUS, &command);
0085     command = agp_collect_device_status(bridge, mode, command);
0086     command |= AGPSTAT_AGP_ENABLE;
0087     rate = (command & 0x7) << 2;
0088 
0089     for_each_pci_dev(device) {
0090         u8 agp = pci_find_capability(device, PCI_CAP_ID_AGP);
0091         if (!agp)
0092             continue;
0093 
0094         dev_info(&agp_bridge->dev->dev, "putting AGP V3 device at %s into %dx mode\n",
0095              pci_name(device), rate);
0096 
0097         pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command);
0098 
0099         /*
0100          * Weird: on some sis chipsets any rate change in the target
0101          * command register triggers a 5ms screwup during which the master
0102          * cannot be configured
0103          */
0104         if (device->device == bridge->dev->device) {
0105             dev_info(&agp_bridge->dev->dev, "SiS delay workaround: giving bridge time to recover\n");
0106             msleep(10);
0107         }
0108     }
0109 }
0110 
0111 static const struct aper_size_info_8 sis_generic_sizes[7] =
0112 {
0113     {256, 65536, 6, 99},
0114     {128, 32768, 5, 83},
0115     {64, 16384, 4, 67},
0116     {32, 8192, 3, 51},
0117     {16, 4096, 2, 35},
0118     {8, 2048, 1, 19},
0119     {4, 1024, 0, 3}
0120 };
0121 
0122 static struct agp_bridge_driver sis_driver = {
0123     .owner          = THIS_MODULE,
0124     .aperture_sizes     = sis_generic_sizes,
0125     .size_type      = U8_APER_SIZE,
0126     .num_aperture_sizes = 7,
0127     .needs_scratch_page = true,
0128     .configure      = sis_configure,
0129     .fetch_size     = sis_fetch_size,
0130     .cleanup        = sis_cleanup,
0131     .tlb_flush      = sis_tlbflush,
0132     .mask_memory        = agp_generic_mask_memory,
0133     .masks          = NULL,
0134     .agp_enable     = agp_generic_enable,
0135     .cache_flush        = global_cache_flush,
0136     .create_gatt_table  = agp_generic_create_gatt_table,
0137     .free_gatt_table    = agp_generic_free_gatt_table,
0138     .insert_memory      = agp_generic_insert_memory,
0139     .remove_memory      = agp_generic_remove_memory,
0140     .alloc_by_type      = agp_generic_alloc_by_type,
0141     .free_by_type       = agp_generic_free_by_type,
0142     .agp_alloc_page     = agp_generic_alloc_page,
0143     .agp_alloc_pages    = agp_generic_alloc_pages,
0144     .agp_destroy_page   = agp_generic_destroy_page,
0145     .agp_destroy_pages  = agp_generic_destroy_pages,
0146     .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
0147 };
0148 
0149 // chipsets that require the 'delay hack'
0150 static int sis_broken_chipsets[] = {
0151     PCI_DEVICE_ID_SI_648,
0152     PCI_DEVICE_ID_SI_746,
0153     0 // terminator
0154 };
0155 
0156 static void sis_get_driver(struct agp_bridge_data *bridge)
0157 {
0158     int i;
0159 
0160     for (i=0; sis_broken_chipsets[i]!=0; ++i)
0161         if (bridge->dev->device==sis_broken_chipsets[i])
0162             break;
0163 
0164     if (sis_broken_chipsets[i] || agp_sis_force_delay)
0165         sis_driver.agp_enable=sis_delayed_enable;
0166 
0167     // sis chipsets that indicate less than agp3.5
0168     // are not actually fully agp3 compliant
0169     if ((agp_bridge->major_version == 3 && agp_bridge->minor_version >= 5
0170          && agp_sis_agp_spec!=0) || agp_sis_agp_spec==1) {
0171         sis_driver.aperture_sizes = agp3_generic_sizes;
0172         sis_driver.size_type = U16_APER_SIZE;
0173         sis_driver.num_aperture_sizes = AGP_GENERIC_SIZES_ENTRIES;
0174         sis_driver.configure = agp3_generic_configure;
0175         sis_driver.fetch_size = agp3_generic_fetch_size;
0176         sis_driver.cleanup = agp3_generic_cleanup;
0177         sis_driver.tlb_flush = agp3_generic_tlbflush;
0178     }
0179 }
0180 
0181 
0182 static int agp_sis_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
0183 {
0184     struct agp_bridge_data *bridge;
0185     u8 cap_ptr;
0186 
0187     cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
0188     if (!cap_ptr)
0189         return -ENODEV;
0190 
0191 
0192     dev_info(&pdev->dev, "SiS chipset [%04x/%04x]\n",
0193          pdev->vendor, pdev->device);
0194     bridge = agp_alloc_bridge();
0195     if (!bridge)
0196         return -ENOMEM;
0197 
0198     bridge->driver = &sis_driver;
0199     bridge->dev = pdev;
0200     bridge->capndx = cap_ptr;
0201 
0202     get_agp_version(bridge);
0203 
0204     /* Fill in the mode register */
0205     pci_read_config_dword(pdev, bridge->capndx+PCI_AGP_STATUS, &bridge->mode);
0206     sis_get_driver(bridge);
0207 
0208     pci_set_drvdata(pdev, bridge);
0209     return agp_add_bridge(bridge);
0210 }
0211 
0212 static void agp_sis_remove(struct pci_dev *pdev)
0213 {
0214     struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
0215 
0216     agp_remove_bridge(bridge);
0217     agp_put_bridge(bridge);
0218 }
0219 
0220 #define agp_sis_suspend NULL
0221 
0222 static int __maybe_unused agp_sis_resume(
0223     __attribute__((unused)) struct device *dev)
0224 {
0225     return sis_driver.configure();
0226 }
0227 
0228 static const struct pci_device_id agp_sis_pci_table[] = {
0229     {
0230         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0231         .class_mask = ~0,
0232         .vendor     = PCI_VENDOR_ID_SI,
0233         .device     = PCI_DEVICE_ID_SI_5591,
0234         .subvendor  = PCI_ANY_ID,
0235         .subdevice  = PCI_ANY_ID,
0236     },
0237     {
0238         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0239         .class_mask = ~0,
0240         .vendor     = PCI_VENDOR_ID_SI,
0241         .device     = PCI_DEVICE_ID_SI_530,
0242         .subvendor  = PCI_ANY_ID,
0243         .subdevice  = PCI_ANY_ID,
0244     },
0245     {
0246         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0247         .class_mask = ~0,
0248         .vendor     = PCI_VENDOR_ID_SI,
0249         .device     = PCI_DEVICE_ID_SI_540,
0250         .subvendor  = PCI_ANY_ID,
0251         .subdevice  = PCI_ANY_ID,
0252     },
0253     {
0254         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0255         .class_mask = ~0,
0256         .vendor     = PCI_VENDOR_ID_SI,
0257         .device     = PCI_DEVICE_ID_SI_550,
0258         .subvendor  = PCI_ANY_ID,
0259         .subdevice  = PCI_ANY_ID,
0260     },
0261     {
0262         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0263         .class_mask = ~0,
0264         .vendor     = PCI_VENDOR_ID_SI,
0265         .device     = PCI_DEVICE_ID_SI_620,
0266         .subvendor  = PCI_ANY_ID,
0267         .subdevice  = PCI_ANY_ID,
0268     },
0269     {
0270         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0271         .class_mask = ~0,
0272         .vendor     = PCI_VENDOR_ID_SI,
0273         .device     = PCI_DEVICE_ID_SI_630,
0274         .subvendor  = PCI_ANY_ID,
0275         .subdevice  = PCI_ANY_ID,
0276     },
0277     {
0278         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0279         .class_mask = ~0,
0280         .vendor     = PCI_VENDOR_ID_SI,
0281         .device     = PCI_DEVICE_ID_SI_635,
0282         .subvendor  = PCI_ANY_ID,
0283         .subdevice  = PCI_ANY_ID,
0284     },
0285     {
0286         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0287         .class_mask = ~0,
0288         .vendor     = PCI_VENDOR_ID_SI,
0289         .device     = PCI_DEVICE_ID_SI_645,
0290         .subvendor  = PCI_ANY_ID,
0291         .subdevice  = PCI_ANY_ID,
0292     },
0293     {
0294         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0295         .class_mask = ~0,
0296         .vendor     = PCI_VENDOR_ID_SI,
0297         .device     = PCI_DEVICE_ID_SI_646,
0298         .subvendor  = PCI_ANY_ID,
0299         .subdevice  = PCI_ANY_ID,
0300     },
0301     {
0302         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0303         .class_mask = ~0,
0304         .vendor     = PCI_VENDOR_ID_SI,
0305         .device     = PCI_DEVICE_ID_SI_648,
0306         .subvendor  = PCI_ANY_ID,
0307         .subdevice  = PCI_ANY_ID,
0308     },
0309     {
0310         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0311         .class_mask = ~0,
0312         .vendor     = PCI_VENDOR_ID_SI,
0313         .device     = PCI_DEVICE_ID_SI_650,
0314         .subvendor  = PCI_ANY_ID,
0315         .subdevice  = PCI_ANY_ID,
0316     },
0317     {
0318         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0319         .class_mask = ~0,
0320         .vendor     = PCI_VENDOR_ID_SI,
0321         .device     = PCI_DEVICE_ID_SI_651,
0322         .subvendor  = PCI_ANY_ID,
0323         .subdevice  = PCI_ANY_ID,
0324     },
0325     {
0326         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0327         .class_mask = ~0,
0328         .vendor     = PCI_VENDOR_ID_SI,
0329         .device     = PCI_DEVICE_ID_SI_655,
0330         .subvendor  = PCI_ANY_ID,
0331         .subdevice  = PCI_ANY_ID,
0332     },
0333     {
0334         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0335         .class_mask = ~0,
0336         .vendor     = PCI_VENDOR_ID_SI,
0337         .device     = PCI_DEVICE_ID_SI_661,
0338         .subvendor  = PCI_ANY_ID,
0339         .subdevice  = PCI_ANY_ID,
0340     },
0341     {
0342         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0343         .class_mask = ~0,
0344         .vendor     = PCI_VENDOR_ID_SI,
0345         .device     = PCI_DEVICE_ID_SI_662,
0346         .subvendor  = PCI_ANY_ID,
0347         .subdevice  = PCI_ANY_ID,
0348     },
0349     {
0350         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0351         .class_mask = ~0,
0352         .vendor     = PCI_VENDOR_ID_SI,
0353         .device     = PCI_DEVICE_ID_SI_671,
0354         .subvendor  = PCI_ANY_ID,
0355         .subdevice  = PCI_ANY_ID,
0356     },
0357     {
0358         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0359         .class_mask = ~0,
0360         .vendor     = PCI_VENDOR_ID_SI,
0361         .device     = PCI_DEVICE_ID_SI_730,
0362         .subvendor  = PCI_ANY_ID,
0363         .subdevice  = PCI_ANY_ID,
0364     },
0365     {
0366         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0367         .class_mask = ~0,
0368         .vendor     = PCI_VENDOR_ID_SI,
0369         .device     = PCI_DEVICE_ID_SI_735,
0370         .subvendor  = PCI_ANY_ID,
0371         .subdevice  = PCI_ANY_ID,
0372     },
0373     {
0374         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0375         .class_mask = ~0,
0376         .vendor     = PCI_VENDOR_ID_SI,
0377         .device     = PCI_DEVICE_ID_SI_740,
0378         .subvendor  = PCI_ANY_ID,
0379         .subdevice  = PCI_ANY_ID,
0380     },
0381     {
0382         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0383         .class_mask = ~0,
0384         .vendor     = PCI_VENDOR_ID_SI,
0385         .device     = PCI_DEVICE_ID_SI_741,
0386         .subvendor  = PCI_ANY_ID,
0387         .subdevice  = PCI_ANY_ID,
0388     },
0389     {
0390         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0391         .class_mask = ~0,
0392         .vendor     = PCI_VENDOR_ID_SI,
0393         .device     = PCI_DEVICE_ID_SI_745,
0394         .subvendor  = PCI_ANY_ID,
0395         .subdevice  = PCI_ANY_ID,
0396     },
0397     {
0398         .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0399         .class_mask = ~0,
0400         .vendor     = PCI_VENDOR_ID_SI,
0401         .device     = PCI_DEVICE_ID_SI_746,
0402         .subvendor  = PCI_ANY_ID,
0403         .subdevice  = PCI_ANY_ID,
0404     },
0405     { }
0406 };
0407 
0408 MODULE_DEVICE_TABLE(pci, agp_sis_pci_table);
0409 
0410 static SIMPLE_DEV_PM_OPS(agp_sis_pm_ops, agp_sis_suspend, agp_sis_resume);
0411 
0412 static struct pci_driver agp_sis_pci_driver = {
0413     .name       = "agpgart-sis",
0414     .id_table   = agp_sis_pci_table,
0415     .probe      = agp_sis_probe,
0416     .remove     = agp_sis_remove,
0417     .driver.pm      = &agp_sis_pm_ops,
0418 };
0419 
0420 static int __init agp_sis_init(void)
0421 {
0422     if (agp_off)
0423         return -EINVAL;
0424     return pci_register_driver(&agp_sis_pci_driver);
0425 }
0426 
0427 static void __exit agp_sis_cleanup(void)
0428 {
0429     pci_unregister_driver(&agp_sis_pci_driver);
0430 }
0431 
0432 module_init(agp_sis_init);
0433 module_exit(agp_sis_cleanup);
0434 
0435 module_param(agp_sis_force_delay, bool, 0);
0436 MODULE_PARM_DESC(agp_sis_force_delay,"forces sis delay hack");
0437 module_param(agp_sis_agp_spec, int, 0);
0438 MODULE_PARM_DESC(agp_sis_agp_spec,"0=force sis init, 1=force generic agp3 init, default: autodetect");
0439 MODULE_LICENSE("GPL and additional rights");