2005-04-17 02:20:36 +04:00
/*
* ATi AGPGART routines .
*/
# include <linux/types.h>
# include <linux/module.h>
# include <linux/pci.h>
# include <linux/init.h>
2005-10-31 02:03:48 +03:00
# include <linux/string.h>
# include <linux/slab.h>
2005-04-17 02:20:36 +04:00
# include <linux/agp_backend.h>
# include <asm/agp.h>
# include "agp.h"
# define ATI_GART_MMBASE_ADDR 0x14
# define ATI_RS100_APSIZE 0xac
# define ATI_RS100_IG_AGPMODE 0xb0
# define ATI_RS300_APSIZE 0xf8
# define ATI_RS300_IG_AGPMODE 0xfc
# define ATI_GART_FEATURE_ID 0x00
# define ATI_GART_BASE 0x04
# define ATI_GART_CACHE_SZBASE 0x08
# define ATI_GART_CACHE_CNTRL 0x0c
# define ATI_GART_CACHE_ENTRY_CNTRL 0x10
2007-02-23 02:41:28 +03:00
static const struct aper_size_info_lvl2 ati_generic_sizes [ 7 ] =
2005-04-17 02:20:36 +04:00
{
{ 2048 , 524288 , 0x0000000c } ,
{ 1024 , 262144 , 0x0000000a } ,
{ 512 , 131072 , 0x00000008 } ,
{ 256 , 65536 , 0x00000006 } ,
{ 128 , 32768 , 0x00000004 } ,
{ 64 , 16384 , 0x00000002 } ,
{ 32 , 8192 , 0x00000000 }
} ;
static struct gatt_mask ati_generic_masks [ ] =
{
{ . mask = 1 , . type = 0 }
} ;
2007-01-29 01:41:37 +03:00
struct ati_page_map {
2005-04-17 02:20:36 +04:00
unsigned long * real ;
unsigned long __iomem * remapped ;
2007-01-29 01:41:37 +03:00
} ;
2005-04-17 02:20:36 +04:00
static struct _ati_generic_private {
volatile u8 __iomem * registers ;
2007-01-29 01:41:37 +03:00
struct ati_page_map * * gatt_pages ;
2005-04-17 02:20:36 +04:00
int num_tables ;
} ati_generic_private ;
2007-01-29 01:41:37 +03:00
static int ati_create_page_map ( struct ati_page_map * page_map )
2005-04-17 02:20:36 +04:00
{
int i , err = 0 ;
page_map - > real = ( unsigned long * ) __get_free_page ( GFP_KERNEL ) ;
if ( page_map - > real = = NULL )
return - ENOMEM ;
2008-02-20 03:37:08 +03:00
set_memory_uc ( ( unsigned long ) page_map - > real , 1 ) ;
2005-04-17 02:20:36 +04:00
err = map_page_into_agp ( virt_to_page ( page_map - > real ) ) ;
2008-02-06 07:16:00 +03:00
page_map - > remapped = page_map - > real ;
2005-04-17 02:20:36 +04:00
2006-02-28 08:54:25 +03:00
for ( i = 0 ; i < PAGE_SIZE / sizeof ( unsigned long ) ; i + + ) {
2005-04-17 02:20:36 +04:00
writel ( agp_bridge - > scratch_page , page_map - > remapped + i ) ;
readl ( page_map - > remapped + i ) ; /* PCI Posting. */
}
return 0 ;
}
2007-01-29 01:41:37 +03:00
static void ati_free_page_map ( struct ati_page_map * page_map )
2005-04-17 02:20:36 +04:00
{
unmap_page_from_agp ( virt_to_page ( page_map - > real ) ) ;
2008-02-20 03:37:08 +03:00
set_memory_wb ( ( unsigned long ) page_map - > real , 1 ) ;
2005-04-17 02:20:36 +04:00
free_page ( ( unsigned long ) page_map - > real ) ;
}
static void ati_free_gatt_pages ( void )
{
int i ;
2007-01-29 01:41:37 +03:00
struct ati_page_map * * tables ;
struct ati_page_map * entry ;
2005-04-17 02:20:36 +04:00
tables = ati_generic_private . gatt_pages ;
2006-02-28 08:54:25 +03:00
for ( i = 0 ; i < ati_generic_private . num_tables ; i + + ) {
2005-04-17 02:20:36 +04:00
entry = tables [ i ] ;
if ( entry ! = NULL ) {
if ( entry - > real ! = NULL )
ati_free_page_map ( entry ) ;
kfree ( entry ) ;
}
}
kfree ( tables ) ;
}
static int ati_create_gatt_pages ( int nr_tables )
{
2007-01-29 01:41:37 +03:00
struct ati_page_map * * tables ;
struct ati_page_map * entry ;
2005-04-17 02:20:36 +04:00
int retval = 0 ;
int i ;
2007-01-29 01:41:37 +03:00
tables = kzalloc ( ( nr_tables + 1 ) * sizeof ( struct ati_page_map * ) , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( tables = = NULL )
return - ENOMEM ;
for ( i = 0 ; i < nr_tables ; i + + ) {
2007-01-29 01:41:37 +03:00
entry = kzalloc ( sizeof ( struct ati_page_map ) , GFP_KERNEL ) ;
2007-07-21 19:39:11 +04:00
tables [ i ] = entry ;
2005-04-17 02:20:36 +04:00
if ( entry = = NULL ) {
retval = - ENOMEM ;
break ;
}
retval = ati_create_page_map ( entry ) ;
2007-01-29 01:50:17 +03:00
if ( retval ! = 0 )
break ;
2005-04-17 02:20:36 +04:00
}
2007-07-21 19:39:11 +04:00
ati_generic_private . num_tables = i ;
2005-04-17 02:20:36 +04:00
ati_generic_private . gatt_pages = tables ;
2006-06-20 08:39:19 +04:00
if ( retval ! = 0 )
ati_free_gatt_pages ( ) ;
2005-04-17 02:20:36 +04:00
return retval ;
}
static int is_r200 ( void )
{
if ( ( agp_bridge - > dev - > device = = PCI_DEVICE_ID_ATI_RS100 ) | |
( agp_bridge - > dev - > device = = PCI_DEVICE_ID_ATI_RS200 ) | |
( agp_bridge - > dev - > device = = PCI_DEVICE_ID_ATI_RS200_B ) | |
( agp_bridge - > dev - > device = = PCI_DEVICE_ID_ATI_RS250 ) )
return 1 ;
return 0 ;
}
static int ati_fetch_size ( void )
{
int i ;
u32 temp ;
struct aper_size_info_lvl2 * values ;
if ( is_r200 ( ) )
pci_read_config_dword ( agp_bridge - > dev , ATI_RS100_APSIZE , & temp ) ;
else
pci_read_config_dword ( agp_bridge - > dev , ATI_RS300_APSIZE , & temp ) ;
temp = ( temp & 0x0000000e ) ;
values = A_SIZE_LVL2 ( agp_bridge - > driver - > aperture_sizes ) ;
for ( i = 0 ; i < agp_bridge - > driver - > num_aperture_sizes ; i + + ) {
if ( temp = = values [ i ] . size_value ) {
agp_bridge - > previous_size =
agp_bridge - > current_size = ( void * ) ( values + i ) ;
agp_bridge - > aperture_size_idx = i ;
return values [ i ] . size ;
}
}
return 0 ;
}
static void ati_tlbflush ( struct agp_memory * mem )
{
writel ( 1 , ati_generic_private . registers + ATI_GART_CACHE_CNTRL ) ;
readl ( ati_generic_private . registers + ATI_GART_CACHE_CNTRL ) ; /* PCI Posting. */
}
static void ati_cleanup ( void )
{
struct aper_size_info_lvl2 * previous_size ;
u32 temp ;
previous_size = A_SIZE_LVL2 ( agp_bridge - > previous_size ) ;
/* Write back the previous size and disable gart translation */
if ( is_r200 ( ) ) {
pci_read_config_dword ( agp_bridge - > dev , ATI_RS100_APSIZE , & temp ) ;
temp = ( ( temp & ~ ( 0x0000000f ) ) | previous_size - > size_value ) ;
pci_write_config_dword ( agp_bridge - > dev , ATI_RS100_APSIZE , temp ) ;
} else {
pci_read_config_dword ( agp_bridge - > dev , ATI_RS300_APSIZE , & temp ) ;
temp = ( ( temp & ~ ( 0x0000000f ) ) | previous_size - > size_value ) ;
pci_write_config_dword ( agp_bridge - > dev , ATI_RS300_APSIZE , temp ) ;
}
iounmap ( ( volatile u8 __iomem * ) ati_generic_private . registers ) ;
}
static int ati_configure ( void )
{
u32 temp ;
/* Get the memory mapped registers */
pci_read_config_dword ( agp_bridge - > dev , ATI_GART_MMBASE_ADDR , & temp ) ;
temp = ( temp & 0xfffff000 ) ;
ati_generic_private . registers = ( volatile u8 __iomem * ) ioremap ( temp , 4096 ) ;
2007-08-25 12:14:00 +04:00
if ( ! ati_generic_private . registers )
return - ENOMEM ;
2005-04-17 02:20:36 +04:00
if ( is_r200 ( ) )
2006-06-20 08:39:19 +04:00
pci_write_config_dword ( agp_bridge - > dev , ATI_RS100_IG_AGPMODE , 0x20000 ) ;
2005-04-17 02:20:36 +04:00
else
pci_write_config_dword ( agp_bridge - > dev , ATI_RS300_IG_AGPMODE , 0x20000 ) ;
/* address to map too */
2006-06-20 08:39:19 +04:00
/*
2005-04-17 02:20:36 +04:00
pci_read_config_dword ( agp_bridge . dev , AGP_APBASE , & temp ) ;
agp_bridge . gart_bus_addr = ( temp & PCI_BASE_ADDRESS_MEM_MASK ) ;
printk ( KERN_INFO PFX " IGP320 gart_bus_addr: %x \n " , agp_bridge . gart_bus_addr ) ;
2006-06-20 08:39:19 +04:00
*/
2005-04-17 02:20:36 +04:00
writel ( 0x60000 , ati_generic_private . registers + ATI_GART_FEATURE_ID ) ;
readl ( ati_generic_private . registers + ATI_GART_FEATURE_ID ) ; /* PCI Posting.*/
/* SIGNALED_SYSTEM_ERROR @ NB_STATUS */
pci_read_config_dword ( agp_bridge - > dev , 4 , & temp ) ;
pci_write_config_dword ( agp_bridge - > dev , 4 , temp | ( 1 < < 14 ) ) ;
/* Write out the address of the gatt table */
writel ( agp_bridge - > gatt_bus_addr , ati_generic_private . registers + ATI_GART_BASE ) ;
readl ( ati_generic_private . registers + ATI_GART_BASE ) ; /* PCI Posting. */
return 0 ;
}
2006-01-04 10:00:59 +03:00
# ifdef CONFIG_PM
2006-06-20 08:42:04 +04:00
static int agp_ati_suspend ( struct pci_dev * dev , pm_message_t state )
2006-01-04 10:00:59 +03:00
{
2006-06-20 08:42:04 +04:00
pci_save_state ( dev ) ;
2013-06-27 16:52:36 +04:00
pci_set_power_state ( dev , PCI_D3hot ) ;
2006-01-04 10:00:59 +03:00
2006-06-20 08:42:04 +04:00
return 0 ;
2006-01-04 10:00:59 +03:00
}
2006-06-20 08:42:04 +04:00
static int agp_ati_resume ( struct pci_dev * dev )
2006-01-04 10:00:59 +03:00
{
2013-06-27 16:52:36 +04:00
pci_set_power_state ( dev , PCI_D0 ) ;
2006-06-20 08:42:04 +04:00
pci_restore_state ( dev ) ;
2006-01-04 10:00:59 +03:00
2006-06-20 08:42:04 +04:00
return ati_configure ( ) ;
2006-01-04 10:00:59 +03:00
}
# endif
2005-04-17 02:20:36 +04:00
/*
2006-06-26 20:35:02 +04:00
* Since we don ' t need contiguous memory we just try
2005-04-17 02:20:36 +04:00
* to get the gatt table once
*/
# 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)
# undef GET_GATT
# define GET_GATT(addr) (ati_generic_private.gatt_pages[\
GET_PAGE_DIR_IDX ( addr ) ] - > remapped )
static int ati_insert_memory ( struct agp_memory * mem ,
off_t pg_start , int type )
{
int i , j , num_entries ;
unsigned long __iomem * cur_gatt ;
unsigned long addr ;
2009-06-19 04:52:57 +04:00
int mask_type ;
2005-04-17 02:20:36 +04:00
num_entries = A_SIZE_LVL2 ( agp_bridge - > current_size ) - > num_entries ;
2009-06-19 04:52:57 +04:00
mask_type = agp_generic_type_to_mask_type ( mem - > bridge , type ) ;
if ( mask_type ! = 0 | | type ! = mem - > type )
2005-04-17 02:20:36 +04:00
return - EINVAL ;
2009-06-19 04:52:57 +04:00
if ( mem - > page_count = = 0 )
return 0 ;
2005-04-17 02:20:36 +04:00
if ( ( pg_start + mem - > page_count ) > num_entries )
return - EINVAL ;
j = pg_start ;
while ( j < ( pg_start + mem - > page_count ) ) {
addr = ( j * PAGE_SIZE ) + agp_bridge - > gart_bus_addr ;
cur_gatt = GET_GATT ( addr ) ;
if ( ! PGE_EMPTY ( agp_bridge , readl ( cur_gatt + GET_GATT_OFF ( addr ) ) ) )
return - EBUSY ;
j + + ;
}
2008-03-27 00:10:02 +03:00
if ( ! mem - > is_flushed ) {
2005-04-17 02:20:36 +04:00
/*CACHE_FLUSH(); */
global_cache_flush ( ) ;
2008-03-27 00:10:02 +03:00
mem - > is_flushed = true ;
2005-04-17 02:20:36 +04:00
}
for ( i = 0 , j = pg_start ; i < mem - > page_count ; i + + , j + + ) {
addr = ( j * PAGE_SIZE ) + agp_bridge - > gart_bus_addr ;
cur_gatt = GET_GATT ( addr ) ;
2009-06-12 08:11:41 +04:00
writel ( agp_bridge - > driver - > mask_memory ( agp_bridge ,
2009-07-29 13:25:58 +04:00
page_to_phys ( mem - > pages [ i ] ) ,
2009-07-27 13:27:29 +04:00
mem - > type ) ,
2009-06-12 08:11:41 +04:00
cur_gatt + GET_GATT_OFF ( addr ) ) ;
2005-04-17 02:20:36 +04:00
}
2009-06-19 04:52:57 +04:00
readl ( GET_GATT ( agp_bridge - > gart_bus_addr ) ) ; /* PCI posting */
2005-04-17 02:20:36 +04:00
agp_bridge - > driver - > tlb_flush ( mem ) ;
return 0 ;
}
static int ati_remove_memory ( struct agp_memory * mem , off_t pg_start ,
int type )
{
int i ;
unsigned long __iomem * cur_gatt ;
unsigned long addr ;
2009-06-19 04:52:57 +04:00
int mask_type ;
2005-04-17 02:20:36 +04:00
2009-06-19 04:52:57 +04:00
mask_type = agp_generic_type_to_mask_type ( mem - > bridge , type ) ;
if ( mask_type ! = 0 | | type ! = mem - > type )
2005-04-17 02:20:36 +04:00
return - EINVAL ;
2006-06-20 08:39:19 +04:00
2009-06-19 04:52:57 +04:00
if ( mem - > page_count = = 0 )
return 0 ;
2005-04-17 02:20:36 +04:00
for ( i = pg_start ; i < ( mem - > page_count + pg_start ) ; i + + ) {
addr = ( i * PAGE_SIZE ) + agp_bridge - > gart_bus_addr ;
cur_gatt = GET_GATT ( addr ) ;
writel ( agp_bridge - > scratch_page , cur_gatt + GET_GATT_OFF ( addr ) ) ;
}
2009-06-19 04:52:57 +04:00
readl ( GET_GATT ( agp_bridge - > gart_bus_addr ) ) ; /* PCI posting */
2005-04-17 02:20:36 +04:00
agp_bridge - > driver - > tlb_flush ( mem ) ;
return 0 ;
}
static int ati_create_gatt_table ( struct agp_bridge_data * bridge )
{
struct aper_size_info_lvl2 * value ;
2007-01-29 01:41:37 +03:00
struct ati_page_map page_dir ;
2010-04-20 19:43:34 +04:00
unsigned long __iomem * cur_gatt ;
2005-04-17 02:20:36 +04:00
unsigned long addr ;
int retval ;
u32 temp ;
int i ;
struct aper_size_info_lvl2 * current_size ;
value = A_SIZE_LVL2 ( agp_bridge - > current_size ) ;
retval = ati_create_page_map ( & page_dir ) ;
if ( retval ! = 0 )
return retval ;
retval = ati_create_gatt_pages ( value - > num_entries / 1024 ) ;
if ( retval ! = 0 ) {
ati_free_page_map ( & page_dir ) ;
return retval ;
}
agp_bridge - > gatt_table_real = ( u32 * ) page_dir . real ;
agp_bridge - > gatt_table = ( u32 __iomem * ) page_dir . remapped ;
2009-07-29 13:25:58 +04:00
agp_bridge - > gatt_bus_addr = virt_to_phys ( page_dir . real ) ;
2005-04-17 02:20:36 +04:00
/* Write out the size register */
current_size = A_SIZE_LVL2 ( agp_bridge - > current_size ) ;
if ( is_r200 ( ) ) {
pci_read_config_dword ( agp_bridge - > dev , ATI_RS100_APSIZE , & temp ) ;
temp = ( ( ( temp & ~ ( 0x0000000e ) ) | current_size - > size_value )
| 0x00000001 ) ;
pci_write_config_dword ( agp_bridge - > dev , ATI_RS100_APSIZE , temp ) ;
pci_read_config_dword ( agp_bridge - > dev , ATI_RS100_APSIZE , & temp ) ;
} else {
pci_read_config_dword ( agp_bridge - > dev , ATI_RS300_APSIZE , & temp ) ;
temp = ( ( ( temp & ~ ( 0x0000000e ) ) | current_size - > size_value )
| 0x00000001 ) ;
pci_write_config_dword ( agp_bridge - > dev , ATI_RS300_APSIZE , temp ) ;
pci_read_config_dword ( agp_bridge - > dev , ATI_RS300_APSIZE , & temp ) ;
}
/*
* Get the address for the gart region .
* This is a bus address even on the alpha , b / c its
* used to program the agp master not the cpu
*/
pci_read_config_dword ( agp_bridge - > dev , AGP_APBASE , & temp ) ;
addr = ( temp & PCI_BASE_ADDRESS_MEM_MASK ) ;
agp_bridge - > gart_bus_addr = addr ;
/* Calculate the agp offset */
2006-02-28 08:54:25 +03:00
for ( i = 0 ; i < value - > num_entries / 1024 ; i + + , addr + = 0x00400000 ) {
2009-07-29 13:25:58 +04:00
writel ( virt_to_phys ( ati_generic_private . gatt_pages [ i ] - > real ) | 1 ,
2005-04-17 02:20:36 +04:00
page_dir . remapped + GET_PAGE_DIR_OFF ( addr ) ) ;
readl ( page_dir . remapped + GET_PAGE_DIR_OFF ( addr ) ) ; /* PCI Posting. */
}
2010-04-20 19:43:34 +04:00
for ( i = 0 ; i < value - > num_entries ; i + + ) {
addr = ( i * PAGE_SIZE ) + agp_bridge - > gart_bus_addr ;
cur_gatt = GET_GATT ( addr ) ;
writel ( agp_bridge - > scratch_page , cur_gatt + GET_GATT_OFF ( addr ) ) ;
}
2005-04-17 02:20:36 +04:00
return 0 ;
}
static int ati_free_gatt_table ( struct agp_bridge_data * bridge )
{
2007-01-29 01:41:37 +03:00
struct ati_page_map page_dir ;
2005-04-17 02:20:36 +04:00
page_dir . real = ( unsigned long * ) agp_bridge - > gatt_table_real ;
page_dir . remapped = ( unsigned long __iomem * ) agp_bridge - > gatt_table ;
ati_free_gatt_pages ( ) ;
ati_free_page_map ( & page_dir ) ;
return 0 ;
}
2007-02-23 02:41:28 +03:00
static const struct agp_bridge_driver ati_generic_bridge = {
2005-04-17 02:20:36 +04:00
. owner = THIS_MODULE ,
. aperture_sizes = ati_generic_sizes ,
. size_type = LVL2_APER_SIZE ,
. num_aperture_sizes = 7 ,
2010-04-20 19:43:34 +04:00
. needs_scratch_page = true ,
2005-04-17 02:20:36 +04:00
. configure = ati_configure ,
. fetch_size = ati_fetch_size ,
. cleanup = ati_cleanup ,
. tlb_flush = ati_tlbflush ,
. mask_memory = agp_generic_mask_memory ,
. masks = ati_generic_masks ,
. agp_enable = agp_generic_enable ,
. cache_flush = global_cache_flush ,
. create_gatt_table = ati_create_gatt_table ,
. free_gatt_table = ati_free_gatt_table ,
. insert_memory = ati_insert_memory ,
. remove_memory = ati_remove_memory ,
. alloc_by_type = agp_generic_alloc_by_type ,
. free_by_type = agp_generic_free_by_type ,
. agp_alloc_page = agp_generic_alloc_page ,
2008-08-21 21:15:46 +04:00
. agp_alloc_pages = agp_generic_alloc_pages ,
2005-04-17 02:20:36 +04:00
. agp_destroy_page = agp_generic_destroy_page ,
2008-08-21 21:15:46 +04:00
. agp_destroy_pages = agp_generic_destroy_pages ,
2007-01-23 12:33:43 +03:00
. agp_type_to_mask_type = agp_generic_type_to_mask_type ,
2005-04-17 02:20:36 +04:00
} ;
2012-11-19 22:24:36 +04:00
static struct agp_device_ids ati_agp_device_ids [ ] =
2005-04-17 02:20:36 +04:00
{
{
. device_id = PCI_DEVICE_ID_ATI_RS100 ,
. chipset_name = " IGP320/M " ,
} ,
{
. device_id = PCI_DEVICE_ID_ATI_RS200 ,
. chipset_name = " IGP330/340/345/350/M " ,
} ,
{
. device_id = PCI_DEVICE_ID_ATI_RS200_B ,
. chipset_name = " IGP345M " ,
} ,
{
. device_id = PCI_DEVICE_ID_ATI_RS250 ,
. chipset_name = " IGP7000/M " ,
} ,
{
. device_id = PCI_DEVICE_ID_ATI_RS300_100 ,
. chipset_name = " IGP9100/M " ,
} ,
{
. device_id = PCI_DEVICE_ID_ATI_RS300_133 ,
. chipset_name = " IGP9100/M " ,
} ,
{
. device_id = PCI_DEVICE_ID_ATI_RS300_166 ,
. chipset_name = " IGP9100/M " ,
} ,
{
. device_id = PCI_DEVICE_ID_ATI_RS300_200 ,
. chipset_name = " IGP9100/M " ,
} ,
2008-06-13 02:21:26 +04:00
{
. device_id = PCI_DEVICE_ID_ATI_RS350_133 ,
. chipset_name = " IGP9000/M " ,
} ,
2006-03-01 22:23:14 +03:00
{
. device_id = PCI_DEVICE_ID_ATI_RS350_200 ,
. chipset_name = " IGP9100/M " ,
} ,
2005-04-17 02:20:36 +04:00
{ } , /* dummy final entry, always present */
} ;
2012-12-22 03:12:08 +04:00
static int agp_ati_probe ( struct pci_dev * pdev , const struct pci_device_id * ent )
2005-04-17 02:20:36 +04:00
{
struct agp_device_ids * devs = ati_agp_device_ids ;
struct agp_bridge_data * bridge ;
u8 cap_ptr ;
int j ;
cap_ptr = pci_find_capability ( pdev , PCI_CAP_ID_AGP ) ;
if ( ! cap_ptr )
return - ENODEV ;
/* probe for known chipsets */
for ( j = 0 ; devs [ j ] . chipset_name ; j + + ) {
if ( pdev - > device = = devs [ j ] . device_id )
goto found ;
}
2008-07-30 23:26:51 +04:00
dev_err ( & pdev - > dev , " unsupported Ati chipset [%04x/%04x]) \n " ,
pdev - > vendor , pdev - > device ) ;
2005-04-17 02:20:36 +04:00
return - ENODEV ;
found :
bridge = agp_alloc_bridge ( ) ;
if ( ! bridge )
return - ENOMEM ;
bridge - > dev = pdev ;
bridge - > capndx = cap_ptr ;
2006-06-20 08:39:19 +04:00
bridge - > driver = & ati_generic_bridge ;
2005-04-17 02:20:36 +04:00
2008-07-30 23:26:51 +04:00
dev_info ( & pdev - > dev , " Ati %s chipset \n " , devs [ j ] . chipset_name ) ;
2005-04-17 02:20:36 +04:00
/* Fill in the mode register */
pci_read_config_dword ( pdev ,
bridge - > capndx + PCI_AGP_STATUS ,
& bridge - > mode ) ;
pci_set_drvdata ( pdev , bridge ) ;
return agp_add_bridge ( bridge ) ;
}
2012-11-19 22:26:26 +04:00
static void agp_ati_remove ( struct pci_dev * pdev )
2005-04-17 02:20:36 +04:00
{
struct agp_bridge_data * bridge = pci_get_drvdata ( pdev ) ;
agp_remove_bridge ( bridge ) ;
agp_put_bridge ( bridge ) ;
}
static struct pci_device_id agp_ati_pci_table [ ] = {
{
. class = ( PCI_CLASS_BRIDGE_HOST < < 8 ) ,
. class_mask = ~ 0 ,
. vendor = PCI_VENDOR_ID_ATI ,
. device = PCI_ANY_ID ,
. subvendor = PCI_ANY_ID ,
. subdevice = PCI_ANY_ID ,
} ,
{ }
} ;
MODULE_DEVICE_TABLE ( pci , agp_ati_pci_table ) ;
static struct pci_driver agp_ati_pci_driver = {
. name = " agpgart-ati " ,
. id_table = agp_ati_pci_table ,
. probe = agp_ati_probe ,
. remove = agp_ati_remove ,
2006-01-04 10:00:59 +03:00
# ifdef CONFIG_PM
. suspend = agp_ati_suspend ,
2006-06-20 08:42:04 +04:00
. resume = agp_ati_resume ,
2006-01-04 10:00:59 +03:00
# endif
2005-04-17 02:20:36 +04:00
} ;
static int __init agp_ati_init ( void )
{
if ( agp_off )
return - EINVAL ;
return pci_register_driver ( & agp_ati_pci_driver ) ;
}
static void __exit agp_ati_cleanup ( void )
{
pci_unregister_driver ( & agp_ati_pci_driver ) ;
}
module_init ( agp_ati_init ) ;
module_exit ( agp_ati_cleanup ) ;
2008-10-20 21:31:45 +04:00
MODULE_AUTHOR ( " Dave Jones <davej@redhat.com> " ) ;
2005-04-17 02:20:36 +04:00
MODULE_LICENSE ( " GPL and additional rights " ) ;