# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.639 -> 1.640 # include/linux/agpgart.h 1.1 -> 1.2 # drivers/char/agp/agpgart_fe.c 1.12 -> 1.13 # drivers/char/agp/agpgart_be.c 1.34 -> 1.35 # include/linux/agp_backend.h 1.12 -> 1.13 # drivers/char/agp/Makefile 1.4 -> 1.5 # drivers/char/agp/agp.h 1.18 -> 1.19 # (new) -> 1.1 drivers/char/agp/agpgart_be-sis.c # (new) -> 1.1 drivers/char/agp/Config.help # (new) -> 1.1 drivers/char/agp/agpgart_be-sworks.c # (new) -> 1.1 drivers/char/agp/agpgart_be-i8x0.c # (new) -> 1.1 drivers/char/agp/agpgart_be-i810.c # (new) -> 1.1 drivers/char/agp/agpgart_be-amd.c # (new) -> 1.1 drivers/char/agp/agpgart_be-i460.c # (new) -> 1.1 drivers/char/agp/agpgart_be-ali.c # (new) -> 1.1 drivers/char/agp/agpgart_be-hp.c # (new) -> 1.1 drivers/char/agp/agpgart_be-via.c # (new) -> 1.1 drivers/char/agp/Config.in # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/07/15 greg@kroah.com 1.640 # agpgart: Split agpgart code into separate files. # # The majority of this work was done by Dave Jones, I merely converted the # driver to the "new" pci api. # -------------------------------------------- # diff -Nru a/drivers/char/agp/Config.help b/drivers/char/agp/Config.help --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/agp/Config.help Mon Jul 15 12:01:54 2002 @@ -0,0 +1,88 @@ +CONFIG_AGP + AGP (Accelerated Graphics Port) is a bus system mainly used to + connect graphics cards to the rest of the system. + + If you have an AGP system and you say Y here, it will be possible to + use the AGP features of your 3D rendering video card. This code acts + as a sort of "AGP driver" for the motherboard's chipset. + + If you need more texture memory than you can get with the AGP GART + (theoretically up to 256 MB, but in practice usually 64 or 128 MB + due to kernel allocation issues), you could use PCI accesses + and have up to a couple gigs of texture space. + + Note that this is the only means to have XFree4/GLX use + write-combining with MTRR support on the AGP bus. Without it, OpenGL + direct rendering will be a lot slower but still faster than PIO. + + You should say Y here if you use XFree86 3.3.6 or 4.x and want to + use GLX or DRI. If unsure, say N. + + This driver is available as a module. If you want to compile it as + a module, say M here and read . The + module will be called agpgart.o. + +CONFIG_AGP_INTEL + This option gives you AGP support for the GLX component of the + XFree86 4.x on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850 and 860 chipsets. + + You should say Y here if you use XFree86 3.3.6 or 4.x and want to + use GLX or DRI. If unsure, say N. + +CONFIG_AGP_I810 + This option gives you AGP support for the Xserver on the Intel 810 + 815 and 830m chipset boards for their on-board integrated graphics. This + is required to do any useful video modes with these boards. + +CONFIG_AGP_I460 + This option gives you AGP GART support for the Intel 460GX chipset + for IA64 processors. + +CONFIG_AGP_VIA + This option gives you AGP support for the GLX component of the + XFree86 4.x on VIA MPV3/Apollo Pro chipsets. + + You should say Y here if you use XFree86 3.3.6 or 4.x and want to + use GLX or DRI. If unsure, say N. + +CONFIG_AGP_AMD + This option gives you AGP support for the GLX component of the + XFree86 4.x on AMD Irongate, 761, and 762 chipsets. + + You should say Y here if you use XFree86 3.3.6 or 4.x and want to + use GLX or DRI. If unsure, say N. + +CONFIG_AGP_SIS + This option gives you AGP support for the GLX component of the "soon + to be released" XFree86 4.x on Silicon Integrated Systems [SiS] + chipsets. + + Note that 5591/5592 AGP chipsets are NOT supported. + + You should say Y here if you use XFree86 3.3.6 or 4.x and want to + use GLX or DRI. If unsure, say N. + +CONFIG_AGP_SWORKS + Say Y here to support the Serverworks AGP card. See + for product descriptions and images. + +CONFIG_AGP_ALI + This option gives you AGP support for the GLX component of the + XFree86 4.x on the following ALi chipsets. The supported chipsets + include M1541, M1621, M1631, M1632, M1641,M1647,and M1651. + For the ALi-chipset question, ALi suggests you refer to + . + + The M1541 chipset can do AGP 1x and 2x, but note that there is an + acknowledged incompatibility with Matrox G200 cards. Due to + timing issues, this chipset cannot do AGP 2x with the G200. + This is a hardware limitation. AGP 1x seems to be fine, though. + + You should say Y here if you use XFree86 3.3.6 or 4.x and want to + use GLX or DRI. If unsure, say N. + +CONFIG_AGP_HP_ZX1 + This option gives you AGP GART support for the HP ZX1 chipset + for IA64 processors. + + diff -Nru a/drivers/char/agp/Config.in b/drivers/char/agp/Config.in --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/agp/Config.in Mon Jul 15 12:01:54 2002 @@ -0,0 +1,14 @@ +dep_tristate '/dev/agpgart (AGP Support)' CONFIG_AGP $CONFIG_DRM_AGP +if [ "$CONFIG_AGP" != "n" ]; then + bool ' Intel 440LX/BX/GX and I815/I820/I830M/I830MP/I840/I845/I850/I860 support' CONFIG_AGP_INTEL + bool ' Intel I810/I815/I830M (on-board) support' CONFIG_AGP_I810 + bool ' VIA chipset support' CONFIG_AGP_VIA + bool ' AMD Irongate, 761, and 762 support' CONFIG_AGP_AMD + bool ' Generic SiS support' CONFIG_AGP_SIS + bool ' ALI chipset support' CONFIG_AGP_ALI + bool ' Serverworks LE/HE support' CONFIG_AGP_SWORKS + if [ "$CONFIG_IA64" = "y" ]; then + bool ' Intel 460GX support' CONFIG_AGP_I460 + bool ' HP ZX1 AGP support' CONFIG_AGP_HP_ZX1 + fi +fi diff -Nru a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile --- a/drivers/char/agp/Makefile Mon Jul 15 12:01:54 2002 +++ b/drivers/char/agp/Makefile Mon Jul 15 12:01:54 2002 @@ -5,7 +5,18 @@ export-objs := agpgart_be.o -agpgart-objs := agpgart_fe.o agpgart_be.o +agpgart-y := agpgart_fe.o agpgart_be.o + +agpgart-$(CONFIG_AGP_INTEL) += agpgart_be-i8x0.o +agpgart-$(CONFIG_AGP_I810) += agpgart_be-i810.o +agpgart-$(CONFIG_AGP_VIA) += agpgart_be-via.o +agpgart-$(CONFIG_AGP_AMD) += agpgart_be-amd.o +agpgart-$(CONFIG_AGP_SIS) += agpgart_be-sis.o +agpgart-$(CONFIG_AGP_ALI) += agpgart_be-ali.o +agpgart-$(CONFIG_AGP_SWORKS) += agpgart_be-sworks.o +agpgart-$(CONFIG_AGP_I460) += agpgart_be-i460.o +agpgart-$(CONFIG_AGP_HP_ZX1) += agpgart_be-hp.o +agpgart-objs := $(agpgart-y) obj-$(CONFIG_AGP) += agpgart.o diff -Nru a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h --- a/drivers/char/agp/agp.h Mon Jul 15 12:01:54 2002 +++ b/drivers/char/agp/agp.h Mon Jul 15 12:01:54 2002 @@ -27,6 +27,67 @@ #ifndef _AGP_BACKEND_PRIV_H #define _AGP_BACKEND_PRIV_H 1 +#include /* for flush_agp_cache() */ + +extern struct agp_bridge_data agp_bridge; + +/* Generic routines. */ +void agp_generic_agp_enable(u32 mode); +int agp_generic_create_gatt_table(void); +int agp_generic_free_gatt_table(void); +agp_memory *agp_create_memory(int scratch_pages); +int agp_generic_insert_memory(agp_memory * mem, off_t pg_start, int type); +int agp_generic_remove_memory(agp_memory * mem, off_t pg_start, int type); +agp_memory *agp_generic_alloc_by_type(size_t page_count, int type); +void agp_generic_free_by_type(agp_memory * curr); +void *agp_generic_alloc_page(void); +void agp_generic_destroy_page(void *addr); +int agp_generic_suspend(void); +void agp_generic_resume(void); +void agp_free_key(int key); + +/* chipset specific init routines. */ +int __init ali_generic_setup (struct pci_dev *pdev); +int __init amd_irongate_setup (struct pci_dev *pdev); +int __init hp_zx1_setup (struct pci_dev *pdev); +int __init intel_i460_setup (struct pci_dev *pdev); +int __init intel_generic_setup (struct pci_dev *pdev); +int __init intel_i810_setup(struct pci_dev *i810_dev); +int __init intel_815_setup(struct pci_dev *pdev); +int __init intel_i830_setup(struct pci_dev *i830_dev); +int __init intel_820_setup (struct pci_dev *pdev); +int __init intel_830mp_setup (struct pci_dev *pdev); +int __init intel_840_setup (struct pci_dev *pdev); +int __init intel_845_setup (struct pci_dev *pdev); +int __init intel_850_setup (struct pci_dev *pdev); +int __init intel_860_setup (struct pci_dev *pdev); +int __init serverworks_setup (struct pci_dev *pdev); +int __init sis_generic_setup (struct pci_dev *pdev); +int __init via_generic_setup (struct pci_dev *pdev); + +#define AGPGART_MODULE_NAME "agpgart" +#define PFX AGPGART_MODULE_NAME ": " + + +#ifdef CONFIG_SMP +static void ipi_handler(void *null) +{ + flush_agp_cache(); +} + +static void __attribute__((unused)) global_cache_flush(void) +{ + if (smp_call_function(ipi_handler, NULL, 1, 1) != 0) + panic(PFX "timed out waiting for the other CPUs!\n"); + flush_agp_cache(); +} +#else +static void global_cache_flush(void) +{ + flush_agp_cache(); +} +#endif /* !CONFIG_SMP */ + enum aper_size_type { U8_APER_SIZE, U16_APER_SIZE, @@ -35,55 +96,55 @@ FIXED_APER_SIZE }; -typedef struct _gatt_mask { +struct gatt_mask { unsigned long mask; u32 type; /* totally device specific, for integrated chipsets that * might have different types of memory masks. For other * devices this will probably be ignored */ -} gatt_mask; +}; -typedef struct _aper_size_info_8 { +struct aper_size_info_8 { int size; int num_entries; int page_order; u8 size_value; -} aper_size_info_8; +}; -typedef struct _aper_size_info_16 { +struct aper_size_info_16 { int size; int num_entries; int page_order; u16 size_value; -} aper_size_info_16; +}; -typedef struct _aper_size_info_32 { +struct aper_size_info_32 { int size; int num_entries; int page_order; u32 size_value; -} aper_size_info_32; +}; -typedef struct _aper_size_info_lvl2 { +struct aper_size_info_lvl2 { int size; int num_entries; u32 size_value; -} aper_size_info_lvl2; +}; -typedef struct _aper_size_info_fixed { +struct aper_size_info_fixed { int size; int num_entries; int page_order; -} aper_size_info_fixed; +}; struct agp_bridge_data { - agp_version *version; + struct agp_version *version; void *aperture_sizes; void *previous_size; void *current_size; void *dev_private_data; struct pci_dev *dev; - gatt_mask *masks; + struct gatt_mask *masks; unsigned long *gatt_table; unsigned long *gatt_table_real; unsigned long scratch_page; @@ -125,26 +186,26 @@ }; -#define OUTREG64(mmap, addr, val) __raw_writeq((val), (mmap)+(addr)) -#define OUTREG32(mmap, addr, val) __raw_writel((val), (mmap)+(addr)) -#define OUTREG16(mmap, addr, val) __raw_writew((val), (mmap)+(addr)) -#define OUTREG8(mmap, addr, val) __raw_writeb((val), (mmap)+(addr)) - -#define INREG64(mmap, addr) __raw_readq((mmap)+(addr)) -#define INREG32(mmap, addr) __raw_readl((mmap)+(addr)) -#define INREG16(mmap, addr) __raw_readw((mmap)+(addr)) -#define INREG8(mmap, addr) __raw_readb((mmap)+(addr)) - -#define KB(x) ((x) * 1024) -#define MB(x) (KB (KB (x))) -#define GB(x) (MB (KB (x))) +#define OUTREG64(mmap, addr, val) __raw_writeq((val), (mmap)+(addr)) +#define OUTREG32(mmap, addr, val) __raw_writel((val), (mmap)+(addr)) +#define OUTREG16(mmap, addr, val) __raw_writew((val), (mmap)+(addr)) +#define OUTREG8(mmap, addr, val) __raw_writeb((val), (mmap)+(addr)) + +#define INREG64(mmap, addr) __raw_readq((mmap)+(addr)) +#define INREG32(mmap, addr) __raw_readl((mmap)+(addr)) +#define INREG16(mmap, addr) __raw_readw((mmap)+(addr)) +#define INREG8(mmap, addr) __raw_readb((mmap)+(addr)) + +#define KB(x) ((x) * 1024) +#define MB(x) (KB (KB (x))) +#define GB(x) (MB (KB (x))) #define CACHE_FLUSH agp_bridge.cache_flush -#define A_SIZE_8(x) ((aper_size_info_8 *) x) -#define A_SIZE_16(x) ((aper_size_info_16 *) x) -#define A_SIZE_32(x) ((aper_size_info_32 *) x) -#define A_SIZE_LVL2(x) ((aper_size_info_lvl2 *) x) -#define A_SIZE_FIX(x) ((aper_size_info_fixed *) x) +#define A_SIZE_8(x) ((struct aper_size_info_8 *) x) +#define A_SIZE_16(x) ((struct aper_size_info_16 *) x) +#define A_SIZE_32(x) ((struct aper_size_info_32 *) x) +#define A_SIZE_LVL2(x) ((struct aper_size_info_lvl2 *) x) +#define A_SIZE_FIX(x) ((struct aper_size_info_fixed *) x) #define A_IDX8() (A_SIZE_8(agp_bridge.aperture_sizes) + i) #define A_IDX16() (A_SIZE_16(agp_bridge.aperture_sizes) + i) #define A_IDX32() (A_SIZE_32(agp_bridge.aperture_sizes) + i) @@ -152,91 +213,88 @@ #define A_IDXFIX() (A_SIZE_FIX(agp_bridge.aperture_sizes) + i) #define MAXKEY (4096 * 32) -#define AGPGART_MODULE_NAME "agpgart" -#define PFX AGPGART_MODULE_NAME ": " - -#define PGE_EMPTY(p) (!(p) || (p) == (unsigned long) agp_bridge.scratch_page) +#define PGE_EMPTY(p) (!(p) || (p) == (unsigned long) agp_bridge.scratch_page) #ifndef PCI_DEVICE_ID_VIA_82C691_0 -#define PCI_DEVICE_ID_VIA_82C691_0 0x0691 +#define PCI_DEVICE_ID_VIA_82C691_0 0x0691 #endif #ifndef PCI_DEVICE_ID_VIA_8371_0 -#define PCI_DEVICE_ID_VIA_8371_0 0x0391 +#define PCI_DEVICE_ID_VIA_8371_0 0x0391 #endif #ifndef PCI_DEVICE_ID_VIA_8363_0 -#define PCI_DEVICE_ID_VIA_8363_0 0x0305 +#define PCI_DEVICE_ID_VIA_8363_0 0x0305 #endif #ifndef PCI_DEVICE_ID_VIA_82C694X_0 -#define PCI_DEVICE_ID_VIA_82C694X_0 0x0605 +#define PCI_DEVICE_ID_VIA_82C694X_0 0x0605 #endif #ifndef PCI_DEVICE_ID_INTEL_810_0 -#define PCI_DEVICE_ID_INTEL_810_0 0x7120 +#define PCI_DEVICE_ID_INTEL_810_0 0x7120 #endif #ifndef PCI_DEVICE_ID_INTEL_845_G_0 #define PCI_DEVICE_ID_INTEL_845_G_0 0x2560 #endif #ifndef PCI_DEVICE_ID_INTEL_845_G_1 -#define PCI_DEVICE_ID_INTEL_845_G_1 0x2562 +#define PCI_DEVICE_ID_INTEL_845_G_1 0x2562 #endif #ifndef PCI_DEVICE_ID_INTEL_830_M_0 #define PCI_DEVICE_ID_INTEL_830_M_0 0x3575 #endif #ifndef PCI_DEVICE_ID_INTEL_830_M_1 -#define PCI_DEVICE_ID_INTEL_830_M_1 0x3577 +#define PCI_DEVICE_ID_INTEL_830_M_1 0x3577 #endif #ifndef PCI_DEVICE_ID_INTEL_820_0 -#define PCI_DEVICE_ID_INTEL_820_0 0x2500 +#define PCI_DEVICE_ID_INTEL_820_0 0x2500 #endif #ifndef PCI_DEVICE_ID_INTEL_820_UP_0 -#define PCI_DEVICE_ID_INTEL_820_UP_0 0x2501 +#define PCI_DEVICE_ID_INTEL_820_UP_0 0x2501 #endif #ifndef PCI_DEVICE_ID_INTEL_840_0 -#define PCI_DEVICE_ID_INTEL_840_0 0x1a21 +#define PCI_DEVICE_ID_INTEL_840_0 0x1a21 #endif #ifndef PCI_DEVICE_ID_INTEL_845_0 -#define PCI_DEVICE_ID_INTEL_845_0 0x1a30 +#define PCI_DEVICE_ID_INTEL_845_0 0x1a30 #endif #ifndef PCI_DEVICE_ID_INTEL_850_0 -#define PCI_DEVICE_ID_INTEL_850_0 0x2530 +#define PCI_DEVICE_ID_INTEL_850_0 0x2530 #endif #ifndef PCI_DEVICE_ID_INTEL_860_0 -#define PCI_DEVICE_ID_INTEL_860_0 0x2531 +#define PCI_DEVICE_ID_INTEL_860_0 0x2531 #endif #ifndef PCI_DEVICE_ID_INTEL_810_DC100_0 -#define PCI_DEVICE_ID_INTEL_810_DC100_0 0x7122 +#define PCI_DEVICE_ID_INTEL_810_DC100_0 0x7122 #endif #ifndef PCI_DEVICE_ID_INTEL_810_E_0 -#define PCI_DEVICE_ID_INTEL_810_E_0 0x7124 +#define PCI_DEVICE_ID_INTEL_810_E_0 0x7124 #endif #ifndef PCI_DEVICE_ID_INTEL_82443GX_0 -#define PCI_DEVICE_ID_INTEL_82443GX_0 0x71a0 +#define PCI_DEVICE_ID_INTEL_82443GX_0 0x71a0 #endif #ifndef PCI_DEVICE_ID_INTEL_810_1 -#define PCI_DEVICE_ID_INTEL_810_1 0x7121 +#define PCI_DEVICE_ID_INTEL_810_1 0x7121 #endif #ifndef PCI_DEVICE_ID_INTEL_810_DC100_1 -#define PCI_DEVICE_ID_INTEL_810_DC100_1 0x7123 +#define PCI_DEVICE_ID_INTEL_810_DC100_1 0x7123 #endif #ifndef PCI_DEVICE_ID_INTEL_810_E_1 -#define PCI_DEVICE_ID_INTEL_810_E_1 0x7125 +#define PCI_DEVICE_ID_INTEL_810_E_1 0x7125 #endif #ifndef PCI_DEVICE_ID_INTEL_815_0 -#define PCI_DEVICE_ID_INTEL_815_0 0x1130 +#define PCI_DEVICE_ID_INTEL_815_0 0x1130 #endif #ifndef PCI_DEVICE_ID_INTEL_815_1 -#define PCI_DEVICE_ID_INTEL_815_1 0x1132 +#define PCI_DEVICE_ID_INTEL_815_1 0x1132 #endif #ifndef PCI_DEVICE_ID_INTEL_82443GX_1 -#define PCI_DEVICE_ID_INTEL_82443GX_1 0x71a1 +#define PCI_DEVICE_ID_INTEL_82443GX_1 0x71a1 #endif #ifndef PCI_DEVICE_ID_INTEL_460GX -#define PCI_DEVICE_ID_INTEL_460GX 0x84ea +#define PCI_DEVICE_ID_INTEL_460GX 0x84ea #endif #ifndef PCI_DEVICE_ID_AMD_IRONGATE_0 -#define PCI_DEVICE_ID_AMD_IRONGATE_0 0x7006 +#define PCI_DEVICE_ID_AMD_IRONGATE_0 0x7006 #endif #ifndef PCI_DEVICE_ID_AMD_761_0 -#define PCI_DEVICE_ID_AMD_761_0 0x700e +#define PCI_DEVICE_ID_AMD_761_0 0x700e #endif #ifndef PCI_DEVICE_ID_AMD_762_0 #define PCI_DEVICE_ID_AMD_762_0 0x700C @@ -270,12 +328,12 @@ #endif /* intel register */ -#define INTEL_APBASE 0x10 -#define INTEL_APSIZE 0xb4 -#define INTEL_ATTBASE 0xb8 -#define INTEL_AGPCTRL 0xb0 -#define INTEL_NBXCFG 0x50 -#define INTEL_ERRSTS 0x91 +#define INTEL_APBASE 0x10 +#define INTEL_APSIZE 0xb4 +#define INTEL_ATTBASE 0xb8 +#define INTEL_AGPCTRL 0xb0 +#define INTEL_NBXCFG 0x50 +#define INTEL_ERRSTS 0x91 /* Intel 460GX Registers */ #define INTEL_I460_APBASE 0x10 @@ -287,116 +345,120 @@ #define INTEL_I460_GATT_COHERENT (1UL << 25) /* intel i830 registers */ -#define I830_GMCH_CTRL 0x52 -#define I830_GMCH_ENABLED 0x4 -#define I830_GMCH_MEM_MASK 0x1 -#define I830_GMCH_MEM_64M 0x1 -#define I830_GMCH_MEM_128M 0 -#define I830_GMCH_GMS_MASK 0x70 -#define I830_GMCH_GMS_DISABLED 0x00 -#define I830_GMCH_GMS_LOCAL 0x10 -#define I830_GMCH_GMS_STOLEN_512 0x20 -#define I830_GMCH_GMS_STOLEN_1024 0x30 -#define I830_GMCH_GMS_STOLEN_8192 0x40 -#define I830_RDRAM_CHANNEL_TYPE 0x03010 -#define I830_RDRAM_ND(x) (((x) & 0x20) >> 5) -#define I830_RDRAM_DDT(x) (((x) & 0x18) >> 3) +#define I830_GMCH_CTRL 0x52 +#define I830_GMCH_ENABLED 0x4 +#define I830_GMCH_MEM_MASK 0x1 +#define I830_GMCH_MEM_64M 0x1 +#define I830_GMCH_MEM_128M 0 +#define I830_GMCH_GMS_MASK 0x70 +#define I830_GMCH_GMS_DISABLED 0x00 +#define I830_GMCH_GMS_LOCAL 0x10 +#define I830_GMCH_GMS_STOLEN_512 0x20 +#define I830_GMCH_GMS_STOLEN_1024 0x30 +#define I830_GMCH_GMS_STOLEN_8192 0x40 +#define I830_RDRAM_CHANNEL_TYPE 0x03010 +#define I830_RDRAM_ND(x) (((x) & 0x20) >> 5) +#define I830_RDRAM_DDT(x) (((x) & 0x18) >> 3) /* This one is for I830MP w. an external graphic card */ -#define INTEL_I830_ERRSTS 0x92 +#define INTEL_I830_ERRSTS 0x92 + +/* intel 815 register */ +#define INTEL_815_APCONT 0x51 +#define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF /* intel i820 registers */ -#define INTEL_I820_RDCR 0x51 -#define INTEL_I820_ERRSTS 0xc8 +#define INTEL_I820_RDCR 0x51 +#define INTEL_I820_ERRSTS 0xc8 /* intel i840 registers */ -#define INTEL_I840_MCHCFG 0x50 -#define INTEL_I840_ERRSTS 0xc8 +#define INTEL_I840_MCHCFG 0x50 +#define INTEL_I840_ERRSTS 0xc8 /* intel i845 registers */ -#define INTEL_I845_AGPM 0x51 -#define INTEL_I845_ERRSTS 0xc8 +#define INTEL_I845_AGPM 0x51 +#define INTEL_I845_ERRSTS 0xc8 /* intel i850 registers */ -#define INTEL_I850_MCHCFG 0x50 -#define INTEL_I850_ERRSTS 0xc8 +#define INTEL_I850_MCHCFG 0x50 +#define INTEL_I850_ERRSTS 0xc8 /* intel i860 registers */ #define INTEL_I860_MCHCFG 0x50 #define INTEL_I860_ERRSTS 0xc8 /* intel i810 registers */ -#define I810_GMADDR 0x10 -#define I810_MMADDR 0x14 -#define I810_PTE_BASE 0x10000 -#define I810_PTE_MAIN_UNCACHED 0x00000000 -#define I810_PTE_LOCAL 0x00000002 -#define I810_PTE_VALID 0x00000001 -#define I810_SMRAM_MISCC 0x70 -#define I810_GFX_MEM_WIN_SIZE 0x00010000 -#define I810_GFX_MEM_WIN_32M 0x00010000 -#define I810_GMS 0x000000c0 -#define I810_GMS_DISABLE 0x00000000 -#define I810_PGETBL_CTL 0x2020 -#define I810_PGETBL_ENABLED 0x00000001 -#define I810_DRAM_CTL 0x3000 -#define I810_DRAM_ROW_0 0x00000001 -#define I810_DRAM_ROW_0_SDRAM 0x00000001 +#define I810_GMADDR 0x10 +#define I810_MMADDR 0x14 +#define I810_PTE_BASE 0x10000 +#define I810_PTE_MAIN_UNCACHED 0x00000000 +#define I810_PTE_LOCAL 0x00000002 +#define I810_PTE_VALID 0x00000001 +#define I810_SMRAM_MISCC 0x70 +#define I810_GFX_MEM_WIN_SIZE 0x00010000 +#define I810_GFX_MEM_WIN_32M 0x00010000 +#define I810_GMS 0x000000c0 +#define I810_GMS_DISABLE 0x00000000 +#define I810_PGETBL_CTL 0x2020 +#define I810_PGETBL_ENABLED 0x00000001 +#define I810_DRAM_CTL 0x3000 +#define I810_DRAM_ROW_0 0x00000001 +#define I810_DRAM_ROW_0_SDRAM 0x00000001 /* VIA register */ -#define VIA_APBASE 0x10 -#define VIA_GARTCTRL 0x80 -#define VIA_APSIZE 0x84 -#define VIA_ATTBASE 0x88 +#define VIA_APBASE 0x10 +#define VIA_GARTCTRL 0x80 +#define VIA_APSIZE 0x84 +#define VIA_ATTBASE 0x88 /* SiS registers */ -#define SIS_APBASE 0x10 -#define SIS_ATTBASE 0x90 -#define SIS_APSIZE 0x94 -#define SIS_TLBCNTRL 0x97 -#define SIS_TLBFLUSH 0x98 +#define SIS_APBASE 0x10 +#define SIS_ATTBASE 0x90 +#define SIS_APSIZE 0x94 +#define SIS_TLBCNTRL 0x97 +#define SIS_TLBFLUSH 0x98 /* AMD registers */ -#define AMD_APBASE 0x10 -#define AMD_MMBASE 0x14 -#define AMD_APSIZE 0xac -#define AMD_MODECNTL 0xb0 -#define AMD_MODECNTL2 0xb2 -#define AMD_GARTENABLE 0x02 /* In mmio region (16-bit register) */ -#define AMD_ATTBASE 0x04 /* In mmio region (32-bit register) */ -#define AMD_TLBFLUSH 0x0c /* In mmio region (32-bit register) */ -#define AMD_CACHEENTRY 0x10 /* In mmio region (32-bit register) */ +#define AMD_APBASE 0x10 +#define AMD_MMBASE 0x14 +#define AMD_APSIZE 0xac +#define AMD_MODECNTL 0xb0 +#define AMD_MODECNTL2 0xb2 +#define AMD_GARTENABLE 0x02 /* In mmio region (16-bit register) */ +#define AMD_ATTBASE 0x04 /* In mmio region (32-bit register) */ +#define AMD_TLBFLUSH 0x0c /* In mmio region (32-bit register) */ +#define AMD_CACHEENTRY 0x10 /* In mmio region (32-bit register) */ /* ALi registers */ -#define ALI_APBASE 0x10 -#define ALI_AGPCTRL 0xb8 -#define ALI_ATTBASE 0xbc -#define ALI_TLBCTRL 0xc0 -#define ALI_TAGCTRL 0xc4 -#define ALI_CACHE_FLUSH_CTRL 0xD0 +#define ALI_APBASE 0x10 +#define ALI_AGPCTRL 0xb8 +#define ALI_ATTBASE 0xbc +#define ALI_TLBCTRL 0xc0 +#define ALI_TAGCTRL 0xc4 +#define ALI_CACHE_FLUSH_CTRL 0xD0 #define ALI_CACHE_FLUSH_ADDR_MASK 0xFFFFF000 -#define ALI_CACHE_FLUSH_EN 0x100 +#define ALI_CACHE_FLUSH_EN 0x100 /* Serverworks Registers */ -#define SVWRKS_APSIZE 0x10 -#define SVWRKS_SIZE_MASK 0xfe000000 +#define SVWRKS_APSIZE 0x10 +#define SVWRKS_SIZE_MASK 0xfe000000 -#define SVWRKS_MMBASE 0x14 -#define SVWRKS_CACHING 0x4b -#define SVWRKS_FEATURE 0x68 +#define SVWRKS_MMBASE 0x14 +#define SVWRKS_CACHING 0x4b +#define SVWRKS_FEATURE 0x68 /* func 1 registers */ -#define SVWRKS_AGP_ENABLE 0x60 -#define SVWRKS_COMMAND 0x04 +#define SVWRKS_AGP_ENABLE 0x60 +#define SVWRKS_COMMAND 0x04 /* Memory mapped registers */ -#define SVWRKS_GART_CACHE 0x02 -#define SVWRKS_GATTBASE 0x04 -#define SVWRKS_TLBFLUSH 0x10 -#define SVWRKS_POSTFLUSH 0x14 -#define SVWRKS_DIRFLUSH 0x0c +#define SVWRKS_GART_CACHE 0x02 +#define SVWRKS_GATTBASE 0x04 +#define SVWRKS_TLBFLUSH 0x10 +#define SVWRKS_POSTFLUSH 0x14 +#define SVWRKS_DIRFLUSH 0x0c /* HP ZX1 SBA registers */ #define HP_ZX1_CTRL 0x200 diff -Nru a/drivers/char/agp/agpgart_be-ali.c b/drivers/char/agp/agpgart_be-ali.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/agp/agpgart_be-ali.c Mon Jul 15 12:01:54 2002 @@ -0,0 +1,265 @@ +/* + * AGPGART module version 0.99 + * Copyright (C) 1999 Jeff Hartmann + * Copyright (C) 1999 Precision Insight, Inc. + * Copyright (C) 1999 Xi Graphics, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * TODO: + * - Allocate more than order 0 pages to avoid too much linear map splitting. + */ +#include +#include +#include +#include +#include +#include +#include "agp.h" + +static int ali_fetch_size(void) +{ + int i; + u32 temp; + struct aper_size_info_32 *values; + + pci_read_config_dword(agp_bridge.dev, ALI_ATTBASE, &temp); + temp &= ~(0xfffffff0); + values = A_SIZE_32(agp_bridge.aperture_sizes); + + for (i = 0; i < agp_bridge.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 ali_tlbflush(agp_memory * mem) +{ + u32 temp; + + pci_read_config_dword(agp_bridge.dev, ALI_TLBCTRL, &temp); +// clear tag + pci_write_config_dword(agp_bridge.dev, ALI_TAGCTRL, + ((temp & 0xfffffff0) | 0x00000001|0x00000002)); +} + +static void ali_cleanup(void) +{ + struct aper_size_info_32 *previous_size; + u32 temp; + + previous_size = A_SIZE_32(agp_bridge.previous_size); + + pci_read_config_dword(agp_bridge.dev, ALI_TLBCTRL, &temp); +// clear tag + pci_write_config_dword(agp_bridge.dev, ALI_TAGCTRL, + ((temp & 0xffffff00) | 0x00000001|0x00000002)); + + pci_read_config_dword(agp_bridge.dev, ALI_ATTBASE, &temp); + pci_write_config_dword(agp_bridge.dev, ALI_ATTBASE, + ((temp & 0x00000ff0) | previous_size->size_value)); +} + +static int ali_configure(void) +{ + u32 temp; + struct aper_size_info_32 *current_size; + + current_size = A_SIZE_32(agp_bridge.current_size); + + /* aperture size and gatt addr */ + pci_read_config_dword(agp_bridge.dev, ALI_ATTBASE, &temp); + temp = (((temp & 0x00000ff0) | (agp_bridge.gatt_bus_addr & 0xfffff000)) + | (current_size->size_value & 0xf)); + pci_write_config_dword(agp_bridge.dev, ALI_ATTBASE, temp); + + /* tlb control */ + + /* + * Question: Jeff, ALi's patch deletes this: + * + * pci_read_config_dword(agp_bridge.dev, ALI_TLBCTRL, &temp); + * pci_write_config_dword(agp_bridge.dev, ALI_TLBCTRL, + * ((temp & 0xffffff00) | 0x00000010)); + * + * and replaces it with the following, which seems to duplicate the + * next couple of lines below it. I suspect this was an oversight, + * but you might want to check up on this? + */ + + pci_read_config_dword(agp_bridge.dev, ALI_APBASE, &temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + + /* address to map to */ + pci_read_config_dword(agp_bridge.dev, ALI_APBASE, &temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + +#if 0 + if (agp_bridge.type == ALI_M1541) { + u32 nlvm_addr = 0; + + switch (current_size->size_value) { + case 0: break; + case 1: nlvm_addr = 0x100000;break; + case 2: nlvm_addr = 0x200000;break; + case 3: nlvm_addr = 0x400000;break; + case 4: nlvm_addr = 0x800000;break; + case 6: nlvm_addr = 0x1000000;break; + case 7: nlvm_addr = 0x2000000;break; + case 8: nlvm_addr = 0x4000000;break; + case 9: nlvm_addr = 0x8000000;break; + case 10: nlvm_addr = 0x10000000;break; + default: break; + } + nlvm_addr--; + nlvm_addr&=0xfff00000; + + nlvm_addr+= agp_bridge.gart_bus_addr; + nlvm_addr|=(agp_bridge.gart_bus_addr>>12); + printk(KERN_INFO PFX "nlvm top &base = %8x\n",nlvm_addr); + } +#endif + + pci_read_config_dword(agp_bridge.dev, ALI_TLBCTRL, &temp); + temp &= 0xffffff7f; //enable TLB + pci_write_config_dword(agp_bridge.dev, ALI_TLBCTRL, temp); + + return 0; +} + +static unsigned long ali_mask_memory(unsigned long addr, int type) +{ + /* Memory type is ignored */ + + return addr | agp_bridge.masks[0].mask; +} + +static void ali_cache_flush(void) +{ + global_cache_flush(); + + if (agp_bridge.type == ALI_M1541) { + int i, page_count; + u32 temp; + + page_count = 1 << A_SIZE_32(agp_bridge.current_size)->page_order; + for (i = 0; i < PAGE_SIZE * page_count; i += PAGE_SIZE) { + pci_read_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, &temp); + pci_write_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, + (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | + (agp_bridge.gatt_bus_addr + i)) | + ALI_CACHE_FLUSH_EN)); + } + } +} + +static void *ali_alloc_page(void) +{ + void *adr = agp_generic_alloc_page(); + u32 temp; + + if (adr == 0) + return 0; + + if (agp_bridge.type == ALI_M1541) { + pci_read_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, &temp); + pci_write_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, + (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | + virt_to_phys(adr)) | + ALI_CACHE_FLUSH_EN )); + } + return adr; +} + +static void ali_destroy_page(void * addr) +{ + u32 temp; + + if (addr == NULL) + return; + + global_cache_flush(); + + if (agp_bridge.type == ALI_M1541) { + pci_read_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, &temp); + pci_write_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, + (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | + virt_to_phys(addr)) | + ALI_CACHE_FLUSH_EN)); + } + + agp_generic_destroy_page(addr); +} + +/* Setup function */ +static struct gatt_mask ali_generic_masks[] = +{ + {mask: 0x00000000, type: 0} +}; + +static struct aper_size_info_32 ali_generic_sizes[7] = +{ + {256, 65536, 6, 10}, + {128, 32768, 5, 9}, + {64, 16384, 4, 8}, + {32, 8192, 3, 7}, + {16, 4096, 2, 6}, + {8, 2048, 1, 4}, + {4, 1024, 0, 3} +}; + +int __init ali_generic_setup (struct pci_dev *pdev) +{ + agp_bridge.masks = ali_generic_masks; + agp_bridge.num_of_masks = 1; + agp_bridge.aperture_sizes = (void *) ali_generic_sizes; + agp_bridge.size_type = U32_APER_SIZE; + agp_bridge.num_aperture_sizes = 7; + agp_bridge.dev_private_data = NULL; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = ali_configure; + agp_bridge.fetch_size = ali_fetch_size; + agp_bridge.cleanup = ali_cleanup; + agp_bridge.tlb_flush = ali_tlbflush; + agp_bridge.mask_memory = ali_mask_memory; + agp_bridge.agp_enable = agp_generic_agp_enable; + agp_bridge.cache_flush = ali_cache_flush; + agp_bridge.create_gatt_table = agp_generic_create_gatt_table; + agp_bridge.free_gatt_table = agp_generic_free_gatt_table; + agp_bridge.insert_memory = agp_generic_insert_memory; + agp_bridge.remove_memory = agp_generic_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = ali_alloc_page; + agp_bridge.agp_destroy_page = ali_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; + + return 0; + + (void) pdev; /* unused */ +} + diff -Nru a/drivers/char/agp/agpgart_be-amd.c b/drivers/char/agp/agpgart_be-amd.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/agp/agpgart_be-amd.c Mon Jul 15 12:01:54 2002 @@ -0,0 +1,408 @@ +/* + * AGPGART module version 0.99 + * Copyright (C) 1999 Jeff Hartmann + * Copyright (C) 1999 Precision Insight, Inc. + * Copyright (C) 1999 Xi Graphics, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * TODO: + * - Allocate more than order 0 pages to avoid too much linear map splitting. + */ + +#include +#include +#include +#include +#include "agp.h" + +struct amd_page_map { + unsigned long *real; + unsigned long *remapped; +}; + +static struct _amd_irongate_private { + volatile u8 *registers; + struct amd_page_map **gatt_pages; + int num_tables; +} amd_irongate_private; + +static int amd_create_page_map(struct amd_page_map *page_map) +{ + int i; + + page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL); + if (page_map->real == NULL) { + return -ENOMEM; + } + SetPageReserved(virt_to_page(page_map->real)); + CACHE_FLUSH(); + 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)); + free_page((unsigned long) page_map->real); + page_map->real = NULL; + return -ENOMEM; + } + CACHE_FLUSH(); + + for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { + page_map->remapped[i] = agp_bridge.scratch_page; + } + + return 0; +} + +static void amd_free_page_map(struct amd_page_map *page_map) +{ + iounmap(page_map->remapped); + ClearPageReserved(virt_to_page(page_map->real)); + free_page((unsigned long) page_map->real); +} + +static void amd_free_gatt_pages(void) +{ + int i; + struct amd_page_map **tables; + struct amd_page_map *entry; + + tables = amd_irongate_private.gatt_pages; + for(i = 0; i < amd_irongate_private.num_tables; i++) { + entry = tables[i]; + if (entry != NULL) { + if (entry->real != NULL) { + amd_free_page_map(entry); + } + kfree(entry); + } + } + kfree(tables); +} + +static int amd_create_gatt_pages(int nr_tables) +{ + struct amd_page_map **tables; + struct amd_page_map *entry; + int retval = 0; + int i; + + tables = kmalloc((nr_tables + 1) * sizeof(struct amd_page_map *), + GFP_KERNEL); + if (tables == NULL) { + return -ENOMEM; + } + memset(tables, 0, sizeof(struct amd_page_map *) * (nr_tables + 1)); + for (i = 0; i < nr_tables; i++) { + entry = kmalloc(sizeof(struct amd_page_map), GFP_KERNEL); + if (entry == NULL) { + retval = -ENOMEM; + break; + } + memset(entry, 0, sizeof(struct amd_page_map)); + tables[i] = entry; + retval = amd_create_page_map(entry); + if (retval != 0) break; + } + amd_irongate_private.num_tables = nr_tables; + amd_irongate_private.gatt_pages = tables; + + if (retval != 0) amd_free_gatt_pages(); + + return retval; +} + +/* Since we don't need contigious memory we just try + * 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) +#define GET_GATT(addr) (amd_irongate_private.gatt_pages[\ + GET_PAGE_DIR_IDX(addr)]->remapped) + +static int amd_create_gatt_table(void) +{ + struct aper_size_info_lvl2 *value; + struct amd_page_map page_dir; + unsigned long addr; + int retval; + u32 temp; + int i; + + value = A_SIZE_LVL2(agp_bridge.current_size); + retval = amd_create_page_map(&page_dir); + if (retval != 0) { + return retval; + } + + retval = amd_create_gatt_pages(value->num_entries / 1024); + if (retval != 0) { + amd_free_page_map(&page_dir); + return retval; + } + + agp_bridge.gatt_table_real = page_dir.real; + agp_bridge.gatt_table = page_dir.remapped; + agp_bridge.gatt_bus_addr = virt_to_phys(page_dir.real); + + /* 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, AMD_APBASE, &temp); + addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + agp_bridge.gart_bus_addr = addr; + + /* Calculate the agp offset */ + for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { + page_dir.remapped[GET_PAGE_DIR_OFF(addr)] = + virt_to_phys(amd_irongate_private.gatt_pages[i]->real); + page_dir.remapped[GET_PAGE_DIR_OFF(addr)] |= 0x00000001; + } + + return 0; +} + +static int amd_free_gatt_table(void) +{ + struct amd_page_map page_dir; + + page_dir.real = agp_bridge.gatt_table_real; + page_dir.remapped = agp_bridge.gatt_table; + + amd_free_gatt_pages(); + amd_free_page_map(&page_dir); + return 0; +} + +static int amd_irongate_fetch_size(void) +{ + int i; + u32 temp; + struct aper_size_info_lvl2 *values; + + pci_read_config_dword(agp_bridge.dev, AMD_APSIZE, &temp); + temp = (temp & 0x0000000e); + values = A_SIZE_LVL2(agp_bridge.aperture_sizes); + for (i = 0; i < agp_bridge.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 int amd_irongate_configure(void) +{ + struct aper_size_info_lvl2 *current_size; + u32 temp; + u16 enable_reg; + + current_size = A_SIZE_LVL2(agp_bridge.current_size); + + /* Get the memory mapped registers */ + pci_read_config_dword(agp_bridge.dev, AMD_MMBASE, &temp); + temp = (temp & PCI_BASE_ADDRESS_MEM_MASK); + amd_irongate_private.registers = (volatile u8 *) ioremap(temp, 4096); + + /* Write out the address of the gatt table */ + OUTREG32(amd_irongate_private.registers, AMD_ATTBASE, + agp_bridge.gatt_bus_addr); + + /* 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); + + /* Write the enable register */ + enable_reg = INREG16(amd_irongate_private.registers, AMD_GARTENABLE); + enable_reg = (enable_reg | 0x0004); + OUTREG16(amd_irongate_private.registers, AMD_GARTENABLE, enable_reg); + + /* Write out the size register */ + pci_read_config_dword(agp_bridge.dev, AMD_APSIZE, &temp); + temp = (((temp & ~(0x0000000e)) | current_size->size_value) + | 0x00000001); + pci_write_config_dword(agp_bridge.dev, AMD_APSIZE, temp); + + /* Flush the tlb */ + OUTREG32(amd_irongate_private.registers, AMD_TLBFLUSH, 0x00000001); + + return 0; +} + +static void amd_irongate_cleanup(void) +{ + struct aper_size_info_lvl2 *previous_size; + u32 temp; + u16 enable_reg; + + previous_size = A_SIZE_LVL2(agp_bridge.previous_size); + + enable_reg = INREG16(amd_irongate_private.registers, AMD_GARTENABLE); + enable_reg = (enable_reg & ~(0x0004)); + OUTREG16(amd_irongate_private.registers, AMD_GARTENABLE, enable_reg); + + /* Write back the previous size and disable gart translation */ + pci_read_config_dword(agp_bridge.dev, AMD_APSIZE, &temp); + temp = ((temp & ~(0x0000000f)) | previous_size->size_value); + pci_write_config_dword(agp_bridge.dev, AMD_APSIZE, temp); + iounmap((void *) amd_irongate_private.registers); +} + +/* + * This routine could be implemented by taking the addresses + * written to the GATT, and flushing them individually. However + * currently it just flushes the whole table. Which is probably + * more efficent, since agp_memory blocks can be a large number of + * entries. + */ + +static void amd_irongate_tlbflush(agp_memory * temp) +{ + OUTREG32(amd_irongate_private.registers, AMD_TLBFLUSH, 0x00000001); +} + +static unsigned long amd_irongate_mask_memory(unsigned long addr, int type) +{ + /* Only type 0 is supported by the irongate */ + + return addr | agp_bridge.masks[0].mask; +} + +static int amd_insert_memory(agp_memory * mem, + off_t pg_start, int type) +{ + int i, j, num_entries; + unsigned long *cur_gatt; + unsigned long addr; + + num_entries = A_SIZE_LVL2(agp_bridge.current_size)->num_entries; + + if (type != 0 || mem->type != 0) { + return -EINVAL; + } + 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(cur_gatt[GET_GATT_OFF(addr)])) { + return -EBUSY; + } + j++; + } + + if (mem->is_flushed == FALSE) { + CACHE_FLUSH(); + mem->is_flushed = TRUE; + } + + 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); + cur_gatt[GET_GATT_OFF(addr)] = mem->memory[i]; + } + agp_bridge.tlb_flush(mem); + return 0; +} + +static int amd_remove_memory(agp_memory * mem, off_t pg_start, + int type) +{ + int i; + unsigned long *cur_gatt; + unsigned long addr; + + if (type != 0 || mem->type != 0) { + return -EINVAL; + } + 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); + cur_gatt[GET_GATT_OFF(addr)] = + (unsigned long) agp_bridge.scratch_page; + } + + agp_bridge.tlb_flush(mem); + return 0; +} + +static struct aper_size_info_lvl2 amd_irongate_sizes[7] = +{ + {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 amd_irongate_masks[] = +{ + {mask: 0x00000001, type: 0} +}; + +int __init amd_irongate_setup (struct pci_dev *pdev) +{ + agp_bridge.masks = amd_irongate_masks; + agp_bridge.num_of_masks = 1; + agp_bridge.aperture_sizes = (void *) amd_irongate_sizes; + agp_bridge.size_type = LVL2_APER_SIZE; + agp_bridge.num_aperture_sizes = 7; + agp_bridge.dev_private_data = (void *) &amd_irongate_private; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = amd_irongate_configure; + agp_bridge.fetch_size = amd_irongate_fetch_size; + agp_bridge.cleanup = amd_irongate_cleanup; + agp_bridge.tlb_flush = amd_irongate_tlbflush; + agp_bridge.mask_memory = amd_irongate_mask_memory; + agp_bridge.agp_enable = agp_generic_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = amd_create_gatt_table; + agp_bridge.free_gatt_table = amd_free_gatt_table; + agp_bridge.insert_memory = amd_insert_memory; + agp_bridge.remove_memory = amd_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; + + return 0; + + (void) pdev; /* unused */ +} + diff -Nru a/drivers/char/agp/agpgart_be-hp.c b/drivers/char/agp/agpgart_be-hp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/agp/agpgart_be-hp.c Mon Jul 15 12:01:54 2002 @@ -0,0 +1,394 @@ +/* + * AGPGART module version 0.99 + * Copyright (C) 1999 Jeff Hartmann + * Copyright (C) 1999 Precision Insight, Inc. + * Copyright (C) 1999 Xi Graphics, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * TODO: + * - Allocate more than order 0 pages to avoid too much linear map splitting. + */ + +#include +#include +#include +#include +#include "agp.h" + + +#ifndef log2 +#define log2(x) ffz(~(x)) +#endif + +#define HP_ZX1_IOVA_BASE GB(1UL) +#define HP_ZX1_IOVA_SIZE GB(1UL) +#define HP_ZX1_GART_SIZE (HP_ZX1_IOVA_SIZE / 2) +#define HP_ZX1_SBA_IOMMU_COOKIE 0x0000badbadc0ffeeUL + +#define HP_ZX1_PDIR_VALID_BIT 0x8000000000000000UL +#define HP_ZX1_IOVA_TO_PDIR(va) ((va - hp_private.iova_base) >> \ + hp_private.io_tlb_shift) + +static struct aper_size_info_fixed hp_zx1_sizes[] = +{ + {0, 0, 0}, /* filled in by hp_zx1_fetch_size() */ +}; + +static struct gatt_mask hp_zx1_masks[] = +{ + {mask: HP_ZX1_PDIR_VALID_BIT, type: 0} +}; + +static struct _hp_private { + struct pci_dev *ioc; + volatile u8 *registers; + u64 *io_pdir; // PDIR for entire IOVA + u64 *gatt; // PDIR just for GART (subset of above) + u64 gatt_entries; + u64 iova_base; + u64 gart_base; + u64 gart_size; + u64 io_pdir_size; + int io_pdir_owner; // do we own it, or share it with sba_iommu? + int io_page_size; + int io_tlb_shift; + int io_tlb_ps; // IOC ps config + int io_pages_per_kpage; +} hp_private; + +static int __init hp_zx1_ioc_shared(void) +{ + struct _hp_private *hp = &hp_private; + + printk(KERN_INFO PFX "HP ZX1 IOC: IOPDIR shared with sba_iommu\n"); + + /* + * IOC already configured by sba_iommu module; just use + * its setup. We assume: + * - IOVA space is 1Gb in size + * - first 512Mb is IOMMU, second 512Mb is GART + */ + hp->io_tlb_ps = INREG64(hp->registers, HP_ZX1_TCNFG); + switch (hp->io_tlb_ps) { + case 0: hp->io_tlb_shift = 12; break; + case 1: hp->io_tlb_shift = 13; break; + case 2: hp->io_tlb_shift = 14; break; + case 3: hp->io_tlb_shift = 16; break; + default: + printk(KERN_ERR PFX "Invalid IOTLB page size " + "configuration 0x%x\n", hp->io_tlb_ps); + hp->gatt = 0; + hp->gatt_entries = 0; + return -ENODEV; + } + hp->io_page_size = 1 << hp->io_tlb_shift; + hp->io_pages_per_kpage = PAGE_SIZE / hp->io_page_size; + + hp->iova_base = INREG64(hp->registers, HP_ZX1_IBASE) & ~0x1; + hp->gart_base = hp->iova_base + HP_ZX1_IOVA_SIZE - HP_ZX1_GART_SIZE; + + hp->gart_size = HP_ZX1_GART_SIZE; + hp->gatt_entries = hp->gart_size / hp->io_page_size; + + hp->io_pdir = phys_to_virt(INREG64(hp->registers, HP_ZX1_PDIR_BASE)); + hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)]; + + if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) { + hp->gatt = 0; + hp->gatt_entries = 0; + printk(KERN_ERR PFX "No reserved IO PDIR entry found; " + "GART disabled\n"); + return -ENODEV; + } + + return 0; +} + +static int __init hp_zx1_ioc_owner(u8 ioc_rev) +{ + struct _hp_private *hp = &hp_private; + + printk(KERN_INFO PFX "HP ZX1 IOC: IOPDIR dedicated to GART\n"); + + /* + * Select an IOV page size no larger than system page size. + */ + if (PAGE_SIZE >= KB(64)) { + hp->io_tlb_shift = 16; + hp->io_tlb_ps = 3; + } else if (PAGE_SIZE >= KB(16)) { + hp->io_tlb_shift = 14; + hp->io_tlb_ps = 2; + } else if (PAGE_SIZE >= KB(8)) { + hp->io_tlb_shift = 13; + hp->io_tlb_ps = 1; + } else { + hp->io_tlb_shift = 12; + hp->io_tlb_ps = 0; + } + hp->io_page_size = 1 << hp->io_tlb_shift; + hp->io_pages_per_kpage = PAGE_SIZE / hp->io_page_size; + + hp->iova_base = HP_ZX1_IOVA_BASE; + hp->gart_size = HP_ZX1_GART_SIZE; + hp->gart_base = hp->iova_base + HP_ZX1_IOVA_SIZE - hp->gart_size; + + hp->gatt_entries = hp->gart_size / hp->io_page_size; + hp->io_pdir_size = (HP_ZX1_IOVA_SIZE / hp->io_page_size) * sizeof(u64); + + return 0; +} + +static int __init hp_zx1_ioc_init(void) +{ + struct _hp_private *hp = &hp_private; + struct pci_dev *ioc; + int i; + u8 ioc_rev; + + ioc = pci_find_device(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_ZX1_IOC, NULL); + if (!ioc) { + printk(KERN_ERR PFX "Detected HP ZX1 AGP bridge but no IOC\n"); + return -ENODEV; + } + hp->ioc = ioc; + + pci_read_config_byte(ioc, PCI_REVISION_ID, &ioc_rev); + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + if (pci_resource_flags(ioc, i) == IORESOURCE_MEM) { + hp->registers = (u8 *) ioremap(pci_resource_start(ioc, + i), + pci_resource_len(ioc, i)); + break; + } + } + if (!hp->registers) { + printk(KERN_ERR PFX "Detected HP ZX1 AGP bridge but no CSRs\n"); + + return -ENODEV; + } + + /* + * If the IOTLB is currently disabled, we can take it over. + * Otherwise, we have to share with sba_iommu. + */ + hp->io_pdir_owner = (INREG64(hp->registers, HP_ZX1_IBASE) & 0x1) == 0; + + if (hp->io_pdir_owner) + return hp_zx1_ioc_owner(ioc_rev); + + return hp_zx1_ioc_shared(); +} + +static int hp_zx1_fetch_size(void) +{ + int size; + + size = hp_private.gart_size / MB(1); + hp_zx1_sizes[0].size = size; + agp_bridge.current_size = (void *) &hp_zx1_sizes[0]; + return size; +} + +static int hp_zx1_configure(void) +{ + struct _hp_private *hp = &hp_private; + + agp_bridge.gart_bus_addr = hp->gart_base; + agp_bridge.capndx = pci_find_capability(agp_bridge.dev, PCI_CAP_ID_AGP); + pci_read_config_dword(agp_bridge.dev, + agp_bridge.capndx + PCI_AGP_STATUS, &agp_bridge.mode); + + if (hp->io_pdir_owner) { + OUTREG64(hp->registers, HP_ZX1_PDIR_BASE, + virt_to_phys(hp->io_pdir)); + OUTREG64(hp->registers, HP_ZX1_TCNFG, hp->io_tlb_ps); + OUTREG64(hp->registers, HP_ZX1_IMASK, ~(HP_ZX1_IOVA_SIZE - 1)); + OUTREG64(hp->registers, HP_ZX1_IBASE, hp->iova_base | 0x1); + OUTREG64(hp->registers, HP_ZX1_PCOM, + hp->iova_base | log2(HP_ZX1_IOVA_SIZE)); + INREG64(hp->registers, HP_ZX1_PCOM); + } + + return 0; +} + +static void hp_zx1_cleanup(void) +{ + struct _hp_private *hp = &hp_private; + + if (hp->io_pdir_owner) + OUTREG64(hp->registers, HP_ZX1_IBASE, 0); + iounmap((void *) hp->registers); +} + +static void hp_zx1_tlbflush(agp_memory * mem) +{ + struct _hp_private *hp = &hp_private; + + OUTREG64(hp->registers, HP_ZX1_PCOM, + hp->gart_base | log2(hp->gart_size)); + INREG64(hp->registers, HP_ZX1_PCOM); +} + +static int hp_zx1_create_gatt_table(void) +{ + struct _hp_private *hp = &hp_private; + int i; + + if (hp->io_pdir_owner) { + hp->io_pdir = (u64 *) __get_free_pages(GFP_KERNEL, + get_order(hp->io_pdir_size)); + if (!hp->io_pdir) { + printk(KERN_ERR PFX "Couldn't allocate contiguous " + "memory for I/O PDIR\n"); + hp->gatt = 0; + hp->gatt_entries = 0; + return -ENOMEM; + } + memset(hp->io_pdir, 0, hp->io_pdir_size); + + hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)]; + } + + for (i = 0; i < hp->gatt_entries; i++) { + hp->gatt[i] = (unsigned long) agp_bridge.scratch_page; + } + + return 0; +} + +static int hp_zx1_free_gatt_table(void) +{ + struct _hp_private *hp = &hp_private; + + if (hp->io_pdir_owner) + free_pages((unsigned long) hp->io_pdir, + get_order(hp->io_pdir_size)); + else + hp->gatt[0] = HP_ZX1_SBA_IOMMU_COOKIE; + return 0; +} + +static int hp_zx1_insert_memory(agp_memory * mem, off_t pg_start, int type) +{ + struct _hp_private *hp = &hp_private; + int i, k; + off_t j, io_pg_start; + int io_pg_count; + + if (type != 0 || mem->type != 0) { + return -EINVAL; + } + + io_pg_start = hp->io_pages_per_kpage * pg_start; + io_pg_count = hp->io_pages_per_kpage * mem->page_count; + if ((io_pg_start + io_pg_count) > hp->gatt_entries) { + return -EINVAL; + } + + j = io_pg_start; + while (j < (io_pg_start + io_pg_count)) { + if (hp->gatt[j]) { + return -EBUSY; + } + j++; + } + + if (mem->is_flushed == FALSE) { + CACHE_FLUSH(); + mem->is_flushed = TRUE; + } + + for (i = 0, j = io_pg_start; i < mem->page_count; i++) { + unsigned long paddr; + + paddr = mem->memory[i]; + for (k = 0; + k < hp->io_pages_per_kpage; + k++, j++, paddr += hp->io_page_size) { + hp->gatt[j] = agp_bridge.mask_memory(paddr, type); + } + } + + agp_bridge.tlb_flush(mem); + return 0; +} + +static int hp_zx1_remove_memory(agp_memory * mem, off_t pg_start, int type) +{ + struct _hp_private *hp = &hp_private; + int i, io_pg_start, io_pg_count; + + if (type != 0 || mem->type != 0) { + return -EINVAL; + } + + io_pg_start = hp->io_pages_per_kpage * pg_start; + io_pg_count = hp->io_pages_per_kpage * mem->page_count; + for (i = io_pg_start; i < io_pg_count + io_pg_start; i++) { + hp->gatt[i] = agp_bridge.scratch_page; + } + + agp_bridge.tlb_flush(mem); + return 0; +} + +static unsigned long hp_zx1_mask_memory(unsigned long addr, int type) +{ + return HP_ZX1_PDIR_VALID_BIT | addr; +} + +static unsigned long hp_zx1_unmask_memory(unsigned long addr) +{ + return addr & ~(HP_ZX1_PDIR_VALID_BIT); +} + +int __init hp_zx1_setup (struct pci_dev *pdev) +{ + agp_bridge.masks = hp_zx1_masks; + agp_bridge.num_of_masks = 1; + agp_bridge.dev_private_data = NULL; + agp_bridge.size_type = FIXED_APER_SIZE; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = hp_zx1_configure; + agp_bridge.fetch_size = hp_zx1_fetch_size; + agp_bridge.cleanup = hp_zx1_cleanup; + agp_bridge.tlb_flush = hp_zx1_tlbflush; + agp_bridge.mask_memory = hp_zx1_mask_memory; + agp_bridge.unmask_memory = hp_zx1_unmask_memory; + agp_bridge.agp_enable = agp_generic_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = hp_zx1_create_gatt_table; + agp_bridge.free_gatt_table = hp_zx1_free_gatt_table; + agp_bridge.insert_memory = hp_zx1_insert_memory; + agp_bridge.remove_memory = hp_zx1_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.cant_use_aperture = 1; + + return hp_zx1_ioc_init(); + + (void) pdev; /* unused */ +} + diff -Nru a/drivers/char/agp/agpgart_be-i460.c b/drivers/char/agp/agpgart_be-i460.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/agp/agpgart_be-i460.c Mon Jul 15 12:01:54 2002 @@ -0,0 +1,595 @@ +/* + * AGPGART module version 0.99 + * Copyright (C) 1999 Jeff Hartmann + * Copyright (C) 1999 Precision Insight, Inc. + * Copyright (C) 1999 Xi Graphics, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * TODO: + * - Allocate more than order 0 pages to avoid too much linear map splitting. + */ + +#include +#include +#include +#include +#include "agp.h" + +/* BIOS configures the chipset so that one of two apbase registers are used */ +static u8 intel_i460_dynamic_apbase = 0x10; + +/* 460 supports multiple GART page sizes, so GART pageshift is dynamic */ +static u8 intel_i460_pageshift = 12; +static u32 intel_i460_pagesize; + +/* Keep track of which is larger, chipset or kernel page size. */ +static u32 intel_i460_cpk = 1; + +/* Structure for tracking partial use of 4MB GART pages */ +static u32 **i460_pg_detail = NULL; +static u32 *i460_pg_count = NULL; + +#define I460_CPAGES_PER_KPAGE (PAGE_SIZE >> intel_i460_pageshift) +#define I460_KPAGES_PER_CPAGE ((1 << intel_i460_pageshift) >> PAGE_SHIFT) + +#define I460_SRAM_IO_DISABLE (1 << 4) +#define I460_BAPBASE_ENABLE (1 << 3) +#define I460_AGPSIZ_MASK 0x7 +#define I460_4M_PS (1 << 1) + +#define log2(x) ffz(~(x)) + +static inline void intel_i460_read_back (volatile u32 *entry) +{ + /* + * The 460 spec says we have to read the last location written to + * make sure that all writes have taken effect + */ + *entry; +} + +static int intel_i460_fetch_size(void) +{ + int i; + u8 temp; + struct aper_size_info_8 *values; + + /* Determine the GART page size */ + pci_read_config_byte(agp_bridge.dev, INTEL_I460_GXBCTL, &temp); + intel_i460_pageshift = (temp & I460_4M_PS) ? 22 : 12; + intel_i460_pagesize = 1UL << intel_i460_pageshift; + + values = A_SIZE_8(agp_bridge.aperture_sizes); + + pci_read_config_byte(agp_bridge.dev, INTEL_I460_AGPSIZ, &temp); + + /* Exit now if the IO drivers for the GART SRAMS are turned off */ + if (temp & I460_SRAM_IO_DISABLE) { + printk(KERN_ERR PFX "GART SRAMS disabled on 460GX chipset\n"); + printk(KERN_ERR PFX "AGPGART operation not possible\n"); + return 0; + } + + /* Make sure we don't try to create an 2 ^ 23 entry GATT */ + if ((intel_i460_pageshift == 0) && ((temp & I460_AGPSIZ_MASK) == 4)) { + printk(KERN_ERR PFX "We can't have a 32GB aperture with 4KB GART pages\n"); + return 0; + } + + /* Determine the proper APBASE register */ + if (temp & I460_BAPBASE_ENABLE) + intel_i460_dynamic_apbase = INTEL_I460_BAPBASE; + else + intel_i460_dynamic_apbase = INTEL_I460_APBASE; + + for (i = 0; i < agp_bridge.num_aperture_sizes; i++) { + /* + * Dynamically calculate the proper num_entries and page_order values for + * the define aperture sizes. Take care not to shift off the end of + * values[i].size. + */ + values[i].num_entries = (values[i].size << 8) >> (intel_i460_pageshift - 12); + values[i].page_order = log2((sizeof(u32)*values[i].num_entries) >> PAGE_SHIFT); + } + + for (i = 0; i < agp_bridge.num_aperture_sizes; i++) { + /* Neglect control bits when matching up size_value */ + if ((temp & I460_AGPSIZ_MASK) == 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; +} + +/* There isn't anything to do here since 460 has no GART TLB. */ +static void intel_i460_tlb_flush(agp_memory * mem) +{ + return; +} + +/* + * This utility function is needed to prevent corruption of the control bits + * which are stored along with the aperture size in 460's AGPSIZ register + */ +static void intel_i460_write_agpsiz(u8 size_value) +{ + u8 temp; + + pci_read_config_byte(agp_bridge.dev, INTEL_I460_AGPSIZ, &temp); + pci_write_config_byte(agp_bridge.dev, INTEL_I460_AGPSIZ, + ((temp & ~I460_AGPSIZ_MASK) | size_value)); +} + +static void intel_i460_cleanup(void) +{ + struct aper_size_info_8 *previous_size; + + previous_size = A_SIZE_8(agp_bridge.previous_size); + intel_i460_write_agpsiz(previous_size->size_value); + + if (intel_i460_cpk == 0) { + vfree(i460_pg_detail); + vfree(i460_pg_count); + } +} + + +/* Control bits for Out-Of-GART coherency and Burst Write Combining */ +#define I460_GXBCTL_OOG (1UL << 0) +#define I460_GXBCTL_BWC (1UL << 2) + +static int intel_i460_configure(void) +{ + union { + u32 small[2]; + u64 large; + } temp; + u8 scratch; + int i; + + struct aper_size_info_8 *current_size; + + temp.large = 0; + + current_size = A_SIZE_8(agp_bridge.current_size); + intel_i460_write_agpsiz(current_size->size_value); + + /* + * Do the necessary rigmarole to read all eight bytes of APBASE. + * This has to be done since the AGP aperture can be above 4GB on + * 460 based systems. + */ + pci_read_config_dword(agp_bridge.dev, intel_i460_dynamic_apbase, &(temp.small[0])); + pci_read_config_dword(agp_bridge.dev, intel_i460_dynamic_apbase + 4, &(temp.small[1])); + + /* Clear BAR control bits */ + agp_bridge.gart_bus_addr = temp.large & ~((1UL << 3) - 1); + + pci_read_config_byte(agp_bridge.dev, INTEL_I460_GXBCTL, &scratch); + pci_write_config_byte(agp_bridge.dev, INTEL_I460_GXBCTL, + (scratch & 0x02) | I460_GXBCTL_OOG | I460_GXBCTL_BWC); + + /* + * Initialize partial allocation trackers if a GART page is bigger than + * a kernel page. + */ + if (I460_CPAGES_PER_KPAGE >= 1) { + intel_i460_cpk = 1; + } else { + intel_i460_cpk = 0; + + i460_pg_detail = vmalloc(sizeof(*i460_pg_detail) * current_size->num_entries); + i460_pg_count = vmalloc(sizeof(*i460_pg_count) * current_size->num_entries); + + for (i = 0; i < current_size->num_entries; i++) { + i460_pg_count[i] = 0; + i460_pg_detail[i] = NULL; + } + } + return 0; +} + +static int intel_i460_create_gatt_table(void) +{ + char *table; + int i; + int page_order; + int num_entries; + void *temp; + + /* + * Load up the fixed address of the GART SRAMS which hold our + * GATT table. + */ + table = (char *) __va(INTEL_I460_ATTBASE); + + temp = agp_bridge.current_size; + page_order = A_SIZE_8(temp)->page_order; + num_entries = A_SIZE_8(temp)->num_entries; + + agp_bridge.gatt_table_real = (u32 *) table; + agp_bridge.gatt_table = ioremap_nocache(virt_to_phys(table), + (PAGE_SIZE * (1 << page_order))); + agp_bridge.gatt_bus_addr = virt_to_phys(agp_bridge.gatt_table_real); + + for (i = 0; i < num_entries; i++) { + agp_bridge.gatt_table[i] = 0; + } + + intel_i460_read_back(agp_bridge.gatt_table + i - 1); + return 0; +} + +static int intel_i460_free_gatt_table(void) +{ + int num_entries; + int i; + void *temp; + + temp = agp_bridge.current_size; + + num_entries = A_SIZE_8(temp)->num_entries; + + for (i = 0; i < num_entries; i++) { + agp_bridge.gatt_table[i] = 0; + } + + intel_i460_read_back(agp_bridge.gatt_table + i - 1); + + iounmap(agp_bridge.gatt_table); + return 0; +} + +/* These functions are called when PAGE_SIZE exceeds the GART page size */ + +static int intel_i460_insert_memory_cpk(agp_memory * mem, off_t pg_start, int type) +{ + int i, j, k, num_entries; + void *temp; + unsigned long paddr; + + /* + * The rest of the kernel will compute page offsets in terms of + * PAGE_SIZE. + */ + pg_start = I460_CPAGES_PER_KPAGE * pg_start; + + temp = agp_bridge.current_size; + num_entries = A_SIZE_8(temp)->num_entries; + + if ((pg_start + I460_CPAGES_PER_KPAGE * mem->page_count) > num_entries) { + printk(KERN_ERR PFX "Looks like we're out of AGP memory\n"); + return -EINVAL; + } + + j = pg_start; + while (j < (pg_start + I460_CPAGES_PER_KPAGE * mem->page_count)) { + if (!PGE_EMPTY(agp_bridge.gatt_table[j])) { + return -EBUSY; + } + j++; + } + +#if 0 + /* not necessary since 460 GART is operated in coherent mode... */ + if (mem->is_flushed == FALSE) { + CACHE_FLUSH(); + mem->is_flushed = TRUE; + } +#endif + + for (i = 0, j = pg_start; i < mem->page_count; i++) { + paddr = mem->memory[i]; + for (k = 0; k < I460_CPAGES_PER_KPAGE; k++, j++, paddr += intel_i460_pagesize) + agp_bridge.gatt_table[j] = (u32) agp_bridge.mask_memory(paddr, mem->type); + } + + intel_i460_read_back(agp_bridge.gatt_table + j - 1); + return 0; +} + +static int intel_i460_remove_memory_cpk(agp_memory * mem, off_t pg_start, int type) +{ + int i; + + pg_start = I460_CPAGES_PER_KPAGE * pg_start; + + for (i = pg_start; i < (pg_start + I460_CPAGES_PER_KPAGE * mem->page_count); i++) + agp_bridge.gatt_table[i] = 0; + + intel_i460_read_back(agp_bridge.gatt_table + i - 1); + return 0; +} + +/* + * These functions are called when the GART page size exceeds PAGE_SIZE. + * + * This situation is interesting since AGP memory allocations that are + * smaller than a single GART page are possible. The structures i460_pg_count + * and i460_pg_detail track partial allocation of the large GART pages to + * work around this issue. + * + * i460_pg_count[pg_num] tracks the number of kernel pages in use within + * GART page pg_num. i460_pg_detail[pg_num] is an array containing a + * psuedo-GART entry for each of the aforementioned kernel pages. The whole + * of i460_pg_detail is equivalent to a giant GATT with page size equal to + * that of the kernel. + */ + +static void *intel_i460_alloc_large_page(int pg_num) +{ + int i; + void *bp, *bp_end; + struct page *page; + + i460_pg_detail[pg_num] = (void *) vmalloc(sizeof(u32) * I460_KPAGES_PER_CPAGE); + if (i460_pg_detail[pg_num] == NULL) { + printk(KERN_ERR PFX "Out of memory, we're in trouble...\n"); + return NULL; + } + + for (i = 0; i < I460_KPAGES_PER_CPAGE; i++) + i460_pg_detail[pg_num][i] = 0; + + bp = (void *) __get_free_pages(GFP_KERNEL, intel_i460_pageshift - PAGE_SHIFT); + if (bp == NULL) { + printk(KERN_ERR PFX "Couldn't alloc 4M GART page...\n"); + return NULL; + } + + bp_end = bp + ((PAGE_SIZE * (1 << (intel_i460_pageshift - PAGE_SHIFT))) - 1); + + for (page = virt_to_page(bp); page <= virt_to_page(bp_end); page++) { + atomic_inc(&agp_bridge.current_memory_agp); + } + return bp; +} + +static void intel_i460_free_large_page(int pg_num, unsigned long addr) +{ + struct page *page; + void *bp, *bp_end; + + bp = (void *) __va(addr); + bp_end = bp + (PAGE_SIZE * (1 << (intel_i460_pageshift - PAGE_SHIFT))); + + vfree(i460_pg_detail[pg_num]); + i460_pg_detail[pg_num] = NULL; + + for (page = virt_to_page(bp); page < virt_to_page(bp_end); page++) { + atomic_dec(&agp_bridge.current_memory_agp); + } + + free_pages((unsigned long) bp, intel_i460_pageshift - PAGE_SHIFT); +} + +static int intel_i460_insert_memory_kpc(agp_memory * mem, off_t pg_start, int type) +{ + int i, pg, start_pg, end_pg, start_offset, end_offset, idx; + int num_entries; + void *temp; + unsigned long paddr; + + temp = agp_bridge.current_size; + num_entries = A_SIZE_8(temp)->num_entries; + + /* Figure out what pg_start means in terms of our large GART pages */ + start_pg = pg_start / I460_KPAGES_PER_CPAGE; + start_offset = pg_start % I460_KPAGES_PER_CPAGE; + end_pg = (pg_start + mem->page_count - 1) / I460_KPAGES_PER_CPAGE; + end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_CPAGE; + + if (end_pg > num_entries) { + printk(KERN_ERR PFX "Looks like we're out of AGP memory\n"); + return -EINVAL; + } + + /* Check if the requested region of the aperture is free */ + for (pg = start_pg; pg <= end_pg; pg++) { + /* Allocate new GART pages if necessary */ + if (i460_pg_detail[pg] == NULL) { + temp = intel_i460_alloc_large_page(pg); + if (temp == NULL) + return -ENOMEM; + agp_bridge.gatt_table[pg] = agp_bridge.mask_memory((unsigned long) temp, + 0); + intel_i460_read_back(agp_bridge.gatt_table + pg); + } + + for (idx = ((pg == start_pg) ? start_offset : 0); + idx < ((pg == end_pg) ? (end_offset + 1) : I460_KPAGES_PER_CPAGE); + idx++) + { + if (i460_pg_detail[pg][idx] != 0) + return -EBUSY; + } + } + +#if 0 + /* not necessary since 460 GART is operated in coherent mode... */ + if (mem->is_flushed == FALSE) { + CACHE_FLUSH(); + mem->is_flushed = TRUE; + } +#endif + + for (pg = start_pg, i = 0; pg <= end_pg; pg++) { + paddr = agp_bridge.unmask_memory(agp_bridge.gatt_table[pg]); + for (idx = ((pg == start_pg) ? start_offset : 0); + idx < ((pg == end_pg) ? (end_offset + 1) : I460_KPAGES_PER_CPAGE); + idx++, i++) + { + mem->memory[i] = paddr + (idx * PAGE_SIZE); + i460_pg_detail[pg][idx] = agp_bridge.mask_memory(mem->memory[i], + mem->type); + i460_pg_count[pg]++; + } + } + + return 0; +} + +static int intel_i460_remove_memory_kpc(agp_memory * mem, off_t pg_start, int type) +{ + int i, pg, start_pg, end_pg, start_offset, end_offset, idx; + int num_entries; + void *temp; + unsigned long paddr; + + temp = agp_bridge.current_size; + num_entries = A_SIZE_8(temp)->num_entries; + + /* Figure out what pg_start means in terms of our large GART pages */ + start_pg = pg_start / I460_KPAGES_PER_CPAGE; + start_offset = pg_start % I460_KPAGES_PER_CPAGE; + end_pg = (pg_start + mem->page_count - 1) / I460_KPAGES_PER_CPAGE; + end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_CPAGE; + + for (i = 0, pg = start_pg; pg <= end_pg; pg++) { + for (idx = ((pg == start_pg) ? start_offset : 0); + idx < ((pg == end_pg) ? (end_offset + 1) : I460_KPAGES_PER_CPAGE); + idx++, i++) + { + mem->memory[i] = 0; + i460_pg_detail[pg][idx] = 0; + i460_pg_count[pg]--; + } + + /* Free GART pages if they are unused */ + if (i460_pg_count[pg] == 0) { + paddr = agp_bridge.unmask_memory(agp_bridge.gatt_table[pg]); + agp_bridge.gatt_table[pg] = agp_bridge.scratch_page; + intel_i460_read_back(agp_bridge.gatt_table + pg); + intel_i460_free_large_page(pg, paddr); + } + } + return 0; +} + +/* Dummy routines to call the approriate {cpk,kpc} function */ + +static int intel_i460_insert_memory(agp_memory * mem, off_t pg_start, int type) +{ + if (intel_i460_cpk) + return intel_i460_insert_memory_cpk(mem, pg_start, type); + else + return intel_i460_insert_memory_kpc(mem, pg_start, type); +} + +static int intel_i460_remove_memory(agp_memory * mem, off_t pg_start, int type) +{ + if (intel_i460_cpk) + return intel_i460_remove_memory_cpk(mem, pg_start, type); + else + return intel_i460_remove_memory_kpc(mem, pg_start, type); +} + +/* + * If the kernel page size is smaller that the chipset page size, we don't + * want to allocate memory until we know where it is to be bound in the + * aperture (a multi-kernel-page alloc might fit inside of an already + * allocated GART page). Consequently, don't allocate or free anything + * if i460_cpk (meaning chipset pages per kernel page) isn't set. + * + * Let's just hope nobody counts on the allocated AGP memory being there + * before bind time (I don't think current drivers do)... + */ +static void * intel_i460_alloc_page(void) +{ + if (intel_i460_cpk) + return agp_generic_alloc_page(); + + /* Returning NULL would cause problems */ + /* AK: really dubious code. */ + return (void *)~0UL; +} + +static void intel_i460_destroy_page(void *page) +{ + if (intel_i460_cpk) + agp_generic_destroy_page(page); +} + +static struct gatt_mask intel_i460_masks[] = +{ + { + mask: INTEL_I460_GATT_VALID | INTEL_I460_GATT_COHERENT, + type: 0 + } +}; + +static unsigned long intel_i460_mask_memory(unsigned long addr, int type) +{ + /* Make sure the returned address is a valid GATT entry */ + return (agp_bridge.masks[0].mask + | (((addr & ~((1 << intel_i460_pageshift) - 1)) & 0xffffff000) >> 12)); +} + +static unsigned long intel_i460_unmask_memory(unsigned long addr) +{ + /* Turn a GATT entry into a physical address */ + return ((addr & 0xffffff) << 12); +} + +static struct aper_size_info_8 intel_i460_sizes[3] = +{ + /* + * The 32GB aperture is only available with a 4M GART page size. + * Due to the dynamic GART page size, we can't figure out page_order + * or num_entries until runtime. + */ + {32768, 0, 0, 4}, + {1024, 0, 0, 2}, + {256, 0, 0, 1} +}; + +int __init intel_i460_setup (struct pci_dev *pdev __attribute__((unused))) +{ + agp_bridge.masks = intel_i460_masks; + agp_bridge.aperture_sizes = (void *) intel_i460_sizes; + agp_bridge.size_type = U8_APER_SIZE; + agp_bridge.num_aperture_sizes = 3; + agp_bridge.dev_private_data = NULL; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = intel_i460_configure; + agp_bridge.fetch_size = intel_i460_fetch_size; + agp_bridge.cleanup = intel_i460_cleanup; + agp_bridge.tlb_flush = intel_i460_tlb_flush; + agp_bridge.mask_memory = intel_i460_mask_memory; + agp_bridge.unmask_memory = intel_i460_unmask_memory; + agp_bridge.agp_enable = agp_generic_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = intel_i460_create_gatt_table; + agp_bridge.free_gatt_table = intel_i460_free_gatt_table; + agp_bridge.insert_memory = intel_i460_insert_memory; + agp_bridge.remove_memory = intel_i460_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = intel_i460_alloc_page; + agp_bridge.agp_destroy_page = intel_i460_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 1; + return 0; +} + diff -Nru a/drivers/char/agp/agpgart_be-i810.c b/drivers/char/agp/agpgart_be-i810.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/agp/agpgart_be-i810.c Mon Jul 15 12:01:54 2002 @@ -0,0 +1,594 @@ +/* + * AGPGART module version 0.99 + * Copyright (C) 1999 Jeff Hartmann + * Copyright (C) 1999 Precision Insight, Inc. + * Copyright (C) 1999 Xi Graphics, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * TODO: + * - Allocate more than order 0 pages to avoid too much linear map splitting. + */ + +#include +#include +#include +#include +#include "agp.h" + +static struct aper_size_info_fixed intel_i810_sizes[] = +{ + {64, 16384, 4}, + /* The 32M mode still requires a 64k gatt */ + {32, 8192, 4} +}; + +#define AGP_DCACHE_MEMORY 1 +#define AGP_PHYS_MEMORY 2 + +static struct gatt_mask intel_i810_masks[] = +{ + {mask: I810_PTE_VALID, type: 0}, + {mask: (I810_PTE_VALID | I810_PTE_LOCAL), type: AGP_DCACHE_MEMORY}, + {mask: I810_PTE_VALID, type: 0} +}; + +static struct _intel_i810_private { + struct pci_dev *i810_dev; /* device one */ + volatile u8 *registers; + int num_dcache_entries; +} intel_i810_private; + +static int intel_i810_fetch_size(void) +{ + u32 smram_miscc; + struct aper_size_info_fixed *values; + + pci_read_config_dword(agp_bridge.dev, I810_SMRAM_MISCC, &smram_miscc); + values = A_SIZE_FIX(agp_bridge.aperture_sizes); + + if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) { + printk(KERN_WARNING PFX "i810 is disabled\n"); + return 0; + } + if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) { + agp_bridge.previous_size = + agp_bridge.current_size = (void *) (values + 1); + agp_bridge.aperture_size_idx = 1; + return values[1].size; + } else { + agp_bridge.previous_size = + agp_bridge.current_size = (void *) (values); + agp_bridge.aperture_size_idx = 0; + return values[0].size; + } + + return 0; +} + +static int intel_i810_configure(void) +{ + struct aper_size_info_fixed *current_size; + u32 temp; + int i; + + current_size = A_SIZE_FIX(agp_bridge.current_size); + + pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp); + temp &= 0xfff80000; + + intel_i810_private.registers = + (volatile u8 *) ioremap(temp, 128 * 4096); + + if ((INREG32(intel_i810_private.registers, I810_DRAM_CTL) + & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) { + /* This will need to be dynamically assigned */ + printk(KERN_INFO PFX "detected 4MB dedicated video ram.\n"); + intel_i810_private.num_dcache_entries = 1024; + } + pci_read_config_dword(intel_i810_private.i810_dev, I810_GMADDR, &temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + OUTREG32(intel_i810_private.registers, I810_PGETBL_CTL, + agp_bridge.gatt_bus_addr | I810_PGETBL_ENABLED); + CACHE_FLUSH(); + + if (agp_bridge.needs_scratch_page == TRUE) { + for (i = 0; i < current_size->num_entries; i++) { + OUTREG32(intel_i810_private.registers, + I810_PTE_BASE + (i * 4), + agp_bridge.scratch_page); + } + } + return 0; +} + +static void intel_i810_cleanup(void) +{ + OUTREG32(intel_i810_private.registers, I810_PGETBL_CTL, 0); + iounmap((void *) intel_i810_private.registers); +} + +static void intel_i810_tlbflush(agp_memory * mem) +{ + return; +} + +static void intel_i810_agp_enable(u32 mode) +{ + return; +} + +static int intel_i810_insert_entries(agp_memory * mem, off_t pg_start, + int type) +{ + int i, j, num_entries; + void *temp; + + temp = agp_bridge.current_size; + num_entries = A_SIZE_FIX(temp)->num_entries; + + if ((pg_start + mem->page_count) > num_entries) { + return -EINVAL; + } + for (j = pg_start; j < (pg_start + mem->page_count); j++) { + if (!PGE_EMPTY(agp_bridge.gatt_table[j])) { + return -EBUSY; + } + } + + if (type != 0 || mem->type != 0) { + if ((type == AGP_DCACHE_MEMORY) && + (mem->type == AGP_DCACHE_MEMORY)) { + /* special insert */ + CACHE_FLUSH(); + for (i = pg_start; + i < (pg_start + mem->page_count); i++) { + OUTREG32(intel_i810_private.registers, + I810_PTE_BASE + (i * 4), + (i * 4096) | I810_PTE_LOCAL | + I810_PTE_VALID); + } + CACHE_FLUSH(); + agp_bridge.tlb_flush(mem); + return 0; + } + if((type == AGP_PHYS_MEMORY) && + (mem->type == AGP_PHYS_MEMORY)) { + goto insert; + } + return -EINVAL; + } + +insert: + CACHE_FLUSH(); + for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { + OUTREG32(intel_i810_private.registers, + I810_PTE_BASE + (j * 4), mem->memory[i]); + } + CACHE_FLUSH(); + + agp_bridge.tlb_flush(mem); + return 0; +} + +static int intel_i810_remove_entries(agp_memory * mem, off_t pg_start, + int type) +{ + int i; + + for (i = pg_start; i < (mem->page_count + pg_start); i++) { + OUTREG32(intel_i810_private.registers, + I810_PTE_BASE + (i * 4), + agp_bridge.scratch_page); + } + + CACHE_FLUSH(); + agp_bridge.tlb_flush(mem); + return 0; +} + +static agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type) +{ + agp_memory *new; + + if (type == AGP_DCACHE_MEMORY) { + if (pg_count != intel_i810_private.num_dcache_entries) { + return NULL; + } + new = agp_create_memory(1); + + if (new == NULL) { + return NULL; + } + new->type = AGP_DCACHE_MEMORY; + new->page_count = pg_count; + new->num_scratch_pages = 0; + vfree(new->memory); + MOD_INC_USE_COUNT; + return new; + } + if(type == AGP_PHYS_MEMORY) { + void *addr; + /* The I810 requires a physical address to program + * it's mouse pointer into hardware. However the + * Xserver still writes to it through the agp + * aperture + */ + if (pg_count != 1) { + return NULL; + } + new = agp_create_memory(1); + + if (new == NULL) { + return NULL; + } + MOD_INC_USE_COUNT; + addr = agp_bridge.agp_alloc_page(); + + if (addr == NULL) { + /* Free this structure */ + agp_free_memory(new); + return NULL; + } + new->memory[0] = agp_bridge.mask_memory(virt_to_phys(addr), type); + new->page_count = 1; + new->num_scratch_pages = 1; + new->type = AGP_PHYS_MEMORY; + new->physical = virt_to_phys((void *) new->memory[0]); + return new; + } + + return NULL; +} + +static void intel_i810_free_by_type(agp_memory * curr) +{ + agp_free_key(curr->key); + if(curr->type == AGP_PHYS_MEMORY) { + agp_bridge.agp_destroy_page( + phys_to_virt(curr->memory[0])); + vfree(curr->memory); + } + kfree(curr); + MOD_DEC_USE_COUNT; +} + +static unsigned long intel_i810_mask_memory(unsigned long addr, int type) +{ + /* Type checking must be done elsewhere */ + return addr | agp_bridge.masks[type].mask; +} + +int __init intel_i810_setup(struct pci_dev *i810_dev) +{ + intel_i810_private.i810_dev = i810_dev; + + agp_bridge.masks = intel_i810_masks; + agp_bridge.num_of_masks = 2; + agp_bridge.aperture_sizes = (void *) intel_i810_sizes; + agp_bridge.size_type = FIXED_APER_SIZE; + agp_bridge.num_aperture_sizes = 2; + agp_bridge.dev_private_data = (void *) &intel_i810_private; + agp_bridge.needs_scratch_page = TRUE; + agp_bridge.configure = intel_i810_configure; + agp_bridge.fetch_size = intel_i810_fetch_size; + agp_bridge.cleanup = intel_i810_cleanup; + agp_bridge.tlb_flush = intel_i810_tlbflush; + agp_bridge.mask_memory = intel_i810_mask_memory; + agp_bridge.agp_enable = intel_i810_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = agp_generic_create_gatt_table; + agp_bridge.free_gatt_table = agp_generic_free_gatt_table; + agp_bridge.insert_memory = intel_i810_insert_entries; + agp_bridge.remove_memory = intel_i810_remove_entries; + agp_bridge.alloc_by_type = intel_i810_alloc_by_type; + agp_bridge.free_by_type = intel_i810_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; + + return 0; +} + +static struct aper_size_info_fixed intel_i830_sizes[] = +{ + {128, 32768, 5}, + /* The 64M mode still requires a 128k gatt */ + {64, 16384, 5} +}; + +static struct _intel_i830_private { + struct pci_dev *i830_dev; /* device one */ + volatile u8 *registers; + int gtt_entries; +} intel_i830_private; + +static void intel_i830_init_gtt_entries(void) +{ + u16 gmch_ctrl; + int gtt_entries; + u8 rdct; + static const int ddt[4] = { 0, 16, 32, 64 }; + + pci_read_config_word(agp_bridge.dev,I830_GMCH_CTRL,&gmch_ctrl); + + switch (gmch_ctrl & I830_GMCH_GMS_MASK) { + case I830_GMCH_GMS_STOLEN_512: + gtt_entries = KB(512) - KB(132); + printk(KERN_INFO PFX "detected %dK stolen memory.\n",gtt_entries / KB(1)); + break; + case I830_GMCH_GMS_STOLEN_1024: + gtt_entries = MB(1) - KB(132); + printk(KERN_INFO PFX "detected %dK stolen memory.\n",gtt_entries / KB(1)); + break; + case I830_GMCH_GMS_STOLEN_8192: + gtt_entries = MB(8) - KB(132); + printk(KERN_INFO PFX "detected %dK stolen memory.\n",gtt_entries / KB(1)); + break; + case I830_GMCH_GMS_LOCAL: + rdct = INREG8(intel_i830_private.registers,I830_RDRAM_CHANNEL_TYPE); + gtt_entries = (I830_RDRAM_ND(rdct) + 1) * MB(ddt[I830_RDRAM_DDT(rdct)]); + printk(KERN_INFO PFX "detected %dK local memory.\n",gtt_entries / KB(1)); + break; + default: + printk(KERN_INFO PFX "no video memory detected.\n"); + gtt_entries = 0; + break; + } + + gtt_entries /= KB(4); + + intel_i830_private.gtt_entries = gtt_entries; +} + +/* The intel i830 automatically initializes the agp aperture during POST. + * Use the memory already set aside for in the GTT. + */ +static int intel_i830_create_gatt_table(void) +{ + int page_order; + struct aper_size_info_fixed *size; + int num_entries; + u32 temp; + + size = agp_bridge.current_size; + page_order = size->page_order; + num_entries = size->num_entries; + agp_bridge.gatt_table_real = 0; + + pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp); + temp &= 0xfff80000; + + intel_i830_private.registers = (volatile u8 *) ioremap(temp,128 * 4096); + if (!intel_i830_private.registers) return (-ENOMEM); + + temp = INREG32(intel_i830_private.registers,I810_PGETBL_CTL) & 0xfffff000; + CACHE_FLUSH(); + + /* we have to call this as early as possible after the MMIO base address is known */ + intel_i830_init_gtt_entries(); + + agp_bridge.gatt_table = NULL; + + agp_bridge.gatt_bus_addr = temp; + + return(0); +} + +/* Return the gatt table to a sane state. Use the top of stolen + * memory for the GTT. + */ +static int intel_i830_free_gatt_table(void) +{ + return(0); +} + +static int intel_i830_fetch_size(void) +{ + u16 gmch_ctrl; + struct aper_size_info_fixed *values; + + pci_read_config_word(agp_bridge.dev,I830_GMCH_CTRL,&gmch_ctrl); + values = A_SIZE_FIX(agp_bridge.aperture_sizes); + + if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) { + agp_bridge.previous_size = agp_bridge.current_size = (void *) values; + agp_bridge.aperture_size_idx = 0; + return(values[0].size); + } else { + agp_bridge.previous_size = agp_bridge.current_size = (void *) values; + agp_bridge.aperture_size_idx = 1; + return(values[1].size); + } + + return(0); +} + +static int intel_i830_configure(void) +{ + struct aper_size_info_fixed *current_size; + u32 temp; + u16 gmch_ctrl; + int i; + + current_size = A_SIZE_FIX(agp_bridge.current_size); + + pci_read_config_dword(intel_i830_private.i830_dev,I810_GMADDR,&temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + + pci_read_config_word(agp_bridge.dev,I830_GMCH_CTRL,&gmch_ctrl); + gmch_ctrl |= I830_GMCH_ENABLED; + pci_write_config_word(agp_bridge.dev,I830_GMCH_CTRL,gmch_ctrl); + + OUTREG32(intel_i830_private.registers,I810_PGETBL_CTL,agp_bridge.gatt_bus_addr | I810_PGETBL_ENABLED); + CACHE_FLUSH(); + + if (agp_bridge.needs_scratch_page == TRUE) + for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) + OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge.scratch_page); + + return (0); +} + +static void intel_i830_cleanup(void) +{ + iounmap((void *) intel_i830_private.registers); +} + +static int intel_i830_insert_entries(agp_memory *mem,off_t pg_start,int type) +{ + int i,j,num_entries; + void *temp; + + temp = agp_bridge.current_size; + num_entries = A_SIZE_FIX(temp)->num_entries; + + if (pg_start < intel_i830_private.gtt_entries) { + printk (KERN_DEBUG "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n", + pg_start,intel_i830_private.gtt_entries); + + printk ("Trying to insert into local/stolen memory\n"); + return (-EINVAL); + } + + if ((pg_start + mem->page_count) > num_entries) + return (-EINVAL); + + /* The i830 can't check the GTT for entries since its read only, + * depend on the caller to make the correct offset decisions. + */ + + if ((type != 0 && type != AGP_PHYS_MEMORY) || + (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) + return (-EINVAL); + + CACHE_FLUSH(); + + for (i = 0, j = pg_start; i < mem->page_count; i++, j++) + OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (j * 4),mem->memory[i]); + + CACHE_FLUSH(); + + agp_bridge.tlb_flush(mem); + + return(0); +} + +static int intel_i830_remove_entries(agp_memory *mem,off_t pg_start,int type) +{ + int i; + + CACHE_FLUSH (); + + if (pg_start < intel_i830_private.gtt_entries) { + printk ("Trying to disable local/stolen memory\n"); + return (-EINVAL); + } + + for (i = pg_start; i < (mem->page_count + pg_start); i++) + OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge.scratch_page); + + CACHE_FLUSH(); + + agp_bridge.tlb_flush(mem); + + return (0); +} + +static agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type) +{ + agp_memory *nw; + + /* always return NULL for now */ + if (type == AGP_DCACHE_MEMORY) return(NULL); + + if (type == AGP_PHYS_MEMORY) { + void *addr; + + /* The i830 requires a physical address to program + * it's mouse pointer into hardware. However the + * Xserver still writes to it through the agp + * aperture + */ + + if (pg_count != 1) return(NULL); + + nw = agp_create_memory(1); + + if (nw == NULL) return(NULL); + + MOD_INC_USE_COUNT; + addr = agp_bridge.agp_alloc_page(); + if (addr == NULL) { + /* free this structure */ + agp_free_memory(nw); + return(NULL); + } + + nw->memory[0] = agp_bridge.mask_memory(virt_to_phys(addr),type); + nw->page_count = 1; + nw->num_scratch_pages = 1; + nw->type = AGP_PHYS_MEMORY; + nw->physical = virt_to_phys(addr); + return(nw); + } + + return(NULL); +} + +int __init intel_i830_setup(struct pci_dev *i830_dev) +{ + intel_i830_private.i830_dev = i830_dev; + + agp_bridge.masks = intel_i810_masks; + agp_bridge.num_of_masks = 3; + agp_bridge.aperture_sizes = (void *) intel_i830_sizes; + agp_bridge.size_type = FIXED_APER_SIZE; + agp_bridge.num_aperture_sizes = 2; + + agp_bridge.dev_private_data = (void *) &intel_i830_private; + agp_bridge.needs_scratch_page = TRUE; + + agp_bridge.configure = intel_i830_configure; + agp_bridge.fetch_size = intel_i830_fetch_size; + agp_bridge.cleanup = intel_i830_cleanup; + agp_bridge.tlb_flush = intel_i810_tlbflush; + agp_bridge.mask_memory = intel_i810_mask_memory; + agp_bridge.agp_enable = intel_i810_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + + agp_bridge.create_gatt_table = intel_i830_create_gatt_table; + agp_bridge.free_gatt_table = intel_i830_free_gatt_table; + + agp_bridge.insert_memory = intel_i830_insert_entries; + agp_bridge.remove_memory = intel_i830_remove_entries; + agp_bridge.alloc_by_type = intel_i830_alloc_by_type; + agp_bridge.free_by_type = intel_i810_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; + + return(0); +} + diff -Nru a/drivers/char/agp/agpgart_be-i8x0.c b/drivers/char/agp/agpgart_be-i8x0.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/agp/agpgart_be-i8x0.c Mon Jul 15 12:01:54 2002 @@ -0,0 +1,726 @@ +/* + * AGPGART module version 0.99 + * Copyright (C) 1999 Jeff Hartmann + * Copyright (C) 1999 Precision Insight, Inc. + * Copyright (C) 1999 Xi Graphics, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * TODO: + * - Allocate more than order 0 pages to avoid too much linear map splitting. + */ + +#include +#include +#include +#include +#include "agp.h" + + +static int intel_fetch_size(void) +{ + int i; + u16 temp; + struct aper_size_info_16 *values; + + pci_read_config_word(agp_bridge.dev, INTEL_APSIZE, &temp); + values = A_SIZE_16(agp_bridge.aperture_sizes); + + for (i = 0; i < agp_bridge.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 int intel_8xx_fetch_size(void) +{ + int i; + u8 temp; + struct aper_size_info_8 *values; + + pci_read_config_byte(agp_bridge.dev, INTEL_APSIZE, &temp); + + /* Intel 815 chipsets have a _weird_ APSIZE register with only + * one non-reserved bit, so mask the others out ... */ + if (agp_bridge.type == INTEL_I815) + temp &= (1 << 3) + + values = A_SIZE_8(agp_bridge.aperture_sizes); + + for (i = 0; i < agp_bridge.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 intel_tlbflush(agp_memory * mem) +{ + pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x2200); + pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x2280); +} + + +static void intel_8xx_tlbflush(agp_memory * mem) +{ + u32 temp; + pci_read_config_dword(agp_bridge.dev, INTEL_AGPCTRL, &temp); + pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, temp & ~(1 << 7)); + pci_read_config_dword(agp_bridge.dev, INTEL_AGPCTRL, &temp); + pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, temp | (1 << 7)); +} + + +static void intel_cleanup(void) +{ + u16 temp; + struct aper_size_info_16 *previous_size; + + previous_size = A_SIZE_16(agp_bridge.previous_size); + pci_read_config_word(agp_bridge.dev, INTEL_NBXCFG, &temp); + pci_write_config_word(agp_bridge.dev, INTEL_NBXCFG, temp & ~(1 << 9)); + pci_write_config_word(agp_bridge.dev, INTEL_APSIZE, + previous_size->size_value); +} + + +static void intel_8xx_cleanup(void) +{ + u16 temp; + struct aper_size_info_8 *previous_size; + + previous_size = A_SIZE_8(agp_bridge.previous_size); + pci_read_config_word(agp_bridge.dev, INTEL_NBXCFG, &temp); + pci_write_config_word(agp_bridge.dev, INTEL_NBXCFG, temp & ~(1 << 9)); + pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, + previous_size->size_value); +} + + +static int intel_configure(void) +{ + u32 temp; + u16 temp2; + struct aper_size_info_16 *current_size; + + current_size = A_SIZE_16(agp_bridge.current_size); + + /* aperture size */ + pci_write_config_word(agp_bridge.dev, INTEL_APSIZE, + current_size->size_value); + + /* address to map to */ + pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + + /* attbase - aperture base */ + pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE, + agp_bridge.gatt_bus_addr); + + /* agpctrl */ + pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x2280); + + /* paccfg/nbxcfg */ + pci_read_config_word(agp_bridge.dev, INTEL_NBXCFG, &temp2); + pci_write_config_word(agp_bridge.dev, INTEL_NBXCFG, + (temp2 & ~(1 << 10)) | (1 << 9)); + /* clear any possible error conditions */ + pci_write_config_byte(agp_bridge.dev, INTEL_ERRSTS + 1, 7); + return 0; +} + +static int intel_815_configure(void) +{ + u32 temp, addr; + u8 temp2; + struct aper_size_info_8 *current_size; + + current_size = A_SIZE_8(agp_bridge.current_size); + + /* aperture size */ + pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, + current_size->size_value); + + /* address to map to */ + pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + + /* attbase - aperture base */ + /* the Intel 815 chipset spec. says that bits 29-31 in the + * ATTBASE register are reserved -> try not to write them */ + if (agp_bridge.gatt_bus_addr & INTEL_815_ATTBASE_MASK) + panic("gatt bus addr too high"); + pci_read_config_dword(agp_bridge.dev, INTEL_ATTBASE, &addr); + addr &= INTEL_815_ATTBASE_MASK; + addr |= agp_bridge.gatt_bus_addr; + pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE, addr); + + /* agpctrl */ + pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000); + + /* apcont */ + pci_read_config_byte(agp_bridge.dev, INTEL_815_APCONT, &temp2); + pci_write_config_byte(agp_bridge.dev, INTEL_815_APCONT, temp2 | (1 << 1)); + + /* clear any possible error conditions */ + /* Oddness : this chipset seems to have no ERRSTS register ! */ + return 0; +} + +static void intel_820_tlbflush(agp_memory * mem) +{ + return; +} + +static void intel_820_cleanup(void) +{ + u8 temp; + struct aper_size_info_8 *previous_size; + + previous_size = A_SIZE_8(agp_bridge.previous_size); + pci_read_config_byte(agp_bridge.dev, INTEL_I820_RDCR, &temp); + pci_write_config_byte(agp_bridge.dev, INTEL_I820_RDCR, + temp & ~(1 << 1)); + pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, + previous_size->size_value); +} + + +static int intel_820_configure(void) +{ + u32 temp; + u8 temp2; + struct aper_size_info_8 *current_size; + + current_size = A_SIZE_8(agp_bridge.current_size); + + /* aperture size */ + pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, + current_size->size_value); + + /* address to map to */ + pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + + /* attbase - aperture base */ + pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE, + agp_bridge.gatt_bus_addr); + + /* agpctrl */ + pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000); + + /* global enable aperture access */ + /* This flag is not accessed through MCHCFG register as in */ + /* i850 chipset. */ + pci_read_config_byte(agp_bridge.dev, INTEL_I820_RDCR, &temp2); + pci_write_config_byte(agp_bridge.dev, INTEL_I820_RDCR, + temp2 | (1 << 1)); + /* clear any possible AGP-related error conditions */ + pci_write_config_word(agp_bridge.dev, INTEL_I820_ERRSTS, 0x001c); + return 0; +} + +static int intel_840_configure(void) +{ + u32 temp; + u16 temp2; + struct aper_size_info_8 *current_size; + + current_size = A_SIZE_8(agp_bridge.current_size); + + /* aperture size */ + pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, + current_size->size_value); + + /* address to map to */ + pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + + /* attbase - aperture base */ + pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE, + agp_bridge.gatt_bus_addr); + + /* agpctrl */ + pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000); + + /* mcgcfg */ + pci_read_config_word(agp_bridge.dev, INTEL_I840_MCHCFG, &temp2); + pci_write_config_word(agp_bridge.dev, INTEL_I840_MCHCFG, + temp2 | (1 << 9)); + /* clear any possible error conditions */ + pci_write_config_word(agp_bridge.dev, INTEL_I840_ERRSTS, 0xc000); + return 0; +} + +static int intel_845_configure(void) +{ + u32 temp; + u8 temp2; + struct aper_size_info_8 *current_size; + + current_size = A_SIZE_8(agp_bridge.current_size); + + /* aperture size */ + pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, + current_size->size_value); + + /* address to map to */ + pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + + /* attbase - aperture base */ + pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE, + agp_bridge.gatt_bus_addr); + + /* agpctrl */ + pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000); + + /* agpm */ + pci_read_config_byte(agp_bridge.dev, INTEL_I845_AGPM, &temp2); + pci_write_config_byte(agp_bridge.dev, INTEL_I845_AGPM, + temp2 | (1 << 1)); + /* clear any possible error conditions */ + pci_write_config_word(agp_bridge.dev, INTEL_I845_ERRSTS, 0x001c); + return 0; +} + +static int intel_850_configure(void) +{ + u32 temp; + u16 temp2; + struct aper_size_info_8 *current_size; + + current_size = A_SIZE_8(agp_bridge.current_size); + + /* aperture size */ + pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, + current_size->size_value); + + /* address to map to */ + pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + + /* attbase - aperture base */ + pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE, + agp_bridge.gatt_bus_addr); + + /* agpctrl */ + pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000); + + /* mcgcfg */ + pci_read_config_word(agp_bridge.dev, INTEL_I850_MCHCFG, &temp2); + pci_write_config_word(agp_bridge.dev, INTEL_I850_MCHCFG, + temp2 | (1 << 9)); + /* clear any possible AGP-related error conditions */ + pci_write_config_word(agp_bridge.dev, INTEL_I850_ERRSTS, 0x001c); + return 0; +} + +static int intel_860_configure(void) +{ + u32 temp; + u16 temp2; + struct aper_size_info_8 *current_size; + + current_size = A_SIZE_8(agp_bridge.current_size); + + /* aperture size */ + pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, + current_size->size_value); + + /* address to map to */ + pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + + /* attbase - aperture base */ + pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE, + agp_bridge.gatt_bus_addr); + + /* agpctrl */ + pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000); + + /* mcgcfg */ + pci_read_config_word(agp_bridge.dev, INTEL_I860_MCHCFG, &temp2); + pci_write_config_word(agp_bridge.dev, INTEL_I860_MCHCFG, + temp2 | (1 << 9)); + /* clear any possible AGP-related error conditions */ + pci_write_config_word(agp_bridge.dev, INTEL_I860_ERRSTS, 0xf700); + return 0; +} + +static int intel_830mp_configure(void) +{ + u32 temp; + u16 temp2; + struct aper_size_info_8 *current_size; + + current_size = A_SIZE_8(agp_bridge.current_size); + + /* aperture size */ + pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, + current_size->size_value); + + /* address to map to */ + pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + + /* attbase - aperture base */ + pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE, + agp_bridge.gatt_bus_addr); + + /* agpctrl */ + pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000); + + /* gmch */ + pci_read_config_word(agp_bridge.dev, INTEL_NBXCFG, &temp2); + pci_write_config_word(agp_bridge.dev, INTEL_NBXCFG, + temp2 | (1 << 9)); + /* clear any possible AGP-related error conditions */ + pci_write_config_word(agp_bridge.dev, INTEL_I830_ERRSTS, 0x1c); + return 0; +} + +static unsigned long intel_mask_memory(unsigned long addr, int type) +{ + /* Memory type is ignored */ + + return addr | agp_bridge.masks[0].mask; +} + +static void intel_resume(void) +{ + intel_configure(); +} + +/* Setup function */ +static struct gatt_mask intel_generic_masks[] = +{ + {mask: 0x00000017, type: 0} +}; + +static struct aper_size_info_8 intel_815_sizes[2] = +{ + {64, 16384, 4, 0}, + {32, 8192, 3, 8}, +}; + +static struct aper_size_info_8 intel_8xx_sizes[7] = +{ + {256, 65536, 6, 0}, + {128, 32768, 5, 32}, + {64, 16384, 4, 48}, + {32, 8192, 3, 56}, + {16, 4096, 2, 60}, + {8, 2048, 1, 62}, + {4, 1024, 0, 63} +}; + +static struct aper_size_info_16 intel_generic_sizes[7] = +{ + {256, 65536, 6, 0}, + {128, 32768, 5, 32}, + {64, 16384, 4, 48}, + {32, 8192, 3, 56}, + {16, 4096, 2, 60}, + {8, 2048, 1, 62}, + {4, 1024, 0, 63} +}; + +static struct aper_size_info_8 intel_830mp_sizes[4] = +{ + {256, 65536, 6, 0}, + {128, 32768, 5, 32}, + {64, 16384, 4, 48}, + {32, 8192, 3, 56} +}; + +int __init intel_generic_setup (struct pci_dev *pdev) +{ + agp_bridge.masks = intel_generic_masks; + agp_bridge.num_of_masks = 1; + agp_bridge.aperture_sizes = (void *) intel_generic_sizes; + agp_bridge.size_type = U16_APER_SIZE; + agp_bridge.num_aperture_sizes = 7; + agp_bridge.dev_private_data = NULL; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = intel_configure; + agp_bridge.fetch_size = intel_fetch_size; + agp_bridge.cleanup = intel_cleanup; + agp_bridge.tlb_flush = intel_tlbflush; + agp_bridge.mask_memory = intel_mask_memory; + agp_bridge.agp_enable = agp_generic_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = agp_generic_create_gatt_table; + agp_bridge.free_gatt_table = agp_generic_free_gatt_table; + agp_bridge.insert_memory = agp_generic_insert_memory; + agp_bridge.remove_memory = agp_generic_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = intel_resume; + agp_bridge.cant_use_aperture = 0; + + return 0; + + (void) pdev; /* unused */ +} + +int __init intel_815_setup (struct pci_dev *pdev) +{ + agp_bridge.masks = intel_generic_masks; + agp_bridge.num_of_masks = 1; + agp_bridge.aperture_sizes = (void *) intel_815_sizes; + agp_bridge.size_type = U8_APER_SIZE; + agp_bridge.num_aperture_sizes = 2; + agp_bridge.dev_private_data = NULL; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = intel_815_configure; + agp_bridge.fetch_size = intel_8xx_fetch_size; + agp_bridge.cleanup = intel_8xx_cleanup; + agp_bridge.tlb_flush = intel_8xx_tlbflush; + agp_bridge.mask_memory = intel_mask_memory; + agp_bridge.agp_enable = agp_generic_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = agp_generic_create_gatt_table; + agp_bridge.free_gatt_table = agp_generic_free_gatt_table; + agp_bridge.insert_memory = agp_generic_insert_memory; + agp_bridge.remove_memory = agp_generic_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; + + return 0; +} + + +int __init intel_820_setup (struct pci_dev *pdev) +{ + agp_bridge.masks = intel_generic_masks; + agp_bridge.num_of_masks = 1; + agp_bridge.aperture_sizes = (void *) intel_8xx_sizes; + agp_bridge.size_type = U8_APER_SIZE; + agp_bridge.num_aperture_sizes = 7; + agp_bridge.dev_private_data = NULL; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = intel_820_configure; + agp_bridge.fetch_size = intel_8xx_fetch_size; + agp_bridge.cleanup = intel_820_cleanup; + agp_bridge.tlb_flush = intel_820_tlbflush; + agp_bridge.mask_memory = intel_mask_memory; + agp_bridge.agp_enable = agp_generic_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = agp_generic_create_gatt_table; + agp_bridge.free_gatt_table = agp_generic_free_gatt_table; + agp_bridge.insert_memory = agp_generic_insert_memory; + agp_bridge.remove_memory = agp_generic_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; + + return 0; + + (void) pdev; /* unused */ +} + +int __init intel_830mp_setup (struct pci_dev *pdev) +{ + agp_bridge.masks = intel_generic_masks; + agp_bridge.num_of_masks = 1; + agp_bridge.aperture_sizes = (void *) intel_830mp_sizes; + agp_bridge.size_type = U8_APER_SIZE; + agp_bridge.num_aperture_sizes = 4; + agp_bridge.dev_private_data = NULL; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = intel_830mp_configure; + agp_bridge.fetch_size = intel_8xx_fetch_size; + agp_bridge.cleanup = intel_8xx_cleanup; + agp_bridge.tlb_flush = intel_8xx_tlbflush; + agp_bridge.mask_memory = intel_mask_memory; + agp_bridge.agp_enable = agp_generic_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = agp_generic_create_gatt_table; + agp_bridge.free_gatt_table = agp_generic_free_gatt_table; + agp_bridge.insert_memory = agp_generic_insert_memory; + agp_bridge.remove_memory = agp_generic_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; + + return 0; + + (void) pdev; /* unused */ +} + +int __init intel_840_setup (struct pci_dev *pdev) +{ + agp_bridge.masks = intel_generic_masks; + agp_bridge.num_of_masks = 1; + agp_bridge.aperture_sizes = (void *) intel_8xx_sizes; + agp_bridge.size_type = U8_APER_SIZE; + agp_bridge.num_aperture_sizes = 7; + agp_bridge.dev_private_data = NULL; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = intel_840_configure; + agp_bridge.fetch_size = intel_8xx_fetch_size; + agp_bridge.cleanup = intel_8xx_cleanup; + agp_bridge.tlb_flush = intel_8xx_tlbflush; + agp_bridge.mask_memory = intel_mask_memory; + agp_bridge.agp_enable = agp_generic_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = agp_generic_create_gatt_table; + agp_bridge.free_gatt_table = agp_generic_free_gatt_table; + agp_bridge.insert_memory = agp_generic_insert_memory; + agp_bridge.remove_memory = agp_generic_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; + + return 0; + + (void) pdev; /* unused */ +} + +int __init intel_845_setup (struct pci_dev *pdev) +{ + agp_bridge.masks = intel_generic_masks; + agp_bridge.num_of_masks = 1; + agp_bridge.aperture_sizes = (void *) intel_8xx_sizes; + agp_bridge.size_type = U8_APER_SIZE; + agp_bridge.num_aperture_sizes = 7; + agp_bridge.dev_private_data = NULL; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = intel_845_configure; + agp_bridge.fetch_size = intel_8xx_fetch_size; + agp_bridge.cleanup = intel_8xx_cleanup; + agp_bridge.tlb_flush = intel_8xx_tlbflush; + agp_bridge.mask_memory = intel_mask_memory; + agp_bridge.agp_enable = agp_generic_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = agp_generic_create_gatt_table; + agp_bridge.free_gatt_table = agp_generic_free_gatt_table; + agp_bridge.insert_memory = agp_generic_insert_memory; + agp_bridge.remove_memory = agp_generic_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; + + return 0; + + (void) pdev; /* unused */ +} + +int __init intel_850_setup (struct pci_dev *pdev) +{ + agp_bridge.masks = intel_generic_masks; + agp_bridge.num_of_masks = 1; + agp_bridge.aperture_sizes = (void *) intel_8xx_sizes; + agp_bridge.size_type = U8_APER_SIZE; + agp_bridge.num_aperture_sizes = 7; + agp_bridge.dev_private_data = NULL; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = intel_850_configure; + agp_bridge.fetch_size = intel_8xx_fetch_size; + agp_bridge.cleanup = intel_8xx_cleanup; + agp_bridge.tlb_flush = intel_8xx_tlbflush; + agp_bridge.mask_memory = intel_mask_memory; + agp_bridge.agp_enable = agp_generic_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = agp_generic_create_gatt_table; + agp_bridge.free_gatt_table = agp_generic_free_gatt_table; + agp_bridge.insert_memory = agp_generic_insert_memory; + agp_bridge.remove_memory = agp_generic_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; + + return 0; + + (void) pdev; /* unused */ +} + +int __init intel_860_setup (struct pci_dev *pdev) +{ + agp_bridge.masks = intel_generic_masks; + agp_bridge.num_of_masks = 1; + agp_bridge.aperture_sizes = (void *) intel_8xx_sizes; + agp_bridge.size_type = U8_APER_SIZE; + agp_bridge.num_aperture_sizes = 7; + agp_bridge.dev_private_data = NULL; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = intel_860_configure; + agp_bridge.fetch_size = intel_8xx_fetch_size; + agp_bridge.cleanup = intel_8xx_cleanup; + agp_bridge.tlb_flush = intel_8xx_tlbflush; + agp_bridge.mask_memory = intel_mask_memory; + agp_bridge.agp_enable = agp_generic_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = agp_generic_create_gatt_table; + agp_bridge.free_gatt_table = agp_generic_free_gatt_table; + agp_bridge.insert_memory = agp_generic_insert_memory; + agp_bridge.remove_memory = agp_generic_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; + + return 0; + + (void) pdev; /* unused */ +} + diff -Nru a/drivers/char/agp/agpgart_be-sis.c b/drivers/char/agp/agpgart_be-sis.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/agp/agpgart_be-sis.c Mon Jul 15 12:01:54 2002 @@ -0,0 +1,142 @@ +/* + * AGPGART module version 0.99 + * Copyright (C) 1999 Jeff Hartmann + * Copyright (C) 1999 Precision Insight, Inc. + * Copyright (C) 1999 Xi Graphics, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * TODO: + * - Allocate more than order 0 pages to avoid too much linear map splitting. + */ + +#include +#include +#include +#include +#include "agp.h" + +static int sis_fetch_size(void) +{ + u8 temp_size; + int i; + struct aper_size_info_8 *values; + + pci_read_config_byte(agp_bridge.dev, SIS_APSIZE, &temp_size); + values = A_SIZE_8(agp_bridge.aperture_sizes); + for (i = 0; i < agp_bridge.num_aperture_sizes; i++) { + if ((temp_size == values[i].size_value) || + ((temp_size & ~(0x03)) == + (values[i].size_value & ~(0x03)))) { + 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 sis_tlbflush(agp_memory * mem) +{ + pci_write_config_byte(agp_bridge.dev, SIS_TLBFLUSH, 0x02); +} + +static int sis_configure(void) +{ + u32 temp; + struct aper_size_info_8 *current_size; + + current_size = A_SIZE_8(agp_bridge.current_size); + pci_write_config_byte(agp_bridge.dev, SIS_TLBCNTRL, 0x05); + pci_read_config_dword(agp_bridge.dev, SIS_APBASE, &temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + pci_write_config_dword(agp_bridge.dev, SIS_ATTBASE, + agp_bridge.gatt_bus_addr); + pci_write_config_byte(agp_bridge.dev, SIS_APSIZE, + current_size->size_value); + return 0; +} + +static void sis_cleanup(void) +{ + struct aper_size_info_8 *previous_size; + + previous_size = A_SIZE_8(agp_bridge.previous_size); + pci_write_config_byte(agp_bridge.dev, SIS_APSIZE, + (previous_size->size_value & ~(0x03))); +} + +static unsigned long sis_mask_memory(unsigned long addr, int type) +{ + /* Memory type is ignored */ + + return addr | agp_bridge.masks[0].mask; +} + +static struct aper_size_info_8 sis_generic_sizes[7] = +{ + {256, 65536, 6, 99}, + {128, 32768, 5, 83}, + {64, 16384, 4, 67}, + {32, 8192, 3, 51}, + {16, 4096, 2, 35}, + {8, 2048, 1, 19}, + {4, 1024, 0, 3} +}; + +static struct gatt_mask sis_generic_masks[] = +{ + {mask: 0x00000000, type: 0} +}; + +int __init sis_generic_setup (struct pci_dev *pdev) +{ + agp_bridge.masks = sis_generic_masks; + agp_bridge.num_of_masks = 1; + agp_bridge.aperture_sizes = (void *) sis_generic_sizes; + agp_bridge.size_type = U8_APER_SIZE; + agp_bridge.num_aperture_sizes = 7; + agp_bridge.dev_private_data = NULL; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = sis_configure; + agp_bridge.fetch_size = sis_fetch_size; + agp_bridge.cleanup = sis_cleanup; + agp_bridge.tlb_flush = sis_tlbflush; + agp_bridge.mask_memory = sis_mask_memory; + agp_bridge.agp_enable = agp_generic_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = agp_generic_create_gatt_table; + agp_bridge.free_gatt_table = agp_generic_free_gatt_table; + agp_bridge.insert_memory = agp_generic_insert_memory; + agp_bridge.remove_memory = agp_generic_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; + + return 0; +} + diff -Nru a/drivers/char/agp/agpgart_be-sworks.c b/drivers/char/agp/agpgart_be-sworks.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/agp/agpgart_be-sworks.c Mon Jul 15 12:01:54 2002 @@ -0,0 +1,626 @@ +/* + * AGPGART module version 0.99 + * Copyright (C) 1999 Jeff Hartmann + * Copyright (C) 1999 Precision Insight, Inc. + * Copyright (C) 1999 Xi Graphics, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * TODO: + * - Allocate more than order 0 pages to avoid too much linear map splitting. + */ + +#include +#include +#include +#include +#include "agp.h" + +struct serverworks_page_map { + unsigned long *real; + unsigned long *remapped; +}; + +static struct _serverworks_private { + struct pci_dev *svrwrks_dev; /* device one */ + volatile u8 *registers; + struct serverworks_page_map **gatt_pages; + int num_tables; + struct serverworks_page_map scratch_dir; + + int gart_addr_ofs; + int mm_addr_ofs; +} serverworks_private; + +static int serverworks_create_page_map(struct serverworks_page_map *page_map) +{ + int i; + + page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL); + if (page_map->real == NULL) { + return -ENOMEM; + } + SetPageReserved(virt_to_page(page_map->real)); + CACHE_FLUSH(); + 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)); + free_page((unsigned long) page_map->real); + page_map->real = NULL; + return -ENOMEM; + } + CACHE_FLUSH(); + + for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { + page_map->remapped[i] = agp_bridge.scratch_page; + } + + return 0; +} + +static void serverworks_free_page_map(struct serverworks_page_map *page_map) +{ + iounmap(page_map->remapped); + ClearPageReserved(virt_to_page(page_map->real)); + free_page((unsigned long) page_map->real); +} + +static void serverworks_free_gatt_pages(void) +{ + int i; + struct serverworks_page_map **tables; + struct serverworks_page_map *entry; + + tables = serverworks_private.gatt_pages; + for(i = 0; i < serverworks_private.num_tables; i++) { + entry = tables[i]; + if (entry != NULL) { + if (entry->real != NULL) { + serverworks_free_page_map(entry); + } + kfree(entry); + } + } + kfree(tables); +} + +static int serverworks_create_gatt_pages(int nr_tables) +{ + struct serverworks_page_map **tables; + struct serverworks_page_map *entry; + int retval = 0; + int i; + + tables = kmalloc((nr_tables + 1) * sizeof(struct serverworks_page_map *), + GFP_KERNEL); + if (tables == NULL) { + return -ENOMEM; + } + memset(tables, 0, sizeof(struct serverworks_page_map *) * (nr_tables + 1)); + for (i = 0; i < nr_tables; i++) { + entry = kmalloc(sizeof(struct serverworks_page_map), GFP_KERNEL); + if (entry == NULL) { + retval = -ENOMEM; + break; + } + memset(entry, 0, sizeof(struct serverworks_page_map)); + tables[i] = entry; + retval = serverworks_create_page_map(entry); + if (retval != 0) break; + } + serverworks_private.num_tables = nr_tables; + serverworks_private.gatt_pages = tables; + + if (retval != 0) serverworks_free_gatt_pages(); + + return retval; +} + +#define SVRWRKS_GET_GATT(addr) (serverworks_private.gatt_pages[\ + GET_PAGE_DIR_IDX(addr)]->remapped) + +#ifndef GET_PAGE_DIR_OFF +#define GET_PAGE_DIR_OFF(addr) (addr >> 22) +#endif + +#ifndef GET_PAGE_DIR_IDX +#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \ + GET_PAGE_DIR_OFF(agp_bridge.gart_bus_addr)) +#endif + +#ifndef GET_GATT_OFF +#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) +#endif + +static int serverworks_create_gatt_table(void) +{ + struct aper_size_info_lvl2 *value; + struct serverworks_page_map page_dir; + int retval; + u32 temp; + int i; + + value = A_SIZE_LVL2(agp_bridge.current_size); + retval = serverworks_create_page_map(&page_dir); + if (retval != 0) { + return retval; + } + retval = serverworks_create_page_map(&serverworks_private.scratch_dir); + if (retval != 0) { + serverworks_free_page_map(&page_dir); + return retval; + } + /* Create a fake scratch directory */ + for(i = 0; i < 1024; i++) { + serverworks_private.scratch_dir.remapped[i] = (unsigned long) agp_bridge.scratch_page; + page_dir.remapped[i] = + virt_to_phys(serverworks_private.scratch_dir.real); + page_dir.remapped[i] |= 0x00000001; + } + + retval = serverworks_create_gatt_pages(value->num_entries / 1024); + if (retval != 0) { + serverworks_free_page_map(&page_dir); + serverworks_free_page_map(&serverworks_private.scratch_dir); + return retval; + } + + agp_bridge.gatt_table_real = page_dir.real; + agp_bridge.gatt_table = page_dir.remapped; + agp_bridge.gatt_bus_addr = virt_to_phys(page_dir.real); + + /* 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, + serverworks_private.gart_addr_ofs, + &temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + + /* Calculate the agp offset */ + + for(i = 0; i < value->num_entries / 1024; i++) { + page_dir.remapped[i] = + virt_to_phys(serverworks_private.gatt_pages[i]->real); + page_dir.remapped[i] |= 0x00000001; + } + + return 0; +} + +static int serverworks_free_gatt_table(void) +{ + struct serverworks_page_map page_dir; + + page_dir.real = agp_bridge.gatt_table_real; + page_dir.remapped = agp_bridge.gatt_table; + + serverworks_free_gatt_pages(); + serverworks_free_page_map(&page_dir); + serverworks_free_page_map(&serverworks_private.scratch_dir); + return 0; +} + +static int serverworks_fetch_size(void) +{ + int i; + u32 temp; + u32 temp2; + struct aper_size_info_lvl2 *values; + + values = A_SIZE_LVL2(agp_bridge.aperture_sizes); + pci_read_config_dword(agp_bridge.dev, + serverworks_private.gart_addr_ofs, + &temp); + pci_write_config_dword(agp_bridge.dev, + serverworks_private.gart_addr_ofs, + SVWRKS_SIZE_MASK); + pci_read_config_dword(agp_bridge.dev, + serverworks_private.gart_addr_ofs, + &temp2); + pci_write_config_dword(agp_bridge.dev, + serverworks_private.gart_addr_ofs, + temp); + temp2 &= SVWRKS_SIZE_MASK; + + for (i = 0; i < agp_bridge.num_aperture_sizes; i++) { + if (temp2 == 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 int serverworks_configure(void) +{ + struct aper_size_info_lvl2 *current_size; + u32 temp; + u8 enable_reg; + u8 cap_ptr; + u32 cap_id; + u16 cap_reg; + + current_size = A_SIZE_LVL2(agp_bridge.current_size); + + /* Get the memory mapped registers */ + pci_read_config_dword(agp_bridge.dev, + serverworks_private.mm_addr_ofs, + &temp); + temp = (temp & PCI_BASE_ADDRESS_MEM_MASK); + serverworks_private.registers = (volatile u8 *) ioremap(temp, 4096); + + OUTREG8(serverworks_private.registers, SVWRKS_GART_CACHE, 0x0a); + + OUTREG32(serverworks_private.registers, SVWRKS_GATTBASE, + agp_bridge.gatt_bus_addr); + + cap_reg = INREG16(serverworks_private.registers, SVWRKS_COMMAND); + cap_reg &= ~0x0007; + cap_reg |= 0x4; + OUTREG16(serverworks_private.registers, SVWRKS_COMMAND, cap_reg); + + pci_read_config_byte(serverworks_private.svrwrks_dev, + SVWRKS_AGP_ENABLE, &enable_reg); + enable_reg |= 0x1; /* Agp Enable bit */ + pci_write_config_byte(serverworks_private.svrwrks_dev, + SVWRKS_AGP_ENABLE, enable_reg); + agp_bridge.tlb_flush(NULL); + + pci_read_config_byte(serverworks_private.svrwrks_dev, 0x34, &cap_ptr); + if (cap_ptr != 0x00) { + do { + pci_read_config_dword(serverworks_private.svrwrks_dev, + cap_ptr, &cap_id); + + if ((cap_id & 0xff) != 0x02) + cap_ptr = (cap_id >> 8) & 0xff; + } + while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00)); + } + agp_bridge.capndx = cap_ptr; + + /* Fill in the mode register */ + pci_read_config_dword(serverworks_private.svrwrks_dev, + agp_bridge.capndx + 4, + &agp_bridge.mode); + + pci_read_config_byte(agp_bridge.dev, + SVWRKS_CACHING, + &enable_reg); + enable_reg &= ~0x3; + pci_write_config_byte(agp_bridge.dev, + SVWRKS_CACHING, + enable_reg); + + pci_read_config_byte(agp_bridge.dev, + SVWRKS_FEATURE, + &enable_reg); + enable_reg |= (1<<6); + pci_write_config_byte(agp_bridge.dev, + SVWRKS_FEATURE, + enable_reg); + + return 0; +} + +static void serverworks_cleanup(void) +{ + iounmap((void *) serverworks_private.registers); +} + +/* + * This routine could be implemented by taking the addresses + * written to the GATT, and flushing them individually. However + * currently it just flushes the whole table. Which is probably + * more efficent, since agp_memory blocks can be a large number of + * entries. + */ + +static void serverworks_tlbflush(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 "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 "TLB flush took more" + "then 3 seconds\n"); + } + } +} + +static unsigned long serverworks_mask_memory(unsigned long addr, int type) +{ + /* Only type 0 is supported by the serverworks chipsets */ + + return addr | agp_bridge.masks[0].mask; +} + +static int serverworks_insert_memory(agp_memory * mem, + off_t pg_start, int type) +{ + int i, j, num_entries; + unsigned long *cur_gatt; + unsigned long addr; + + num_entries = A_SIZE_LVL2(agp_bridge.current_size)->num_entries; + + if (type != 0 || mem->type != 0) { + return -EINVAL; + } + 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 = SVRWRKS_GET_GATT(addr); + if (!PGE_EMPTY(cur_gatt[GET_GATT_OFF(addr)])) { + return -EBUSY; + } + j++; + } + + if (mem->is_flushed == FALSE) { + CACHE_FLUSH(); + mem->is_flushed = TRUE; + } + + for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { + addr = (j * PAGE_SIZE) + agp_bridge.gart_bus_addr; + cur_gatt = SVRWRKS_GET_GATT(addr); + cur_gatt[GET_GATT_OFF(addr)] = mem->memory[i]; + } + agp_bridge.tlb_flush(mem); + return 0; +} + +static int serverworks_remove_memory(agp_memory * mem, off_t pg_start, + int type) +{ + int i; + unsigned long *cur_gatt; + unsigned long addr; + + if (type != 0 || mem->type != 0) { + return -EINVAL; + } + + CACHE_FLUSH(); + agp_bridge.tlb_flush(mem); + + for (i = pg_start; i < (mem->page_count + pg_start); i++) { + addr = (i * PAGE_SIZE) + agp_bridge.gart_bus_addr; + cur_gatt = SVRWRKS_GET_GATT(addr); + cur_gatt[GET_GATT_OFF(addr)] = + (unsigned long) agp_bridge.scratch_page; + } + + agp_bridge.tlb_flush(mem); + return 0; +} + +static struct gatt_mask serverworks_masks[] = +{ + {mask: 0x00000001, type: 0} +}; + +static struct aper_size_info_lvl2 serverworks_sizes[7] = +{ + {2048, 524288, 0x80000000}, + {1024, 262144, 0xc0000000}, + {512, 131072, 0xe0000000}, + {256, 65536, 0xf0000000}, + {128, 32768, 0xf8000000}, + {64, 16384, 0xfc000000}, + {32, 8192, 0xfe000000} +}; + +static void serverworks_agp_enable(u32 mode) +{ + struct pci_dev *device = NULL; + u32 command, scratch, cap_id; + u8 cap_ptr; + + pci_read_config_dword(serverworks_private.svrwrks_dev, + agp_bridge.capndx + 4, + &command); + + /* + * PASS1: go throu all devices that claim to be + * AGP devices and collect their data. + */ + + + pci_for_each_dev(device) { + cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); + if (cap_ptr != 0x00) { + do { + pci_read_config_dword(device, + cap_ptr, &cap_id); + + if ((cap_id & 0xff) != 0x02) + cap_ptr = (cap_id >> 8) & 0xff; + } + while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00)); + } + if (cap_ptr != 0x00) { + /* + * Ok, here we have a AGP device. Disable impossible + * settings, and adjust the readqueue to the minimum. + */ + + pci_read_config_dword(device, cap_ptr + 4, &scratch); + + /* adjust RQ depth */ + command = + ((command & ~0xff000000) | + min_t(u32, (mode & 0xff000000), + min_t(u32, (command & 0xff000000), + (scratch & 0xff000000)))); + + /* disable SBA if it's not supported */ + if (!((command & 0x00000200) && + (scratch & 0x00000200) && + (mode & 0x00000200))) + command &= ~0x00000200; + + /* disable FW */ + command &= ~0x00000010; + + command &= ~0x00000008; + + if (!((command & 4) && + (scratch & 4) && + (mode & 4))) + command &= ~0x00000004; + + if (!((command & 2) && + (scratch & 2) && + (mode & 2))) + command &= ~0x00000002; + + if (!((command & 1) && + (scratch & 1) && + (mode & 1))) + command &= ~0x00000001; + } + } + /* + * PASS2: Figure out the 4X/2X/1X setting and enable the + * target (our motherboard chipset). + */ + + if (command & 4) { + command &= ~3; /* 4X */ + } + if (command & 2) { + command &= ~5; /* 2X */ + } + if (command & 1) { + command &= ~6; /* 1X */ + } + command |= 0x00000100; + + pci_write_config_dword(serverworks_private.svrwrks_dev, + agp_bridge.capndx + 8, + command); + + /* + * PASS3: Go throu all AGP devices and update the + * command registers. + */ + + pci_for_each_dev(device) { + cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); + if (cap_ptr != 0x00) + pci_write_config_dword(device, cap_ptr + 8, command); + } +} + +int __init serverworks_setup (struct pci_dev *pdev) +{ + u32 temp; + u32 temp2; + + serverworks_private.svrwrks_dev = pdev; + + agp_bridge.masks = serverworks_masks; + agp_bridge.num_of_masks = 1; + agp_bridge.aperture_sizes = (void *) serverworks_sizes; + agp_bridge.size_type = LVL2_APER_SIZE; + agp_bridge.num_aperture_sizes = 7; + agp_bridge.dev_private_data = (void *) &serverworks_private; + agp_bridge.needs_scratch_page = TRUE; + agp_bridge.configure = serverworks_configure; + agp_bridge.fetch_size = serverworks_fetch_size; + agp_bridge.cleanup = serverworks_cleanup; + agp_bridge.tlb_flush = serverworks_tlbflush; + agp_bridge.mask_memory = serverworks_mask_memory; + agp_bridge.agp_enable = serverworks_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = serverworks_create_gatt_table; + agp_bridge.free_gatt_table = serverworks_free_gatt_table; + agp_bridge.insert_memory = serverworks_insert_memory; + agp_bridge.remove_memory = serverworks_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; + + pci_read_config_dword(agp_bridge.dev, + SVWRKS_APSIZE, + &temp); + + serverworks_private.gart_addr_ofs = 0x10; + + if(temp & PCI_BASE_ADDRESS_MEM_TYPE_64) { + pci_read_config_dword(agp_bridge.dev, + SVWRKS_APSIZE + 4, + &temp2); + if(temp2 != 0) { + printk("Detected 64 bit aperture address, but top " + "bits are not zero. Disabling agp\n"); + return -ENODEV; + } + serverworks_private.mm_addr_ofs = 0x18; + } else { + serverworks_private.mm_addr_ofs = 0x14; + } + + pci_read_config_dword(agp_bridge.dev, + serverworks_private.mm_addr_ofs, + &temp); + if(temp & PCI_BASE_ADDRESS_MEM_TYPE_64) { + pci_read_config_dword(agp_bridge.dev, + serverworks_private.mm_addr_ofs + 4, + &temp2); + if(temp2 != 0) { + printk("Detected 64 bit MMIO address, but top " + "bits are not zero. Disabling agp\n"); + return -ENODEV; + } + } + + return 0; +} + diff -Nru a/drivers/char/agp/agpgart_be-via.c b/drivers/char/agp/agpgart_be-via.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/agp/agpgart_be-via.c Mon Jul 15 12:01:54 2002 @@ -0,0 +1,151 @@ +/* + * AGPGART module version 0.99 + * Copyright (C) 1999 Jeff Hartmann + * Copyright (C) 1999 Precision Insight, Inc. + * Copyright (C) 1999 Xi Graphics, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * TODO: + * - Allocate more than order 0 pages to avoid too much linear map splitting. + */ +#include +#include +#include +#include +#include +#include +#include "agp.h" + + +static int via_fetch_size(void) +{ + int i; + u8 temp; + struct aper_size_info_8 *values; + + values = A_SIZE_8(agp_bridge.aperture_sizes); + pci_read_config_byte(agp_bridge.dev, VIA_APSIZE, &temp); + for (i = 0; i < agp_bridge.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 int via_configure(void) +{ + u32 temp; + struct aper_size_info_8 *current_size; + + current_size = A_SIZE_8(agp_bridge.current_size); + /* aperture size */ + pci_write_config_byte(agp_bridge.dev, VIA_APSIZE, + current_size->size_value); + /* address to map too */ + pci_read_config_dword(agp_bridge.dev, VIA_APBASE, &temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + + /* GART control register */ + pci_write_config_dword(agp_bridge.dev, VIA_GARTCTRL, 0x0000000f); + + /* attbase - aperture GATT base */ + pci_write_config_dword(agp_bridge.dev, VIA_ATTBASE, + (agp_bridge.gatt_bus_addr & 0xfffff000) | 3); + return 0; +} + +static void via_cleanup(void) +{ + struct aper_size_info_8 *previous_size; + + previous_size = A_SIZE_8(agp_bridge.previous_size); + pci_write_config_byte(agp_bridge.dev, VIA_APSIZE, + previous_size->size_value); + /* Do not disable by writing 0 to VIA_ATTBASE, it screws things up + * during reinitialization. + */ +} + +static void via_tlbflush(agp_memory * mem) +{ + pci_write_config_dword(agp_bridge.dev, VIA_GARTCTRL, 0x0000008f); + pci_write_config_dword(agp_bridge.dev, VIA_GARTCTRL, 0x0000000f); +} + +static unsigned long via_mask_memory(unsigned long addr, int type) +{ + /* Memory type is ignored */ + + return addr | agp_bridge.masks[0].mask; +} + +static struct aper_size_info_8 via_generic_sizes[7] = +{ + {256, 65536, 6, 0}, + {128, 32768, 5, 128}, + {64, 16384, 4, 192}, + {32, 8192, 3, 224}, + {16, 4096, 2, 240}, + {8, 2048, 1, 248}, + {4, 1024, 0, 252} +}; + +static struct gatt_mask via_generic_masks[] = +{ + {mask: 0x00000000, type: 0} +}; + +int __init via_generic_setup (struct pci_dev *pdev) +{ + agp_bridge.masks = via_generic_masks; + agp_bridge.num_of_masks = 1; + agp_bridge.aperture_sizes = (void *) via_generic_sizes; + agp_bridge.size_type = U8_APER_SIZE; + agp_bridge.num_aperture_sizes = 7; + agp_bridge.dev_private_data = NULL; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = via_configure; + agp_bridge.fetch_size = via_fetch_size; + agp_bridge.cleanup = via_cleanup; + agp_bridge.tlb_flush = via_tlbflush; + agp_bridge.mask_memory = via_mask_memory; + agp_bridge.agp_enable = agp_generic_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = agp_generic_create_gatt_table; + agp_bridge.free_gatt_table = agp_generic_free_gatt_table; + agp_bridge.insert_memory = agp_generic_insert_memory; + agp_bridge.remove_memory = agp_generic_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 0; + + return 0; + + (void) pdev; /* unused */ +} diff -Nru a/drivers/char/agp/agpgart_be.c b/drivers/char/agp/agpgart_be.c --- a/drivers/char/agp/agpgart_be.c Mon Jul 15 12:01:54 2002 +++ b/drivers/char/agp/agpgart_be.c Mon Jul 15 12:01:54 2002 @@ -26,27 +26,12 @@ * - Allocate more than order 0 pages to avoid too much linear map splitting. */ #include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include #include #include -#include -#include -#include -#include -#include - #include #include "agp.h" @@ -62,34 +47,14 @@ EXPORT_SYMBOL(agp_backend_acquire); EXPORT_SYMBOL(agp_backend_release); -static struct agp_bridge_data agp_bridge; +struct agp_bridge_data agp_bridge = { type: NOT_SUPPORTED }; static int agp_try_unsupported __initdata = 0; -#ifdef CONFIG_SMP -static void ipi_handler(void *null) -{ - flush_agp_cache(); -} - -static void smp_flush_cache(void) -{ - if (smp_call_function(ipi_handler, NULL, 1, 1) != 0) - panic(PFX "timed out waiting for the other CPUs!\n"); - flush_agp_cache(); -} -#define global_cache_flush smp_flush_cache -#else /* CONFIG_SMP */ -static void global_cache_flush(void) -{ - flush_agp_cache(); -} -#endif /* !CONFIG_SMP */ - int agp_backend_acquire(void) { - if (agp_bridge.type == NOT_SUPPORTED) { + if (agp_bridge.type == NOT_SUPPORTED) return -EINVAL; - } + atomic_inc(&agp_bridge.agp_in_use); if (atomic_read(&agp_bridge.agp_in_use) != 1) { @@ -102,9 +67,9 @@ void agp_backend_release(void) { - if (agp_bridge.type == NOT_SUPPORTED) { + if (agp_bridge.type == NOT_SUPPORTED) return; - } + atomic_dec(&agp_bridge.agp_in_use); MOD_DEC_USE_COUNT; } @@ -116,15 +81,14 @@ */ -static void agp_free_key(int key) +void agp_free_key(int key) { - if (key < 0) { + if (key < 0) return; - } - if (key < MAXKEY) { + + if (key < MAXKEY) clear_bit(key, agp_bridge.key_list); - } } static int agp_get_key(void) @@ -139,15 +103,15 @@ return -1; } -static agp_memory *agp_create_memory(int scratch_pages) +agp_memory *agp_create_memory(int scratch_pages) { agp_memory *new; new = kmalloc(sizeof(agp_memory), GFP_KERNEL); - if (new == NULL) { + if (new == NULL) return NULL; - } + memset(new, 0, sizeof(agp_memory)); new->key = agp_get_key(); @@ -170,12 +134,12 @@ { int i; - if ((agp_bridge.type == NOT_SUPPORTED) || (curr == NULL)) { + if ((agp_bridge.type == NOT_SUPPORTED) || (curr == NULL)) return; - } - if (curr->is_bound == TRUE) { + + if (curr->is_bound == TRUE) agp_unbind_memory(curr); - } + if (curr->type != 0) { agp_bridge.free_by_type(curr); return; @@ -200,9 +164,9 @@ agp_memory *new; int i; - if (agp_bridge.type == NOT_SUPPORTED) { + if (agp_bridge.type == NOT_SUPPORTED) return NULL; - } + if ((atomic_read(&agp_bridge.current_memory_agp) + page_count) > agp_bridge.max_memory_agp) { return NULL; @@ -216,14 +180,14 @@ * it */ - MOD_INC_USE_COUNT; + MOD_INC_USE_COUNT; scratch_pages = (page_count + ENTRIES_PER_PAGE - 1) / ENTRIES_PER_PAGE; new = agp_create_memory(scratch_pages); if (new == NULL) { - MOD_DEC_USE_COUNT; + MOD_DEC_USE_COUNT; return NULL; } @@ -235,8 +199,7 @@ agp_free_memory(new); return NULL; } - new->memory[i] = - agp_bridge.mask_memory(virt_to_phys(addr), type); + new->memory[i] = agp_bridge.mask_memory(virt_to_phys(addr), type); new->page_count++; } @@ -329,9 +292,9 @@ } ret_val = agp_bridge.insert_memory(curr, pg_start, curr->type); - if (ret_val != 0) { + if (ret_val != 0) return ret_val; - } + curr->is_bound = TRUE; curr->pg_start = pg_start; return 0; @@ -341,17 +304,17 @@ { int ret_val; - if ((agp_bridge.type == NOT_SUPPORTED) || (curr == NULL)) { + if ((agp_bridge.type == NOT_SUPPORTED) || (curr == NULL)) return -EINVAL; - } - if (curr->is_bound != TRUE) { + + if (curr->is_bound != TRUE) return -EINVAL; - } + ret_val = agp_bridge.remove_memory(curr, curr->pg_start, curr->type); - if (ret_val != 0) { + if (ret_val != 0) return ret_val; - } + curr->is_bound = FALSE; curr->pg_start = 0; return 0; @@ -369,15 +332,13 @@ /* Generic Agp routines - Start */ -static void agp_generic_agp_enable(u32 mode) +void agp_generic_agp_enable(u32 mode) { struct pci_dev *device = NULL; u32 command, scratch; u8 cap_ptr; - pci_read_config_dword(agp_bridge.dev, - agp_bridge.capndx + 4, - &command); + pci_read_config_dword(agp_bridge.dev, agp_bridge.capndx + 4, &command); /* * PASS1: go throu all devices that claim to be @@ -396,8 +357,7 @@ pci_read_config_dword(device, cap_ptr + 4, &scratch); /* adjust RQ depth */ - command = - ((command & ~0xff000000) | + command = ((command & ~0xff000000) | min_t(u32, (mode & 0xff000000), min_t(u32, (command & 0xff000000), (scratch & 0xff000000)))); @@ -435,15 +395,15 @@ * target (our motherboard chipset). */ - if (command & 4) { + if (command & 4) command &= ~3; /* 4X */ - } - if (command & 2) { + + if (command & 2) command &= ~5; /* 2X */ - } - if (command & 1) { + + if (command & 1) command &= ~6; /* 1X */ - } + command |= 0x00000100; pci_write_config_dword(agp_bridge.dev, @@ -462,7 +422,7 @@ } } -static int agp_generic_create_gatt_table(void) +int agp_generic_create_gatt_table(void) { char *table; char *table_end; @@ -543,15 +503,15 @@ } while ((table == NULL) && (i < agp_bridge.num_aperture_sizes)); } else { - size = ((aper_size_info_fixed *) temp)->size; - page_order = ((aper_size_info_fixed *) temp)->page_order; - num_entries = ((aper_size_info_fixed *) temp)->num_entries; + size = ((struct aper_size_info_fixed *) temp)->size; + page_order = ((struct aper_size_info_fixed *) temp)->page_order; + num_entries = ((struct aper_size_info_fixed *) temp)->num_entries; table = (char *) __get_free_pages(GFP_KERNEL, page_order); } - if (table == NULL) { + if (table == NULL) return -ENOMEM; - } + table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1); for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) @@ -573,25 +533,23 @@ } agp_bridge.gatt_bus_addr = virt_to_phys(agp_bridge.gatt_table_real); - for (i = 0; i < num_entries; i++) { - agp_bridge.gatt_table[i] = - (unsigned long) agp_bridge.scratch_page; - } + for (i = 0; i < num_entries; i++) + agp_bridge.gatt_table[i] = (unsigned long) agp_bridge.scratch_page; return 0; } -static int agp_generic_suspend(void) +int agp_generic_suspend(void) { return 0; } -static void agp_generic_resume(void) +void agp_generic_resume(void) { return; } -static int agp_generic_free_gatt_table(void) +int agp_generic_free_gatt_table(void) { int page_order; char *table, *table_end; @@ -638,8 +596,7 @@ return 0; } -static int agp_generic_insert_memory(agp_memory * mem, - off_t pg_start, int type) +int agp_generic_insert_memory(agp_memory * mem, off_t pg_start, int type) { int i, j, num_entries; void *temp; @@ -672,9 +629,10 @@ /* The generic routines know nothing of memory types */ return -EINVAL; } - if ((pg_start + mem->page_count) > num_entries) { + + if ((pg_start + mem->page_count) > num_entries) return -EINVAL; - } + j = pg_start; while (j < (pg_start + mem->page_count)) { @@ -688,16 +646,15 @@ CACHE_FLUSH(); mem->is_flushed = TRUE; } - for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { + + for (i = 0, j = pg_start; i < mem->page_count; i++, j++) agp_bridge.gatt_table[j] = mem->memory[i]; - } agp_bridge.tlb_flush(mem); return 0; } -static int agp_generic_remove_memory(agp_memory * mem, off_t pg_start, - int type) +int agp_generic_remove_memory(agp_memory * mem, off_t pg_start, int type) { int i; @@ -714,16 +671,16 @@ return 0; } -static agp_memory *agp_generic_alloc_by_type(size_t page_count, int type) +agp_memory *agp_generic_alloc_by_type(size_t page_count, int type) { return NULL; } -static void agp_generic_free_by_type(agp_memory * curr) +void agp_generic_free_by_type(agp_memory * curr) { - if (curr->memory != NULL) { + if (curr->memory != NULL) vfree(curr->memory); - } + agp_free_key(curr->key); kfree(curr); } @@ -737,7 +694,7 @@ * against a maximum value. */ -static void *agp_generic_alloc_page(void) +void *agp_generic_alloc_page(void) { struct page * page; @@ -753,7 +710,7 @@ return page_address(page); } -static void agp_generic_destroy_page(void *addr) +void agp_generic_destroy_page(void *addr) { struct page *page; @@ -772,3555 +729,13 @@ void agp_enable(u32 mode) { - if (agp_bridge.type == NOT_SUPPORTED) return; + if (agp_bridge.type == NOT_SUPPORTED) + return; agp_bridge.agp_enable(mode); } /* End - Generic Agp routines */ -#ifdef CONFIG_AGP_I810 -static aper_size_info_fixed intel_i810_sizes[] = -{ - {64, 16384, 4}, - /* The 32M mode still requires a 64k gatt */ - {32, 8192, 4} -}; - -#define AGP_DCACHE_MEMORY 1 -#define AGP_PHYS_MEMORY 2 - -static gatt_mask intel_i810_masks[] = -{ - {I810_PTE_VALID, 0}, - {(I810_PTE_VALID | I810_PTE_LOCAL), AGP_DCACHE_MEMORY}, - {I810_PTE_VALID, 0} -}; - -static struct _intel_i810_private { - struct pci_dev *i810_dev; /* device one */ - volatile u8 *registers; - int num_dcache_entries; -} intel_i810_private; - -static int intel_i810_fetch_size(void) -{ - u32 smram_miscc; - aper_size_info_fixed *values; - - pci_read_config_dword(agp_bridge.dev, I810_SMRAM_MISCC, &smram_miscc); - values = A_SIZE_FIX(agp_bridge.aperture_sizes); - - if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) { - printk(KERN_WARNING PFX "i810 is disabled\n"); - return 0; - } - if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) { - agp_bridge.previous_size = - agp_bridge.current_size = (void *) (values + 1); - agp_bridge.aperture_size_idx = 1; - return values[1].size; - } else { - agp_bridge.previous_size = - agp_bridge.current_size = (void *) (values); - agp_bridge.aperture_size_idx = 0; - return values[0].size; - } - - return 0; -} - -static int intel_i810_configure(void) -{ - aper_size_info_fixed *current_size; - u32 temp; - int i; - - current_size = A_SIZE_FIX(agp_bridge.current_size); - - pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp); - temp &= 0xfff80000; - - intel_i810_private.registers = - (volatile u8 *) ioremap(temp, 128 * 4096); - - if ((INREG32(intel_i810_private.registers, I810_DRAM_CTL) - & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) { - /* This will need to be dynamically assigned */ - printk(KERN_INFO PFX "detected 4MB dedicated video ram.\n"); - intel_i810_private.num_dcache_entries = 1024; - } - pci_read_config_dword(intel_i810_private.i810_dev, I810_GMADDR, &temp); - agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - OUTREG32(intel_i810_private.registers, I810_PGETBL_CTL, - agp_bridge.gatt_bus_addr | I810_PGETBL_ENABLED); - CACHE_FLUSH(); - - if (agp_bridge.needs_scratch_page == TRUE) { - for (i = 0; i < current_size->num_entries; i++) { - OUTREG32(intel_i810_private.registers, - I810_PTE_BASE + (i * 4), - agp_bridge.scratch_page); - } - } - return 0; -} - -static void intel_i810_cleanup(void) -{ - OUTREG32(intel_i810_private.registers, I810_PGETBL_CTL, 0); - iounmap((void *) intel_i810_private.registers); -} - -static void intel_i810_tlbflush(agp_memory * mem) -{ - return; -} - -static void intel_i810_agp_enable(u32 mode) -{ - return; -} - -static int intel_i810_insert_entries(agp_memory * mem, off_t pg_start, - int type) -{ - int i, j, num_entries; - void *temp; - - temp = agp_bridge.current_size; - num_entries = A_SIZE_FIX(temp)->num_entries; - - if ((pg_start + mem->page_count) > num_entries) { - return -EINVAL; - } - for (j = pg_start; j < (pg_start + mem->page_count); j++) { - if (!PGE_EMPTY(agp_bridge.gatt_table[j])) { - return -EBUSY; - } - } - - if (type != 0 || mem->type != 0) { - if ((type == AGP_DCACHE_MEMORY) && - (mem->type == AGP_DCACHE_MEMORY)) { - /* special insert */ - CACHE_FLUSH(); - for (i = pg_start; - i < (pg_start + mem->page_count); i++) { - OUTREG32(intel_i810_private.registers, - I810_PTE_BASE + (i * 4), - (i * 4096) | I810_PTE_LOCAL | - I810_PTE_VALID); - } - CACHE_FLUSH(); - agp_bridge.tlb_flush(mem); - return 0; - } - if((type == AGP_PHYS_MEMORY) && - (mem->type == AGP_PHYS_MEMORY)) { - goto insert; - } - return -EINVAL; - } - -insert: - CACHE_FLUSH(); - for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { - OUTREG32(intel_i810_private.registers, - I810_PTE_BASE + (j * 4), mem->memory[i]); - } - CACHE_FLUSH(); - - agp_bridge.tlb_flush(mem); - return 0; -} - -static int intel_i810_remove_entries(agp_memory * mem, off_t pg_start, - int type) -{ - int i; - - for (i = pg_start; i < (mem->page_count + pg_start); i++) { - OUTREG32(intel_i810_private.registers, - I810_PTE_BASE + (i * 4), - agp_bridge.scratch_page); - } - - CACHE_FLUSH(); - agp_bridge.tlb_flush(mem); - return 0; -} - -static agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type) -{ - agp_memory *new; - - if (type == AGP_DCACHE_MEMORY) { - if (pg_count != intel_i810_private.num_dcache_entries) { - return NULL; - } - new = agp_create_memory(1); - - if (new == NULL) { - return NULL; - } - new->type = AGP_DCACHE_MEMORY; - new->page_count = pg_count; - new->num_scratch_pages = 0; - vfree(new->memory); - MOD_INC_USE_COUNT; - return new; - } - if(type == AGP_PHYS_MEMORY) { - void *addr; - /* The I810 requires a physical address to program - * it's mouse pointer into hardware. However the - * Xserver still writes to it through the agp - * aperture - */ - if (pg_count != 1) { - return NULL; - } - new = agp_create_memory(1); - - if (new == NULL) { - return NULL; - } - MOD_INC_USE_COUNT; - addr = agp_bridge.agp_alloc_page(); - - if (addr == NULL) { - /* Free this structure */ - agp_free_memory(new); - return NULL; - } - new->memory[0] = agp_bridge.mask_memory(virt_to_phys(addr), type); - new->page_count = 1; - new->num_scratch_pages = 1; - new->type = AGP_PHYS_MEMORY; - new->physical = virt_to_phys((void *) new->memory[0]); - return new; - } - - return NULL; -} - -static void intel_i810_free_by_type(agp_memory * curr) -{ - agp_free_key(curr->key); - if(curr->type == AGP_PHYS_MEMORY) { - agp_bridge.agp_destroy_page( - phys_to_virt(curr->memory[0])); - vfree(curr->memory); - } - kfree(curr); - MOD_DEC_USE_COUNT; -} - -static unsigned long intel_i810_mask_memory(unsigned long addr, int type) -{ - /* Type checking must be done elsewhere */ - return addr | agp_bridge.masks[type].mask; -} - -static int __init intel_i810_setup(struct pci_dev *i810_dev) -{ - intel_i810_private.i810_dev = i810_dev; - - agp_bridge.masks = intel_i810_masks; - agp_bridge.num_of_masks = 2; - agp_bridge.aperture_sizes = (void *) intel_i810_sizes; - agp_bridge.size_type = FIXED_APER_SIZE; - agp_bridge.num_aperture_sizes = 2; - agp_bridge.dev_private_data = (void *) &intel_i810_private; - agp_bridge.needs_scratch_page = TRUE; - agp_bridge.configure = intel_i810_configure; - agp_bridge.fetch_size = intel_i810_fetch_size; - agp_bridge.cleanup = intel_i810_cleanup; - agp_bridge.tlb_flush = intel_i810_tlbflush; - agp_bridge.mask_memory = intel_i810_mask_memory; - agp_bridge.agp_enable = intel_i810_agp_enable; - agp_bridge.cache_flush = global_cache_flush; - agp_bridge.create_gatt_table = agp_generic_create_gatt_table; - agp_bridge.free_gatt_table = agp_generic_free_gatt_table; - agp_bridge.insert_memory = intel_i810_insert_entries; - agp_bridge.remove_memory = intel_i810_remove_entries; - agp_bridge.alloc_by_type = intel_i810_alloc_by_type; - agp_bridge.free_by_type = intel_i810_free_by_type; - agp_bridge.agp_alloc_page = agp_generic_alloc_page; - agp_bridge.agp_destroy_page = agp_generic_destroy_page; - agp_bridge.suspend = agp_generic_suspend; - agp_bridge.resume = agp_generic_resume; - agp_bridge.cant_use_aperture = 0; - - return 0; -} - -static aper_size_info_fixed intel_i830_sizes[] = -{ - {128, 32768, 5}, - /* The 64M mode still requires a 128k gatt */ - {64, 16384, 5} -}; - -static struct _intel_i830_private { - struct pci_dev *i830_dev; /* device one */ - volatile u8 *registers; - int gtt_entries; -} intel_i830_private; - -static void intel_i830_init_gtt_entries(void) { - u16 gmch_ctrl; - int gtt_entries; - u8 rdct; - static const int ddt[4] = { 0, 16, 32, 64 }; - - pci_read_config_word(agp_bridge.dev,I830_GMCH_CTRL,&gmch_ctrl); - - switch (gmch_ctrl & I830_GMCH_GMS_MASK) { - case I830_GMCH_GMS_STOLEN_512: - gtt_entries = KB(512); - printk(KERN_INFO PFX "detected %dK stolen memory.\n",gtt_entries / KB(1)); - break; - case I830_GMCH_GMS_STOLEN_1024: - gtt_entries = MB(1); - printk(KERN_INFO PFX "detected %dK stolen memory.\n",gtt_entries / KB(1)); - break; - case I830_GMCH_GMS_STOLEN_8192: - gtt_entries = MB(8); - printk(KERN_INFO PFX "detected %dK stolen memory.\n",gtt_entries / KB(1)); - break; - case I830_GMCH_GMS_LOCAL: - rdct = INREG8(intel_i830_private.registers,I830_RDRAM_CHANNEL_TYPE); - gtt_entries = (I830_RDRAM_ND(rdct) + 1) * MB(ddt[I830_RDRAM_DDT(rdct)]); - printk(KERN_INFO PFX "detected %dK local memory.\n",gtt_entries / KB(1)); - break; - default: - printk(KERN_INFO PFX "no video memory detected.\n"); - gtt_entries = 0; - break; - } - - gtt_entries /= KB(4); - - intel_i830_private.gtt_entries = gtt_entries; -} - -/* The intel i830 automatically initializes the agp aperture during POST. - * Use the memory already set aside for in the GTT. - */ -static int intel_i830_create_gatt_table(void) -{ - int page_order; - aper_size_info_fixed *size; - int num_entries; - u32 temp; - - size = agp_bridge.current_size; - page_order = size->page_order; - num_entries = size->num_entries; - agp_bridge.gatt_table_real = 0; - - pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp); - temp &= 0xfff80000; - - intel_i830_private.registers = (volatile u8 *) ioremap(temp,128 * 4096); - if (!intel_i830_private.registers) return (-ENOMEM); - - temp = INREG32(intel_i830_private.registers,I810_PGETBL_CTL) & 0xfffff000; - CACHE_FLUSH(); - - /* we have to call this as early as possible after the MMIO base address is known */ - intel_i830_init_gtt_entries(); - - agp_bridge.gatt_table = NULL; - - agp_bridge.gatt_bus_addr = temp; - - return(0); -} - -/* Return the gatt table to a sane state. Use the top of stolen - * memory for the GTT. - */ -static int intel_i830_free_gatt_table(void) -{ - return(0); -} - -static int intel_i830_fetch_size(void) -{ - u16 gmch_ctrl; - aper_size_info_fixed *values; - - pci_read_config_word(agp_bridge.dev,I830_GMCH_CTRL,&gmch_ctrl); - values = A_SIZE_FIX(agp_bridge.aperture_sizes); - - if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) { - agp_bridge.previous_size = agp_bridge.current_size = (void *) values; - agp_bridge.aperture_size_idx = 0; - return(values[0].size); - } else { - agp_bridge.previous_size = agp_bridge.current_size = (void *) values; - agp_bridge.aperture_size_idx = 1; - return(values[1].size); - } - - return(0); -} - -static int intel_i830_configure(void) -{ - aper_size_info_fixed *current_size; - u32 temp; - u16 gmch_ctrl; - int i; - - current_size = A_SIZE_FIX(agp_bridge.current_size); - - pci_read_config_dword(intel_i830_private.i830_dev,I810_GMADDR,&temp); - agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - - pci_read_config_word(agp_bridge.dev,I830_GMCH_CTRL,&gmch_ctrl); - gmch_ctrl |= I830_GMCH_ENABLED; - pci_write_config_word(agp_bridge.dev,I830_GMCH_CTRL,gmch_ctrl); - - OUTREG32(intel_i830_private.registers,I810_PGETBL_CTL,agp_bridge.gatt_bus_addr | I810_PGETBL_ENABLED); - CACHE_FLUSH(); - - if (agp_bridge.needs_scratch_page == TRUE) - for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) - OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge.scratch_page); - - return (0); -} - -static void intel_i830_cleanup(void) -{ - iounmap((void *) intel_i830_private.registers); -} - -static int intel_i830_insert_entries(agp_memory *mem,off_t pg_start,int type) -{ - int i,j,num_entries; - void *temp; - - temp = agp_bridge.current_size; - num_entries = A_SIZE_FIX(temp)->num_entries; - - if (pg_start < intel_i830_private.gtt_entries) { - printk (KERN_DEBUG "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n", - pg_start,intel_i830_private.gtt_entries); - - printk ("Trying to insert into local/stolen memory\n"); - return (-EINVAL); - } - - if ((pg_start + mem->page_count) > num_entries) - return (-EINVAL); - - /* The i830 can't check the GTT for entries since its read only, - * depend on the caller to make the correct offset decisions. - */ - - if ((type != 0 && type != AGP_PHYS_MEMORY) || - (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) - return (-EINVAL); - - CACHE_FLUSH(); - - for (i = 0, j = pg_start; i < mem->page_count; i++, j++) - OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (j * 4),mem->memory[i]); - - CACHE_FLUSH(); - - agp_bridge.tlb_flush(mem); - - return(0); -} - -static int intel_i830_remove_entries(agp_memory *mem,off_t pg_start,int type) -{ - int i; - - CACHE_FLUSH (); - - if (pg_start < intel_i830_private.gtt_entries) { - printk ("Trying to disable local/stolen memory\n"); - return (-EINVAL); - } - - for (i = pg_start; i < (mem->page_count + pg_start); i++) - OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge.scratch_page); - - CACHE_FLUSH(); - - agp_bridge.tlb_flush(mem); - - return (0); -} - -static agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type) -{ - agp_memory *nw; - - /* always return NULL for now */ - if (type == AGP_DCACHE_MEMORY) return(NULL); - - if (type == AGP_PHYS_MEMORY) { - void *addr; - - /* The i830 requires a physical address to program - * it's mouse pointer into hardware. However the - * Xserver still writes to it through the agp - * aperture - */ - - if (pg_count != 1) return(NULL); - - nw = agp_create_memory(1); - - if (nw == NULL) return(NULL); - - MOD_INC_USE_COUNT; - addr = agp_bridge.agp_alloc_page(); - if (addr == NULL) { - /* free this structure */ - agp_free_memory(nw); - return(NULL); - } - - nw->memory[0] = agp_bridge.mask_memory(virt_to_phys(addr),type); - nw->page_count = 1; - nw->num_scratch_pages = 1; - nw->type = AGP_PHYS_MEMORY; - nw->physical = virt_to_phys(addr); - return(nw); - } - - return(NULL); -} - -static int __init intel_i830_setup(struct pci_dev *i830_dev) -{ - intel_i830_private.i830_dev = i830_dev; - - agp_bridge.masks = intel_i810_masks; - agp_bridge.num_of_masks = 3; - agp_bridge.aperture_sizes = (void *) intel_i830_sizes; - agp_bridge.size_type = FIXED_APER_SIZE; - agp_bridge.num_aperture_sizes = 2; - - agp_bridge.dev_private_data = (void *) &intel_i830_private; - agp_bridge.needs_scratch_page = TRUE; - - agp_bridge.configure = intel_i830_configure; - agp_bridge.fetch_size = intel_i830_fetch_size; - agp_bridge.cleanup = intel_i830_cleanup; - agp_bridge.tlb_flush = intel_i810_tlbflush; - agp_bridge.mask_memory = intel_i810_mask_memory; - agp_bridge.agp_enable = intel_i810_agp_enable; - agp_bridge.cache_flush = global_cache_flush; - - agp_bridge.create_gatt_table = intel_i830_create_gatt_table; - agp_bridge.free_gatt_table = intel_i830_free_gatt_table; - - agp_bridge.insert_memory = intel_i830_insert_entries; - agp_bridge.remove_memory = intel_i830_remove_entries; - agp_bridge.alloc_by_type = intel_i830_alloc_by_type; - agp_bridge.free_by_type = intel_i810_free_by_type; - agp_bridge.agp_alloc_page = agp_generic_alloc_page; - agp_bridge.agp_destroy_page = agp_generic_destroy_page; - - agp_bridge.suspend = agp_generic_suspend; - agp_bridge.resume = agp_generic_resume; - agp_bridge.cant_use_aperture = 0; - - return(0); -} - -#endif /* CONFIG_AGP_I810 */ - -#ifdef CONFIG_AGP_I460 - -/* BIOS configures the chipset so that one of two apbase registers are used */ -static u8 intel_i460_dynamic_apbase = 0x10; - -/* 460 supports multiple GART page sizes, so GART pageshift is dynamic */ -static u8 intel_i460_pageshift = 12; -static u32 intel_i460_pagesize; - -/* Keep track of which is larger, chipset or kernel page size. */ -static u32 intel_i460_cpk = 1; - -/* Structure for tracking partial use of 4MB GART pages */ -static u32 **i460_pg_detail = NULL; -static u32 *i460_pg_count = NULL; - -#define I460_CPAGES_PER_KPAGE (PAGE_SIZE >> intel_i460_pageshift) -#define I460_KPAGES_PER_CPAGE ((1 << intel_i460_pageshift) >> PAGE_SHIFT) - -#define I460_SRAM_IO_DISABLE (1 << 4) -#define I460_BAPBASE_ENABLE (1 << 3) -#define I460_AGPSIZ_MASK 0x7 -#define I460_4M_PS (1 << 1) - -#define log2(x) ffz(~(x)) - -static inline void intel_i460_read_back (volatile u32 *entry) -{ - /* - * The 460 spec says we have to read the last location written to - * make sure that all writes have taken effect - */ - *entry; -} - -static int intel_i460_fetch_size(void) -{ - int i; - u8 temp; - aper_size_info_8 *values; - - /* Determine the GART page size */ - pci_read_config_byte(agp_bridge.dev, INTEL_I460_GXBCTL, &temp); - intel_i460_pageshift = (temp & I460_4M_PS) ? 22 : 12; - intel_i460_pagesize = 1UL << intel_i460_pageshift; - - values = A_SIZE_8(agp_bridge.aperture_sizes); - - pci_read_config_byte(agp_bridge.dev, INTEL_I460_AGPSIZ, &temp); - - /* Exit now if the IO drivers for the GART SRAMS are turned off */ - if (temp & I460_SRAM_IO_DISABLE) { - printk(KERN_ERR PFX "GART SRAMS disabled on 460GX chipset\n"); - printk(KERN_ERR PFX "AGPGART operation not possible\n"); - return 0; - } - - /* Make sure we don't try to create an 2 ^ 23 entry GATT */ - if ((intel_i460_pageshift == 0) && ((temp & I460_AGPSIZ_MASK) == 4)) { - printk(KERN_ERR PFX "We can't have a 32GB aperture with 4KB GART pages\n"); - return 0; - } - - /* Determine the proper APBASE register */ - if (temp & I460_BAPBASE_ENABLE) - intel_i460_dynamic_apbase = INTEL_I460_BAPBASE; - else - intel_i460_dynamic_apbase = INTEL_I460_APBASE; - - for (i = 0; i < agp_bridge.num_aperture_sizes; i++) { - /* - * Dynamically calculate the proper num_entries and page_order values for - * the define aperture sizes. Take care not to shift off the end of - * values[i].size. - */ - values[i].num_entries = (values[i].size << 8) >> (intel_i460_pageshift - 12); - values[i].page_order = log2((sizeof(u32)*values[i].num_entries) >> PAGE_SHIFT); - } - - for (i = 0; i < agp_bridge.num_aperture_sizes; i++) { - /* Neglect control bits when matching up size_value */ - if ((temp & I460_AGPSIZ_MASK) == 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; -} - -/* There isn't anything to do here since 460 has no GART TLB. */ -static void intel_i460_tlb_flush(agp_memory * mem) -{ - return; -} - -/* - * This utility function is needed to prevent corruption of the control bits - * which are stored along with the aperture size in 460's AGPSIZ register - */ -static void intel_i460_write_agpsiz(u8 size_value) -{ - u8 temp; - - pci_read_config_byte(agp_bridge.dev, INTEL_I460_AGPSIZ, &temp); - pci_write_config_byte(agp_bridge.dev, INTEL_I460_AGPSIZ, - ((temp & ~I460_AGPSIZ_MASK) | size_value)); -} - -static void intel_i460_cleanup(void) -{ - aper_size_info_8 *previous_size; - - previous_size = A_SIZE_8(agp_bridge.previous_size); - intel_i460_write_agpsiz(previous_size->size_value); - - if (intel_i460_cpk == 0) { - vfree(i460_pg_detail); - vfree(i460_pg_count); - } -} - - -/* Control bits for Out-Of-GART coherency and Burst Write Combining */ -#define I460_GXBCTL_OOG (1UL << 0) -#define I460_GXBCTL_BWC (1UL << 2) - -static int intel_i460_configure(void) -{ - union { - u32 small[2]; - u64 large; - } temp; - u8 scratch; - int i; - - aper_size_info_8 *current_size; - - temp.large = 0; - - current_size = A_SIZE_8(agp_bridge.current_size); - intel_i460_write_agpsiz(current_size->size_value); - - /* - * Do the necessary rigmarole to read all eight bytes of APBASE. - * This has to be done since the AGP aperture can be above 4GB on - * 460 based systems. - */ - pci_read_config_dword(agp_bridge.dev, intel_i460_dynamic_apbase, &(temp.small[0])); - pci_read_config_dword(agp_bridge.dev, intel_i460_dynamic_apbase + 4, &(temp.small[1])); - - /* Clear BAR control bits */ - agp_bridge.gart_bus_addr = temp.large & ~((1UL << 3) - 1); - - pci_read_config_byte(agp_bridge.dev, INTEL_I460_GXBCTL, &scratch); - pci_write_config_byte(agp_bridge.dev, INTEL_I460_GXBCTL, - (scratch & 0x02) | I460_GXBCTL_OOG | I460_GXBCTL_BWC); - - /* - * Initialize partial allocation trackers if a GART page is bigger than - * a kernel page. - */ - if (I460_CPAGES_PER_KPAGE >= 1) { - intel_i460_cpk = 1; - } else { - intel_i460_cpk = 0; - - i460_pg_detail = vmalloc(sizeof(*i460_pg_detail) * current_size->num_entries); - i460_pg_count = vmalloc(sizeof(*i460_pg_count) * current_size->num_entries); - - for (i = 0; i < current_size->num_entries; i++) { - i460_pg_count[i] = 0; - i460_pg_detail[i] = NULL; - } - } - return 0; -} - -static int intel_i460_create_gatt_table(void) -{ - char *table; - int i; - int page_order; - int num_entries; - void *temp; - - /* - * Load up the fixed address of the GART SRAMS which hold our - * GATT table. - */ - table = (char *) __va(INTEL_I460_ATTBASE); - - temp = agp_bridge.current_size; - page_order = A_SIZE_8(temp)->page_order; - num_entries = A_SIZE_8(temp)->num_entries; - - agp_bridge.gatt_table_real = (u32 *) table; - agp_bridge.gatt_table = ioremap_nocache(virt_to_phys(table), - (PAGE_SIZE * (1 << page_order))); - agp_bridge.gatt_bus_addr = virt_to_phys(agp_bridge.gatt_table_real); - - for (i = 0; i < num_entries; i++) { - agp_bridge.gatt_table[i] = 0; - } - - intel_i460_read_back(agp_bridge.gatt_table + i - 1); - return 0; -} - -static int intel_i460_free_gatt_table(void) -{ - int num_entries; - int i; - void *temp; - - temp = agp_bridge.current_size; - - num_entries = A_SIZE_8(temp)->num_entries; - - for (i = 0; i < num_entries; i++) { - agp_bridge.gatt_table[i] = 0; - } - - intel_i460_read_back(agp_bridge.gatt_table + i - 1); - - iounmap(agp_bridge.gatt_table); - return 0; -} - -/* These functions are called when PAGE_SIZE exceeds the GART page size */ - -static int intel_i460_insert_memory_cpk(agp_memory * mem, off_t pg_start, int type) -{ - int i, j, k, num_entries; - void *temp; - unsigned long paddr; - - /* - * The rest of the kernel will compute page offsets in terms of - * PAGE_SIZE. - */ - pg_start = I460_CPAGES_PER_KPAGE * pg_start; - - temp = agp_bridge.current_size; - num_entries = A_SIZE_8(temp)->num_entries; - - if ((pg_start + I460_CPAGES_PER_KPAGE * mem->page_count) > num_entries) { - printk(KERN_ERR PFX "Looks like we're out of AGP memory\n"); - return -EINVAL; - } - - j = pg_start; - while (j < (pg_start + I460_CPAGES_PER_KPAGE * mem->page_count)) { - if (!PGE_EMPTY(agp_bridge.gatt_table[j])) { - return -EBUSY; - } - j++; - } - -#if 0 - /* not necessary since 460 GART is operated in coherent mode... */ - if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); - mem->is_flushed = TRUE; - } -#endif - - for (i = 0, j = pg_start; i < mem->page_count; i++) { - paddr = mem->memory[i]; - for (k = 0; k < I460_CPAGES_PER_KPAGE; k++, j++, paddr += intel_i460_pagesize) - agp_bridge.gatt_table[j] = (u32) agp_bridge.mask_memory(paddr, mem->type); - } - - intel_i460_read_back(agp_bridge.gatt_table + j - 1); - return 0; -} - -static int intel_i460_remove_memory_cpk(agp_memory * mem, off_t pg_start, int type) -{ - int i; - - pg_start = I460_CPAGES_PER_KPAGE * pg_start; - - for (i = pg_start; i < (pg_start + I460_CPAGES_PER_KPAGE * mem->page_count); i++) - agp_bridge.gatt_table[i] = 0; - - intel_i460_read_back(agp_bridge.gatt_table + i - 1); - return 0; -} - -/* - * These functions are called when the GART page size exceeds PAGE_SIZE. - * - * This situation is interesting since AGP memory allocations that are - * smaller than a single GART page are possible. The structures i460_pg_count - * and i460_pg_detail track partial allocation of the large GART pages to - * work around this issue. - * - * i460_pg_count[pg_num] tracks the number of kernel pages in use within - * GART page pg_num. i460_pg_detail[pg_num] is an array containing a - * psuedo-GART entry for each of the aforementioned kernel pages. The whole - * of i460_pg_detail is equivalent to a giant GATT with page size equal to - * that of the kernel. - */ - -static void *intel_i460_alloc_large_page(int pg_num) -{ - int i; - void *bp, *bp_end; - struct page *page; - - i460_pg_detail[pg_num] = (void *) vmalloc(sizeof(u32) * I460_KPAGES_PER_CPAGE); - if (i460_pg_detail[pg_num] == NULL) { - printk(KERN_ERR PFX "Out of memory, we're in trouble...\n"); - return NULL; - } - - for (i = 0; i < I460_KPAGES_PER_CPAGE; i++) - i460_pg_detail[pg_num][i] = 0; - - bp = (void *) __get_free_pages(GFP_KERNEL, intel_i460_pageshift - PAGE_SHIFT); - if (bp == NULL) { - printk(KERN_ERR PFX "Couldn't alloc 4M GART page...\n"); - return NULL; - } - - bp_end = bp + ((PAGE_SIZE * (1 << (intel_i460_pageshift - PAGE_SHIFT))) - 1); - - for (page = virt_to_page(bp); page <= virt_to_page(bp_end); page++) { - atomic_inc(&agp_bridge.current_memory_agp); - } - return bp; -} - -static void intel_i460_free_large_page(int pg_num, unsigned long addr) -{ - struct page *page; - void *bp, *bp_end; - - bp = (void *) __va(addr); - bp_end = bp + (PAGE_SIZE * (1 << (intel_i460_pageshift - PAGE_SHIFT))); - - vfree(i460_pg_detail[pg_num]); - i460_pg_detail[pg_num] = NULL; - - for (page = virt_to_page(bp); page < virt_to_page(bp_end); page++) { - atomic_dec(&agp_bridge.current_memory_agp); - } - - free_pages((unsigned long) bp, intel_i460_pageshift - PAGE_SHIFT); -} - -static int intel_i460_insert_memory_kpc(agp_memory * mem, off_t pg_start, int type) -{ - int i, pg, start_pg, end_pg, start_offset, end_offset, idx; - int num_entries; - void *temp; - unsigned long paddr; - - temp = agp_bridge.current_size; - num_entries = A_SIZE_8(temp)->num_entries; - - /* Figure out what pg_start means in terms of our large GART pages */ - start_pg = pg_start / I460_KPAGES_PER_CPAGE; - start_offset = pg_start % I460_KPAGES_PER_CPAGE; - end_pg = (pg_start + mem->page_count - 1) / I460_KPAGES_PER_CPAGE; - end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_CPAGE; - - if (end_pg > num_entries) { - printk(KERN_ERR PFX "Looks like we're out of AGP memory\n"); - return -EINVAL; - } - - /* Check if the requested region of the aperture is free */ - for (pg = start_pg; pg <= end_pg; pg++) { - /* Allocate new GART pages if necessary */ - if (i460_pg_detail[pg] == NULL) { - temp = intel_i460_alloc_large_page(pg); - if (temp == NULL) - return -ENOMEM; - agp_bridge.gatt_table[pg] = agp_bridge.mask_memory((unsigned long) temp, - 0); - intel_i460_read_back(agp_bridge.gatt_table + pg); - } - - for (idx = ((pg == start_pg) ? start_offset : 0); - idx < ((pg == end_pg) ? (end_offset + 1) : I460_KPAGES_PER_CPAGE); - idx++) - { - if (i460_pg_detail[pg][idx] != 0) - return -EBUSY; - } - } - -#if 0 - /* not necessary since 460 GART is operated in coherent mode... */ - if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); - mem->is_flushed = TRUE; - } -#endif - - for (pg = start_pg, i = 0; pg <= end_pg; pg++) { - paddr = agp_bridge.unmask_memory(agp_bridge.gatt_table[pg]); - for (idx = ((pg == start_pg) ? start_offset : 0); - idx < ((pg == end_pg) ? (end_offset + 1) : I460_KPAGES_PER_CPAGE); - idx++, i++) - { - mem->memory[i] = paddr + (idx * PAGE_SIZE); - i460_pg_detail[pg][idx] = agp_bridge.mask_memory(mem->memory[i], - mem->type); - i460_pg_count[pg]++; - } - } - - return 0; -} - -static int intel_i460_remove_memory_kpc(agp_memory * mem, off_t pg_start, int type) -{ - int i, pg, start_pg, end_pg, start_offset, end_offset, idx; - int num_entries; - void *temp; - unsigned long paddr; - - temp = agp_bridge.current_size; - num_entries = A_SIZE_8(temp)->num_entries; - - /* Figure out what pg_start means in terms of our large GART pages */ - start_pg = pg_start / I460_KPAGES_PER_CPAGE; - start_offset = pg_start % I460_KPAGES_PER_CPAGE; - end_pg = (pg_start + mem->page_count - 1) / I460_KPAGES_PER_CPAGE; - end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_CPAGE; - - for (i = 0, pg = start_pg; pg <= end_pg; pg++) { - for (idx = ((pg == start_pg) ? start_offset : 0); - idx < ((pg == end_pg) ? (end_offset + 1) : I460_KPAGES_PER_CPAGE); - idx++, i++) - { - mem->memory[i] = 0; - i460_pg_detail[pg][idx] = 0; - i460_pg_count[pg]--; - } - - /* Free GART pages if they are unused */ - if (i460_pg_count[pg] == 0) { - paddr = agp_bridge.unmask_memory(agp_bridge.gatt_table[pg]); - agp_bridge.gatt_table[pg] = agp_bridge.scratch_page; - intel_i460_read_back(agp_bridge.gatt_table + pg); - intel_i460_free_large_page(pg, paddr); - } - } - return 0; -} - -/* Dummy routines to call the approriate {cpk,kpc} function */ - -static int intel_i460_insert_memory(agp_memory * mem, off_t pg_start, int type) -{ - if (intel_i460_cpk) - return intel_i460_insert_memory_cpk(mem, pg_start, type); - else - return intel_i460_insert_memory_kpc(mem, pg_start, type); -} - -static int intel_i460_remove_memory(agp_memory * mem, off_t pg_start, int type) -{ - if (intel_i460_cpk) - return intel_i460_remove_memory_cpk(mem, pg_start, type); - else - return intel_i460_remove_memory_kpc(mem, pg_start, type); -} - -/* - * If the kernel page size is smaller that the chipset page size, we don't - * want to allocate memory until we know where it is to be bound in the - * aperture (a multi-kernel-page alloc might fit inside of an already - * allocated GART page). Consequently, don't allocate or free anything - * if i460_cpk (meaning chipset pages per kernel page) isn't set. - * - * Let's just hope nobody counts on the allocated AGP memory being there - * before bind time (I don't think current drivers do)... - */ -static void * intel_i460_alloc_page(void) -{ - if (intel_i460_cpk) - return agp_generic_alloc_page(); - - /* Returning NULL would cause problems */ - /* AK: really dubious code. */ - return (void *)~0UL; -} - -static void intel_i460_destroy_page(void *page) -{ - if (intel_i460_cpk) - agp_generic_destroy_page(page); -} - -static gatt_mask intel_i460_masks[] = -{ - { - INTEL_I460_GATT_VALID | INTEL_I460_GATT_COHERENT, - 0 - } -}; - -static unsigned long intel_i460_mask_memory(unsigned long addr, int type) -{ - /* Make sure the returned address is a valid GATT entry */ - return (agp_bridge.masks[0].mask - | (((addr & ~((1 << intel_i460_pageshift) - 1)) & 0xffffff000) >> 12)); -} - -static unsigned long intel_i460_unmask_memory(unsigned long addr) -{ - /* Turn a GATT entry into a physical address */ - return ((addr & 0xffffff) << 12); -} - -static aper_size_info_8 intel_i460_sizes[3] = -{ - /* - * The 32GB aperture is only available with a 4M GART page size. - * Due to the dynamic GART page size, we can't figure out page_order - * or num_entries until runtime. - */ - {32768, 0, 0, 4}, - {1024, 0, 0, 2}, - {256, 0, 0, 1} -}; - -static int __init intel_i460_setup (struct pci_dev *pdev __attribute__((unused))) -{ - agp_bridge.masks = intel_i460_masks; - agp_bridge.aperture_sizes = (void *) intel_i460_sizes; - agp_bridge.size_type = U8_APER_SIZE; - agp_bridge.num_aperture_sizes = 3; - agp_bridge.dev_private_data = NULL; - agp_bridge.needs_scratch_page = FALSE; - agp_bridge.configure = intel_i460_configure; - agp_bridge.fetch_size = intel_i460_fetch_size; - agp_bridge.cleanup = intel_i460_cleanup; - agp_bridge.tlb_flush = intel_i460_tlb_flush; - agp_bridge.mask_memory = intel_i460_mask_memory; - agp_bridge.unmask_memory = intel_i460_unmask_memory; - agp_bridge.agp_enable = agp_generic_agp_enable; - agp_bridge.cache_flush = global_cache_flush; - agp_bridge.create_gatt_table = intel_i460_create_gatt_table; - agp_bridge.free_gatt_table = intel_i460_free_gatt_table; - agp_bridge.insert_memory = intel_i460_insert_memory; - agp_bridge.remove_memory = intel_i460_remove_memory; - agp_bridge.alloc_by_type = agp_generic_alloc_by_type; - agp_bridge.free_by_type = agp_generic_free_by_type; - agp_bridge.agp_alloc_page = intel_i460_alloc_page; - agp_bridge.agp_destroy_page = intel_i460_destroy_page; - agp_bridge.suspend = agp_generic_suspend; - agp_bridge.resume = agp_generic_resume; - agp_bridge.cant_use_aperture = 1; - return 0; -} - -#endif /* CONFIG_AGP_I460 */ - -#ifdef CONFIG_AGP_INTEL - -static int intel_fetch_size(void) -{ - int i; - u16 temp; - aper_size_info_16 *values; - - pci_read_config_word(agp_bridge.dev, INTEL_APSIZE, &temp); - values = A_SIZE_16(agp_bridge.aperture_sizes); - - for (i = 0; i < agp_bridge.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 int intel_8xx_fetch_size(void) -{ - int i; - u8 temp; - aper_size_info_8 *values; - - pci_read_config_byte(agp_bridge.dev, INTEL_APSIZE, &temp); - values = A_SIZE_8(agp_bridge.aperture_sizes); - - for (i = 0; i < agp_bridge.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 intel_tlbflush(agp_memory * mem) -{ - pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x2200); - pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x2280); -} - - -static void intel_8xx_tlbflush(agp_memory * mem) -{ - u32 temp; - pci_read_config_dword(agp_bridge.dev, INTEL_AGPCTRL, &temp); - pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, temp & ~(1 << 7)); - pci_read_config_dword(agp_bridge.dev, INTEL_AGPCTRL, &temp); - pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, temp | (1 << 7)); -} - - -static void intel_cleanup(void) -{ - u16 temp; - aper_size_info_16 *previous_size; - - previous_size = A_SIZE_16(agp_bridge.previous_size); - pci_read_config_word(agp_bridge.dev, INTEL_NBXCFG, &temp); - pci_write_config_word(agp_bridge.dev, INTEL_NBXCFG, temp & ~(1 << 9)); - pci_write_config_word(agp_bridge.dev, INTEL_APSIZE, - previous_size->size_value); -} - - -static void intel_8xx_cleanup(void) -{ - u16 temp; - aper_size_info_8 *previous_size; - - previous_size = A_SIZE_8(agp_bridge.previous_size); - pci_read_config_word(agp_bridge.dev, INTEL_NBXCFG, &temp); - pci_write_config_word(agp_bridge.dev, INTEL_NBXCFG, temp & ~(1 << 9)); - pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, - previous_size->size_value); -} - - -static int intel_configure(void) -{ - u32 temp; - u16 temp2; - aper_size_info_16 *current_size; - - current_size = A_SIZE_16(agp_bridge.current_size); - - /* aperture size */ - pci_write_config_word(agp_bridge.dev, INTEL_APSIZE, - current_size->size_value); - - /* address to map to */ - pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp); - agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - - /* attbase - aperture base */ - pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE, - agp_bridge.gatt_bus_addr); - - /* agpctrl */ - pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x2280); - - /* paccfg/nbxcfg */ - pci_read_config_word(agp_bridge.dev, INTEL_NBXCFG, &temp2); - pci_write_config_word(agp_bridge.dev, INTEL_NBXCFG, - (temp2 & ~(1 << 10)) | (1 << 9)); - /* clear any possible error conditions */ - pci_write_config_byte(agp_bridge.dev, INTEL_ERRSTS + 1, 7); - return 0; -} - -static void intel_820_tlbflush(agp_memory * mem) -{ - return; -} - -static void intel_820_cleanup(void) -{ - u8 temp; - aper_size_info_8 *previous_size; - - previous_size = A_SIZE_8(agp_bridge.previous_size); - pci_read_config_byte(agp_bridge.dev, INTEL_I820_RDCR, &temp); - pci_write_config_byte(agp_bridge.dev, INTEL_I820_RDCR, - temp & ~(1 << 1)); - pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, - previous_size->size_value); -} - - -static int intel_820_configure(void) -{ - u32 temp; - u8 temp2; - aper_size_info_8 *current_size; - - current_size = A_SIZE_8(agp_bridge.current_size); - - /* aperture size */ - pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, - current_size->size_value); - - /* address to map to */ - pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp); - agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - - /* attbase - aperture base */ - pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE, - agp_bridge.gatt_bus_addr); - - /* agpctrl */ - pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000); - - /* global enable aperture access */ - /* This flag is not accessed through MCHCFG register as in */ - /* i850 chipset. */ - pci_read_config_byte(agp_bridge.dev, INTEL_I820_RDCR, &temp2); - pci_write_config_byte(agp_bridge.dev, INTEL_I820_RDCR, - temp2 | (1 << 1)); - /* clear any possible AGP-related error conditions */ - pci_write_config_word(agp_bridge.dev, INTEL_I820_ERRSTS, 0x001c); - return 0; -} - -static int intel_840_configure(void) -{ - u32 temp; - u16 temp2; - aper_size_info_8 *current_size; - - current_size = A_SIZE_8(agp_bridge.current_size); - - /* aperture size */ - pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, - current_size->size_value); - - /* address to map to */ - pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp); - agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - - /* attbase - aperture base */ - pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE, - agp_bridge.gatt_bus_addr); - - /* agpctrl */ - pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000); - - /* mcgcfg */ - pci_read_config_word(agp_bridge.dev, INTEL_I840_MCHCFG, &temp2); - pci_write_config_word(agp_bridge.dev, INTEL_I840_MCHCFG, - temp2 | (1 << 9)); - /* clear any possible error conditions */ - pci_write_config_word(agp_bridge.dev, INTEL_I840_ERRSTS, 0xc000); - return 0; -} - -static int intel_845_configure(void) -{ - u32 temp; - u8 temp2; - aper_size_info_8 *current_size; - - current_size = A_SIZE_8(agp_bridge.current_size); - - /* aperture size */ - pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, - current_size->size_value); - - /* address to map to */ - pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp); - agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - - /* attbase - aperture base */ - pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE, - agp_bridge.gatt_bus_addr); - - /* agpctrl */ - pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000); - - /* agpm */ - pci_read_config_byte(agp_bridge.dev, INTEL_I845_AGPM, &temp2); - pci_write_config_byte(agp_bridge.dev, INTEL_I845_AGPM, - temp2 | (1 << 1)); - /* clear any possible error conditions */ - pci_write_config_word(agp_bridge.dev, INTEL_I845_ERRSTS, 0x001c); - return 0; -} - -static int intel_850_configure(void) -{ - u32 temp; - u16 temp2; - aper_size_info_8 *current_size; - - current_size = A_SIZE_8(agp_bridge.current_size); - - /* aperture size */ - pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, - current_size->size_value); - - /* address to map to */ - pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp); - agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - - /* attbase - aperture base */ - pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE, - agp_bridge.gatt_bus_addr); - - /* agpctrl */ - pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000); - - /* mcgcfg */ - pci_read_config_word(agp_bridge.dev, INTEL_I850_MCHCFG, &temp2); - pci_write_config_word(agp_bridge.dev, INTEL_I850_MCHCFG, - temp2 | (1 << 9)); - /* clear any possible AGP-related error conditions */ - pci_write_config_word(agp_bridge.dev, INTEL_I850_ERRSTS, 0x001c); - return 0; -} - -static int intel_860_configure(void) -{ - u32 temp; - u16 temp2; - aper_size_info_8 *current_size; - - current_size = A_SIZE_8(agp_bridge.current_size); - - /* aperture size */ - pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, - current_size->size_value); - - /* address to map to */ - pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp); - agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - - /* attbase - aperture base */ - pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE, - agp_bridge.gatt_bus_addr); - - /* agpctrl */ - pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000); - - /* mcgcfg */ - pci_read_config_word(agp_bridge.dev, INTEL_I860_MCHCFG, &temp2); - pci_write_config_word(agp_bridge.dev, INTEL_I860_MCHCFG, - temp2 | (1 << 9)); - /* clear any possible AGP-related error conditions */ - pci_write_config_word(agp_bridge.dev, INTEL_I860_ERRSTS, 0xf700); - return 0; -} - -static int intel_830mp_configure(void) -{ - u32 temp; - u16 temp2; - aper_size_info_8 *current_size; - - current_size = A_SIZE_8(agp_bridge.current_size); - - /* aperture size */ - pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, - current_size->size_value); - - /* address to map to */ - pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp); - agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - - /* attbase - aperture base */ - pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE, - agp_bridge.gatt_bus_addr); - - /* agpctrl */ - pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000); - - /* gmch */ - pci_read_config_word(agp_bridge.dev, INTEL_NBXCFG, &temp2); - pci_write_config_word(agp_bridge.dev, INTEL_NBXCFG, - temp2 | (1 << 9)); - /* clear any possible AGP-related error conditions */ - pci_write_config_word(agp_bridge.dev, INTEL_I830_ERRSTS, 0x1c); - return 0; -} - -static unsigned long intel_mask_memory(unsigned long addr, int type) -{ - /* Memory type is ignored */ - - return addr | agp_bridge.masks[0].mask; -} - -static void intel_resume(void) -{ - intel_configure(); -} - -/* Setup function */ -static gatt_mask intel_generic_masks[] = -{ - {0x00000017, 0} -}; - -static aper_size_info_8 intel_8xx_sizes[7] = -{ - {256, 65536, 6, 0}, - {128, 32768, 5, 32}, - {64, 16384, 4, 48}, - {32, 8192, 3, 56}, - {16, 4096, 2, 60}, - {8, 2048, 1, 62}, - {4, 1024, 0, 63} -}; - -static aper_size_info_16 intel_generic_sizes[7] = -{ - {256, 65536, 6, 0}, - {128, 32768, 5, 32}, - {64, 16384, 4, 48}, - {32, 8192, 3, 56}, - {16, 4096, 2, 60}, - {8, 2048, 1, 62}, - {4, 1024, 0, 63} -}; - -static aper_size_info_8 intel_830mp_sizes[4] = -{ - {256, 65536, 6, 0}, - {128, 32768, 5, 32}, - {64, 16384, 4, 48}, - {32, 8192, 3, 56} -}; - -static int __init intel_generic_setup (struct pci_dev *pdev) -{ - agp_bridge.masks = intel_generic_masks; - agp_bridge.num_of_masks = 1; - agp_bridge.aperture_sizes = (void *) intel_generic_sizes; - agp_bridge.size_type = U16_APER_SIZE; - agp_bridge.num_aperture_sizes = 7; - agp_bridge.dev_private_data = NULL; - agp_bridge.needs_scratch_page = FALSE; - agp_bridge.configure = intel_configure; - agp_bridge.fetch_size = intel_fetch_size; - agp_bridge.cleanup = intel_cleanup; - agp_bridge.tlb_flush = intel_tlbflush; - agp_bridge.mask_memory = intel_mask_memory; - agp_bridge.agp_enable = agp_generic_agp_enable; - agp_bridge.cache_flush = global_cache_flush; - agp_bridge.create_gatt_table = agp_generic_create_gatt_table; - agp_bridge.free_gatt_table = agp_generic_free_gatt_table; - agp_bridge.insert_memory = agp_generic_insert_memory; - agp_bridge.remove_memory = agp_generic_remove_memory; - agp_bridge.alloc_by_type = agp_generic_alloc_by_type; - agp_bridge.free_by_type = agp_generic_free_by_type; - agp_bridge.agp_alloc_page = agp_generic_alloc_page; - agp_bridge.agp_destroy_page = agp_generic_destroy_page; - agp_bridge.suspend = agp_generic_suspend; - agp_bridge.resume = intel_resume; - agp_bridge.cant_use_aperture = 0; - - return 0; - - (void) pdev; /* unused */ -} - - -static int __init intel_820_setup (struct pci_dev *pdev) -{ - agp_bridge.masks = intel_generic_masks; - agp_bridge.num_of_masks = 1; - agp_bridge.aperture_sizes = (void *) intel_8xx_sizes; - agp_bridge.size_type = U8_APER_SIZE; - agp_bridge.num_aperture_sizes = 7; - agp_bridge.dev_private_data = NULL; - agp_bridge.needs_scratch_page = FALSE; - agp_bridge.configure = intel_820_configure; - agp_bridge.fetch_size = intel_8xx_fetch_size; - agp_bridge.cleanup = intel_820_cleanup; - agp_bridge.tlb_flush = intel_820_tlbflush; - agp_bridge.mask_memory = intel_mask_memory; - agp_bridge.agp_enable = agp_generic_agp_enable; - agp_bridge.cache_flush = global_cache_flush; - agp_bridge.create_gatt_table = agp_generic_create_gatt_table; - agp_bridge.free_gatt_table = agp_generic_free_gatt_table; - agp_bridge.insert_memory = agp_generic_insert_memory; - agp_bridge.remove_memory = agp_generic_remove_memory; - agp_bridge.alloc_by_type = agp_generic_alloc_by_type; - agp_bridge.free_by_type = agp_generic_free_by_type; - agp_bridge.agp_alloc_page = agp_generic_alloc_page; - agp_bridge.agp_destroy_page = agp_generic_destroy_page; - agp_bridge.suspend = agp_generic_suspend; - agp_bridge.resume = agp_generic_resume; - agp_bridge.cant_use_aperture = 0; - - return 0; - - (void) pdev; /* unused */ -} - -static int __init intel_830mp_setup (struct pci_dev *pdev) -{ - agp_bridge.masks = intel_generic_masks; - agp_bridge.num_of_masks = 1; - agp_bridge.aperture_sizes = (void *) intel_830mp_sizes; - agp_bridge.size_type = U8_APER_SIZE; - agp_bridge.num_aperture_sizes = 4; - agp_bridge.dev_private_data = NULL; - agp_bridge.needs_scratch_page = FALSE; - agp_bridge.configure = intel_830mp_configure; - agp_bridge.fetch_size = intel_8xx_fetch_size; - agp_bridge.cleanup = intel_8xx_cleanup; - agp_bridge.tlb_flush = intel_8xx_tlbflush; - agp_bridge.mask_memory = intel_mask_memory; - agp_bridge.agp_enable = agp_generic_agp_enable; - agp_bridge.cache_flush = global_cache_flush; - agp_bridge.create_gatt_table = agp_generic_create_gatt_table; - agp_bridge.free_gatt_table = agp_generic_free_gatt_table; - agp_bridge.insert_memory = agp_generic_insert_memory; - agp_bridge.remove_memory = agp_generic_remove_memory; - agp_bridge.alloc_by_type = agp_generic_alloc_by_type; - agp_bridge.free_by_type = agp_generic_free_by_type; - agp_bridge.agp_alloc_page = agp_generic_alloc_page; - agp_bridge.agp_destroy_page = agp_generic_destroy_page; - agp_bridge.suspend = agp_generic_suspend; - agp_bridge.resume = agp_generic_resume; - agp_bridge.cant_use_aperture = 0; - - return 0; - - (void) pdev; /* unused */ -} - -static int __init intel_840_setup (struct pci_dev *pdev) -{ - agp_bridge.masks = intel_generic_masks; - agp_bridge.num_of_masks = 1; - agp_bridge.aperture_sizes = (void *) intel_8xx_sizes; - agp_bridge.size_type = U8_APER_SIZE; - agp_bridge.num_aperture_sizes = 7; - agp_bridge.dev_private_data = NULL; - agp_bridge.needs_scratch_page = FALSE; - agp_bridge.configure = intel_840_configure; - agp_bridge.fetch_size = intel_8xx_fetch_size; - agp_bridge.cleanup = intel_8xx_cleanup; - agp_bridge.tlb_flush = intel_8xx_tlbflush; - agp_bridge.mask_memory = intel_mask_memory; - agp_bridge.agp_enable = agp_generic_agp_enable; - agp_bridge.cache_flush = global_cache_flush; - agp_bridge.create_gatt_table = agp_generic_create_gatt_table; - agp_bridge.free_gatt_table = agp_generic_free_gatt_table; - agp_bridge.insert_memory = agp_generic_insert_memory; - agp_bridge.remove_memory = agp_generic_remove_memory; - agp_bridge.alloc_by_type = agp_generic_alloc_by_type; - agp_bridge.free_by_type = agp_generic_free_by_type; - agp_bridge.agp_alloc_page = agp_generic_alloc_page; - agp_bridge.agp_destroy_page = agp_generic_destroy_page; - agp_bridge.suspend = agp_generic_suspend; - agp_bridge.resume = agp_generic_resume; - agp_bridge.cant_use_aperture = 0; - - return 0; - - (void) pdev; /* unused */ -} - -static int __init intel_845_setup (struct pci_dev *pdev) -{ - agp_bridge.masks = intel_generic_masks; - agp_bridge.num_of_masks = 1; - agp_bridge.aperture_sizes = (void *) intel_8xx_sizes; - agp_bridge.size_type = U8_APER_SIZE; - agp_bridge.num_aperture_sizes = 7; - agp_bridge.dev_private_data = NULL; - agp_bridge.needs_scratch_page = FALSE; - agp_bridge.configure = intel_845_configure; - agp_bridge.fetch_size = intel_8xx_fetch_size; - agp_bridge.cleanup = intel_8xx_cleanup; - agp_bridge.tlb_flush = intel_8xx_tlbflush; - agp_bridge.mask_memory = intel_mask_memory; - agp_bridge.agp_enable = agp_generic_agp_enable; - agp_bridge.cache_flush = global_cache_flush; - agp_bridge.create_gatt_table = agp_generic_create_gatt_table; - agp_bridge.free_gatt_table = agp_generic_free_gatt_table; - agp_bridge.insert_memory = agp_generic_insert_memory; - agp_bridge.remove_memory = agp_generic_remove_memory; - agp_bridge.alloc_by_type = agp_generic_alloc_by_type; - agp_bridge.free_by_type = agp_generic_free_by_type; - agp_bridge.agp_alloc_page = agp_generic_alloc_page; - agp_bridge.agp_destroy_page = agp_generic_destroy_page; - agp_bridge.suspend = agp_generic_suspend; - agp_bridge.resume = agp_generic_resume; - agp_bridge.cant_use_aperture = 0; - - return 0; - - (void) pdev; /* unused */ -} - -static int __init intel_850_setup (struct pci_dev *pdev) -{ - agp_bridge.masks = intel_generic_masks; - agp_bridge.num_of_masks = 1; - agp_bridge.aperture_sizes = (void *) intel_8xx_sizes; - agp_bridge.size_type = U8_APER_SIZE; - agp_bridge.num_aperture_sizes = 7; - agp_bridge.dev_private_data = NULL; - agp_bridge.needs_scratch_page = FALSE; - agp_bridge.configure = intel_850_configure; - agp_bridge.fetch_size = intel_8xx_fetch_size; - agp_bridge.cleanup = intel_8xx_cleanup; - agp_bridge.tlb_flush = intel_8xx_tlbflush; - agp_bridge.mask_memory = intel_mask_memory; - agp_bridge.agp_enable = agp_generic_agp_enable; - agp_bridge.cache_flush = global_cache_flush; - agp_bridge.create_gatt_table = agp_generic_create_gatt_table; - agp_bridge.free_gatt_table = agp_generic_free_gatt_table; - agp_bridge.insert_memory = agp_generic_insert_memory; - agp_bridge.remove_memory = agp_generic_remove_memory; - agp_bridge.alloc_by_type = agp_generic_alloc_by_type; - agp_bridge.free_by_type = agp_generic_free_by_type; - agp_bridge.agp_alloc_page = agp_generic_alloc_page; - agp_bridge.agp_destroy_page = agp_generic_destroy_page; - agp_bridge.suspend = agp_generic_suspend; - agp_bridge.resume = agp_generic_resume; - agp_bridge.cant_use_aperture = 0; - - return 0; - - (void) pdev; /* unused */ -} - -static int __init intel_860_setup (struct pci_dev *pdev) -{ - agp_bridge.masks = intel_generic_masks; - agp_bridge.num_of_masks = 1; - agp_bridge.aperture_sizes = (void *) intel_8xx_sizes; - agp_bridge.size_type = U8_APER_SIZE; - agp_bridge.num_aperture_sizes = 7; - agp_bridge.dev_private_data = NULL; - agp_bridge.needs_scratch_page = FALSE; - agp_bridge.configure = intel_860_configure; - agp_bridge.fetch_size = intel_8xx_fetch_size; - agp_bridge.cleanup = intel_8xx_cleanup; - agp_bridge.tlb_flush = intel_8xx_tlbflush; - agp_bridge.mask_memory = intel_mask_memory; - agp_bridge.agp_enable = agp_generic_agp_enable; - agp_bridge.cache_flush = global_cache_flush; - agp_bridge.create_gatt_table = agp_generic_create_gatt_table; - agp_bridge.free_gatt_table = agp_generic_free_gatt_table; - agp_bridge.insert_memory = agp_generic_insert_memory; - agp_bridge.remove_memory = agp_generic_remove_memory; - agp_bridge.alloc_by_type = agp_generic_alloc_by_type; - agp_bridge.free_by_type = agp_generic_free_by_type; - agp_bridge.agp_alloc_page = agp_generic_alloc_page; - agp_bridge.agp_destroy_page = agp_generic_destroy_page; - agp_bridge.suspend = agp_generic_suspend; - agp_bridge.resume = agp_generic_resume; - agp_bridge.cant_use_aperture = 0; - - return 0; - - (void) pdev; /* unused */ -} - -#endif /* CONFIG_AGP_INTEL */ - -#ifdef CONFIG_AGP_VIA - -static int via_fetch_size(void) -{ - int i; - u8 temp; - aper_size_info_8 *values; - - values = A_SIZE_8(agp_bridge.aperture_sizes); - pci_read_config_byte(agp_bridge.dev, VIA_APSIZE, &temp); - for (i = 0; i < agp_bridge.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 int via_configure(void) -{ - u32 temp; - aper_size_info_8 *current_size; - - current_size = A_SIZE_8(agp_bridge.current_size); - /* aperture size */ - pci_write_config_byte(agp_bridge.dev, VIA_APSIZE, - current_size->size_value); - /* address to map too */ - pci_read_config_dword(agp_bridge.dev, VIA_APBASE, &temp); - agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - - /* GART control register */ - pci_write_config_dword(agp_bridge.dev, VIA_GARTCTRL, 0x0000000f); - - /* attbase - aperture GATT base */ - pci_write_config_dword(agp_bridge.dev, VIA_ATTBASE, - (agp_bridge.gatt_bus_addr & 0xfffff000) | 3); - return 0; -} - -static void via_cleanup(void) -{ - aper_size_info_8 *previous_size; - - previous_size = A_SIZE_8(agp_bridge.previous_size); - pci_write_config_byte(agp_bridge.dev, VIA_APSIZE, - previous_size->size_value); - /* Do not disable by writing 0 to VIA_ATTBASE, it screws things up - * during reinitialization. - */ -} - -static void via_tlbflush(agp_memory * mem) -{ - pci_write_config_dword(agp_bridge.dev, VIA_GARTCTRL, 0x0000008f); - pci_write_config_dword(agp_bridge.dev, VIA_GARTCTRL, 0x0000000f); -} - -static unsigned long via_mask_memory(unsigned long addr, int type) -{ - /* Memory type is ignored */ - - return addr | agp_bridge.masks[0].mask; -} - -static aper_size_info_8 via_generic_sizes[7] = -{ - {256, 65536, 6, 0}, - {128, 32768, 5, 128}, - {64, 16384, 4, 192}, - {32, 8192, 3, 224}, - {16, 4096, 2, 240}, - {8, 2048, 1, 248}, - {4, 1024, 0, 252} -}; - -static gatt_mask via_generic_masks[] = -{ - {0x00000000, 0} -}; - -static int __init via_generic_setup (struct pci_dev *pdev) -{ - agp_bridge.masks = via_generic_masks; - agp_bridge.num_of_masks = 1; - agp_bridge.aperture_sizes = (void *) via_generic_sizes; - agp_bridge.size_type = U8_APER_SIZE; - agp_bridge.num_aperture_sizes = 7; - agp_bridge.dev_private_data = NULL; - agp_bridge.needs_scratch_page = FALSE; - agp_bridge.configure = via_configure; - agp_bridge.fetch_size = via_fetch_size; - agp_bridge.cleanup = via_cleanup; - agp_bridge.tlb_flush = via_tlbflush; - agp_bridge.mask_memory = via_mask_memory; - agp_bridge.agp_enable = agp_generic_agp_enable; - agp_bridge.cache_flush = global_cache_flush; - agp_bridge.create_gatt_table = agp_generic_create_gatt_table; - agp_bridge.free_gatt_table = agp_generic_free_gatt_table; - agp_bridge.insert_memory = agp_generic_insert_memory; - agp_bridge.remove_memory = agp_generic_remove_memory; - agp_bridge.alloc_by_type = agp_generic_alloc_by_type; - agp_bridge.free_by_type = agp_generic_free_by_type; - agp_bridge.agp_alloc_page = agp_generic_alloc_page; - agp_bridge.agp_destroy_page = agp_generic_destroy_page; - agp_bridge.suspend = agp_generic_suspend; - agp_bridge.resume = agp_generic_resume; - agp_bridge.cant_use_aperture = 0; - - return 0; - - (void) pdev; /* unused */ -} - -#endif /* CONFIG_AGP_VIA */ - -#ifdef CONFIG_AGP_SIS - -static int sis_fetch_size(void) -{ - u8 temp_size; - int i; - aper_size_info_8 *values; - - pci_read_config_byte(agp_bridge.dev, SIS_APSIZE, &temp_size); - values = A_SIZE_8(agp_bridge.aperture_sizes); - for (i = 0; i < agp_bridge.num_aperture_sizes; i++) { - if ((temp_size == values[i].size_value) || - ((temp_size & ~(0x03)) == - (values[i].size_value & ~(0x03)))) { - 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 sis_tlbflush(agp_memory * mem) -{ - pci_write_config_byte(agp_bridge.dev, SIS_TLBFLUSH, 0x02); -} - -static int sis_configure(void) -{ - u32 temp; - aper_size_info_8 *current_size; - - current_size = A_SIZE_8(agp_bridge.current_size); - pci_write_config_byte(agp_bridge.dev, SIS_TLBCNTRL, 0x05); - pci_read_config_dword(agp_bridge.dev, SIS_APBASE, &temp); - agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - pci_write_config_dword(agp_bridge.dev, SIS_ATTBASE, - agp_bridge.gatt_bus_addr); - pci_write_config_byte(agp_bridge.dev, SIS_APSIZE, - current_size->size_value); - return 0; -} - -static void sis_cleanup(void) -{ - aper_size_info_8 *previous_size; - - previous_size = A_SIZE_8(agp_bridge.previous_size); - pci_write_config_byte(agp_bridge.dev, SIS_APSIZE, - (previous_size->size_value & ~(0x03))); -} - -static unsigned long sis_mask_memory(unsigned long addr, int type) -{ - /* Memory type is ignored */ - - return addr | agp_bridge.masks[0].mask; -} - -static aper_size_info_8 sis_generic_sizes[7] = -{ - {256, 65536, 6, 99}, - {128, 32768, 5, 83}, - {64, 16384, 4, 67}, - {32, 8192, 3, 51}, - {16, 4096, 2, 35}, - {8, 2048, 1, 19}, - {4, 1024, 0, 3} -}; - -static gatt_mask sis_generic_masks[] = -{ - {0x00000000, 0} -}; - -static int __init sis_generic_setup (struct pci_dev *pdev) -{ - agp_bridge.masks = sis_generic_masks; - agp_bridge.num_of_masks = 1; - agp_bridge.aperture_sizes = (void *) sis_generic_sizes; - agp_bridge.size_type = U8_APER_SIZE; - agp_bridge.num_aperture_sizes = 7; - agp_bridge.dev_private_data = NULL; - agp_bridge.needs_scratch_page = FALSE; - agp_bridge.configure = sis_configure; - agp_bridge.fetch_size = sis_fetch_size; - agp_bridge.cleanup = sis_cleanup; - agp_bridge.tlb_flush = sis_tlbflush; - agp_bridge.mask_memory = sis_mask_memory; - agp_bridge.agp_enable = agp_generic_agp_enable; - agp_bridge.cache_flush = global_cache_flush; - agp_bridge.create_gatt_table = agp_generic_create_gatt_table; - agp_bridge.free_gatt_table = agp_generic_free_gatt_table; - agp_bridge.insert_memory = agp_generic_insert_memory; - agp_bridge.remove_memory = agp_generic_remove_memory; - agp_bridge.alloc_by_type = agp_generic_alloc_by_type; - agp_bridge.free_by_type = agp_generic_free_by_type; - agp_bridge.agp_alloc_page = agp_generic_alloc_page; - agp_bridge.agp_destroy_page = agp_generic_destroy_page; - agp_bridge.suspend = agp_generic_suspend; - agp_bridge.resume = agp_generic_resume; - agp_bridge.cant_use_aperture = 0; - - return 0; -} - -#endif /* CONFIG_AGP_SIS */ - -#ifdef CONFIG_AGP_AMD - -typedef struct _amd_page_map { - unsigned long *real; - unsigned long *remapped; -} amd_page_map; - -static struct _amd_irongate_private { - volatile u8 *registers; - amd_page_map **gatt_pages; - int num_tables; -} amd_irongate_private; - -static int amd_create_page_map(amd_page_map *page_map) -{ - int i; - - page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL); - if (page_map->real == NULL) { - return -ENOMEM; - } - SetPageReserved(virt_to_page(page_map->real)); - CACHE_FLUSH(); - 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)); - free_page((unsigned long) page_map->real); - page_map->real = NULL; - return -ENOMEM; - } - CACHE_FLUSH(); - - for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { - page_map->remapped[i] = agp_bridge.scratch_page; - } - - return 0; -} - -static void amd_free_page_map(amd_page_map *page_map) -{ - iounmap(page_map->remapped); - ClearPageReserved(virt_to_page(page_map->real)); - free_page((unsigned long) page_map->real); -} - -static void amd_free_gatt_pages(void) -{ - int i; - amd_page_map **tables; - amd_page_map *entry; - - tables = amd_irongate_private.gatt_pages; - for(i = 0; i < amd_irongate_private.num_tables; i++) { - entry = tables[i]; - if (entry != NULL) { - if (entry->real != NULL) { - amd_free_page_map(entry); - } - kfree(entry); - } - } - kfree(tables); -} - -static int amd_create_gatt_pages(int nr_tables) -{ - amd_page_map **tables; - amd_page_map *entry; - int retval = 0; - int i; - - tables = kmalloc((nr_tables + 1) * sizeof(amd_page_map *), - GFP_KERNEL); - if (tables == NULL) { - return -ENOMEM; - } - memset(tables, 0, sizeof(amd_page_map *) * (nr_tables + 1)); - for (i = 0; i < nr_tables; i++) { - entry = kmalloc(sizeof(amd_page_map), GFP_KERNEL); - if (entry == NULL) { - retval = -ENOMEM; - break; - } - memset(entry, 0, sizeof(amd_page_map)); - tables[i] = entry; - retval = amd_create_page_map(entry); - if (retval != 0) break; - } - amd_irongate_private.num_tables = nr_tables; - amd_irongate_private.gatt_pages = tables; - - if (retval != 0) amd_free_gatt_pages(); - - return retval; -} - -/* Since we don't need contigious memory we just try - * 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) -#define GET_GATT(addr) (amd_irongate_private.gatt_pages[\ - GET_PAGE_DIR_IDX(addr)]->remapped) - -static int amd_create_gatt_table(void) -{ - aper_size_info_lvl2 *value; - amd_page_map page_dir; - unsigned long addr; - int retval; - u32 temp; - int i; - - value = A_SIZE_LVL2(agp_bridge.current_size); - retval = amd_create_page_map(&page_dir); - if (retval != 0) { - return retval; - } - - retval = amd_create_gatt_pages(value->num_entries / 1024); - if (retval != 0) { - amd_free_page_map(&page_dir); - return retval; - } - - agp_bridge.gatt_table_real = page_dir.real; - agp_bridge.gatt_table = page_dir.remapped; - agp_bridge.gatt_bus_addr = virt_to_phys(page_dir.real); - - /* 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, AMD_APBASE, &temp); - addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - agp_bridge.gart_bus_addr = addr; - - /* Calculate the agp offset */ - for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { - page_dir.remapped[GET_PAGE_DIR_OFF(addr)] = - virt_to_phys(amd_irongate_private.gatt_pages[i]->real); - page_dir.remapped[GET_PAGE_DIR_OFF(addr)] |= 0x00000001; - } - - return 0; -} - -static int amd_free_gatt_table(void) -{ - amd_page_map page_dir; - - page_dir.real = agp_bridge.gatt_table_real; - page_dir.remapped = agp_bridge.gatt_table; - - amd_free_gatt_pages(); - amd_free_page_map(&page_dir); - return 0; -} - -static int amd_irongate_fetch_size(void) -{ - int i; - u32 temp; - aper_size_info_lvl2 *values; - - pci_read_config_dword(agp_bridge.dev, AMD_APSIZE, &temp); - temp = (temp & 0x0000000e); - values = A_SIZE_LVL2(agp_bridge.aperture_sizes); - for (i = 0; i < agp_bridge.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 int amd_irongate_configure(void) -{ - aper_size_info_lvl2 *current_size; - u32 temp; - u16 enable_reg; - - current_size = A_SIZE_LVL2(agp_bridge.current_size); - - /* Get the memory mapped registers */ - pci_read_config_dword(agp_bridge.dev, AMD_MMBASE, &temp); - temp = (temp & PCI_BASE_ADDRESS_MEM_MASK); - amd_irongate_private.registers = (volatile u8 *) ioremap(temp, 4096); - - /* Write out the address of the gatt table */ - OUTREG32(amd_irongate_private.registers, AMD_ATTBASE, - agp_bridge.gatt_bus_addr); - - /* 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); - - /* Write the enable register */ - enable_reg = INREG16(amd_irongate_private.registers, AMD_GARTENABLE); - enable_reg = (enable_reg | 0x0004); - OUTREG16(amd_irongate_private.registers, AMD_GARTENABLE, enable_reg); - - /* Write out the size register */ - pci_read_config_dword(agp_bridge.dev, AMD_APSIZE, &temp); - temp = (((temp & ~(0x0000000e)) | current_size->size_value) - | 0x00000001); - pci_write_config_dword(agp_bridge.dev, AMD_APSIZE, temp); - - /* Flush the tlb */ - OUTREG32(amd_irongate_private.registers, AMD_TLBFLUSH, 0x00000001); - - return 0; -} - -static void amd_irongate_cleanup(void) -{ - aper_size_info_lvl2 *previous_size; - u32 temp; - u16 enable_reg; - - previous_size = A_SIZE_LVL2(agp_bridge.previous_size); - - enable_reg = INREG16(amd_irongate_private.registers, AMD_GARTENABLE); - enable_reg = (enable_reg & ~(0x0004)); - OUTREG16(amd_irongate_private.registers, AMD_GARTENABLE, enable_reg); - - /* Write back the previous size and disable gart translation */ - pci_read_config_dword(agp_bridge.dev, AMD_APSIZE, &temp); - temp = ((temp & ~(0x0000000f)) | previous_size->size_value); - pci_write_config_dword(agp_bridge.dev, AMD_APSIZE, temp); - iounmap((void *) amd_irongate_private.registers); -} - -/* - * This routine could be implemented by taking the addresses - * written to the GATT, and flushing them individually. However - * currently it just flushes the whole table. Which is probably - * more efficent, since agp_memory blocks can be a large number of - * entries. - */ - -static void amd_irongate_tlbflush(agp_memory * temp) -{ - OUTREG32(amd_irongate_private.registers, AMD_TLBFLUSH, 0x00000001); -} - -static unsigned long amd_irongate_mask_memory(unsigned long addr, int type) -{ - /* Only type 0 is supported by the irongate */ - - return addr | agp_bridge.masks[0].mask; -} - -static int amd_insert_memory(agp_memory * mem, - off_t pg_start, int type) -{ - int i, j, num_entries; - unsigned long *cur_gatt; - unsigned long addr; - - num_entries = A_SIZE_LVL2(agp_bridge.current_size)->num_entries; - - if (type != 0 || mem->type != 0) { - return -EINVAL; - } - 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(cur_gatt[GET_GATT_OFF(addr)])) { - return -EBUSY; - } - j++; - } - - if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); - mem->is_flushed = TRUE; - } - - 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); - cur_gatt[GET_GATT_OFF(addr)] = mem->memory[i]; - } - agp_bridge.tlb_flush(mem); - return 0; -} - -static int amd_remove_memory(agp_memory * mem, off_t pg_start, - int type) -{ - int i; - unsigned long *cur_gatt; - unsigned long addr; - - if (type != 0 || mem->type != 0) { - return -EINVAL; - } - 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); - cur_gatt[GET_GATT_OFF(addr)] = - (unsigned long) agp_bridge.scratch_page; - } - - agp_bridge.tlb_flush(mem); - return 0; -} - -static aper_size_info_lvl2 amd_irongate_sizes[7] = -{ - {2048, 524288, 0x0000000c}, - {1024, 262144, 0x0000000a}, - {512, 131072, 0x00000008}, - {256, 65536, 0x00000006}, - {128, 32768, 0x00000004}, - {64, 16384, 0x00000002}, - {32, 8192, 0x00000000} -}; - -static gatt_mask amd_irongate_masks[] = -{ - {0x00000001, 0} -}; - -static int __init amd_irongate_setup (struct pci_dev *pdev) -{ - agp_bridge.masks = amd_irongate_masks; - agp_bridge.num_of_masks = 1; - agp_bridge.aperture_sizes = (void *) amd_irongate_sizes; - agp_bridge.size_type = LVL2_APER_SIZE; - agp_bridge.num_aperture_sizes = 7; - agp_bridge.dev_private_data = (void *) &amd_irongate_private; - agp_bridge.needs_scratch_page = FALSE; - agp_bridge.configure = amd_irongate_configure; - agp_bridge.fetch_size = amd_irongate_fetch_size; - agp_bridge.cleanup = amd_irongate_cleanup; - agp_bridge.tlb_flush = amd_irongate_tlbflush; - agp_bridge.mask_memory = amd_irongate_mask_memory; - agp_bridge.agp_enable = agp_generic_agp_enable; - agp_bridge.cache_flush = global_cache_flush; - agp_bridge.create_gatt_table = amd_create_gatt_table; - agp_bridge.free_gatt_table = amd_free_gatt_table; - agp_bridge.insert_memory = amd_insert_memory; - agp_bridge.remove_memory = amd_remove_memory; - agp_bridge.alloc_by_type = agp_generic_alloc_by_type; - agp_bridge.free_by_type = agp_generic_free_by_type; - agp_bridge.agp_alloc_page = agp_generic_alloc_page; - agp_bridge.agp_destroy_page = agp_generic_destroy_page; - agp_bridge.suspend = agp_generic_suspend; - agp_bridge.resume = agp_generic_resume; - agp_bridge.cant_use_aperture = 0; - - return 0; - - (void) pdev; /* unused */ -} - -#endif /* CONFIG_AGP_AMD */ - -#ifdef CONFIG_AGP_ALI - -static int ali_fetch_size(void) -{ - int i; - u32 temp; - aper_size_info_32 *values; - - pci_read_config_dword(agp_bridge.dev, ALI_ATTBASE, &temp); - temp &= ~(0xfffffff0); - values = A_SIZE_32(agp_bridge.aperture_sizes); - - for (i = 0; i < agp_bridge.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 ali_tlbflush(agp_memory * mem) -{ - u32 temp; - - pci_read_config_dword(agp_bridge.dev, ALI_TLBCTRL, &temp); -// clear tag - pci_write_config_dword(agp_bridge.dev, ALI_TAGCTRL, - ((temp & 0xfffffff0) | 0x00000001|0x00000002)); -} - -static void ali_cleanup(void) -{ - aper_size_info_32 *previous_size; - u32 temp; - - previous_size = A_SIZE_32(agp_bridge.previous_size); - - pci_read_config_dword(agp_bridge.dev, ALI_TLBCTRL, &temp); -// clear tag - pci_write_config_dword(agp_bridge.dev, ALI_TAGCTRL, - ((temp & 0xffffff00) | 0x00000001|0x00000002)); - - pci_read_config_dword(agp_bridge.dev, ALI_ATTBASE, &temp); - pci_write_config_dword(agp_bridge.dev, ALI_ATTBASE, - ((temp & 0x00000ff0) | previous_size->size_value)); -} - -static int ali_configure(void) -{ - u32 temp; - aper_size_info_32 *current_size; - - current_size = A_SIZE_32(agp_bridge.current_size); - - /* aperture size and gatt addr */ - pci_read_config_dword(agp_bridge.dev, ALI_ATTBASE, &temp); - temp = (((temp & 0x00000ff0) | (agp_bridge.gatt_bus_addr & 0xfffff000)) - | (current_size->size_value & 0xf)); - pci_write_config_dword(agp_bridge.dev, ALI_ATTBASE, temp); - - /* tlb control */ - - /* - * Question: Jeff, ALi's patch deletes this: - * - * pci_read_config_dword(agp_bridge.dev, ALI_TLBCTRL, &temp); - * pci_write_config_dword(agp_bridge.dev, ALI_TLBCTRL, - * ((temp & 0xffffff00) | 0x00000010)); - * - * and replaces it with the following, which seems to duplicate the - * next couple of lines below it. I suspect this was an oversight, - * but you might want to check up on this? - */ - - pci_read_config_dword(agp_bridge.dev, ALI_APBASE, &temp); - agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - - /* address to map to */ - pci_read_config_dword(agp_bridge.dev, ALI_APBASE, &temp); - agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - -#if 0 - if (agp_bridge.type == ALI_M1541) { - u32 nlvm_addr = 0; - - switch (current_size->size_value) { - case 0: break; - case 1: nlvm_addr = 0x100000;break; - case 2: nlvm_addr = 0x200000;break; - case 3: nlvm_addr = 0x400000;break; - case 4: nlvm_addr = 0x800000;break; - case 6: nlvm_addr = 0x1000000;break; - case 7: nlvm_addr = 0x2000000;break; - case 8: nlvm_addr = 0x4000000;break; - case 9: nlvm_addr = 0x8000000;break; - case 10: nlvm_addr = 0x10000000;break; - default: break; - } - nlvm_addr--; - nlvm_addr&=0xfff00000; - - nlvm_addr+= agp_bridge.gart_bus_addr; - nlvm_addr|=(agp_bridge.gart_bus_addr>>12); - printk(KERN_INFO PFX "nlvm top &base = %8x\n",nlvm_addr); - } -#endif - - pci_read_config_dword(agp_bridge.dev, ALI_TLBCTRL, &temp); - temp &= 0xffffff7f; //enable TLB - pci_write_config_dword(agp_bridge.dev, ALI_TLBCTRL, temp); - - return 0; -} - -static unsigned long ali_mask_memory(unsigned long addr, int type) -{ - /* Memory type is ignored */ - - return addr | agp_bridge.masks[0].mask; -} - -static void ali_cache_flush(void) -{ - global_cache_flush(); - - if (agp_bridge.type == ALI_M1541) { - int i, page_count; - u32 temp; - - page_count = 1 << A_SIZE_32(agp_bridge.current_size)->page_order; - for (i = 0; i < PAGE_SIZE * page_count; i += PAGE_SIZE) { - pci_read_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, &temp); - pci_write_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, - (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | - (agp_bridge.gatt_bus_addr + i)) | - ALI_CACHE_FLUSH_EN)); - } - } -} - -static void *ali_alloc_page(void) -{ - void *adr = agp_generic_alloc_page(); - unsigned temp; - - if (adr == 0) - return 0; - - if (agp_bridge.type == ALI_M1541) { - pci_read_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, &temp); - pci_write_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, - (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | - virt_to_phys(adr)) | - ALI_CACHE_FLUSH_EN )); - } - return adr; -} - -static void ali_destroy_page(void * addr) -{ - u32 temp; - - if (addr == NULL) - return; - - global_cache_flush(); - - if (agp_bridge.type == ALI_M1541) { - pci_read_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, &temp); - pci_write_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, - (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | - virt_to_phys(addr)) | - ALI_CACHE_FLUSH_EN)); - } - - agp_generic_destroy_page(addr); -} - -/* Setup function */ -static gatt_mask ali_generic_masks[] = -{ - {0x00000000, 0} -}; - -static aper_size_info_32 ali_generic_sizes[7] = -{ - {256, 65536, 6, 10}, - {128, 32768, 5, 9}, - {64, 16384, 4, 8}, - {32, 8192, 3, 7}, - {16, 4096, 2, 6}, - {8, 2048, 1, 4}, - {4, 1024, 0, 3} -}; - -static int __init ali_generic_setup (struct pci_dev *pdev) -{ - agp_bridge.masks = ali_generic_masks; - agp_bridge.num_of_masks = 1; - agp_bridge.aperture_sizes = (void *) ali_generic_sizes; - agp_bridge.size_type = U32_APER_SIZE; - agp_bridge.num_aperture_sizes = 7; - agp_bridge.dev_private_data = NULL; - agp_bridge.needs_scratch_page = FALSE; - agp_bridge.configure = ali_configure; - agp_bridge.fetch_size = ali_fetch_size; - agp_bridge.cleanup = ali_cleanup; - agp_bridge.tlb_flush = ali_tlbflush; - agp_bridge.mask_memory = ali_mask_memory; - agp_bridge.agp_enable = agp_generic_agp_enable; - agp_bridge.cache_flush = ali_cache_flush; - agp_bridge.create_gatt_table = agp_generic_create_gatt_table; - agp_bridge.free_gatt_table = agp_generic_free_gatt_table; - agp_bridge.insert_memory = agp_generic_insert_memory; - agp_bridge.remove_memory = agp_generic_remove_memory; - agp_bridge.alloc_by_type = agp_generic_alloc_by_type; - agp_bridge.free_by_type = agp_generic_free_by_type; - agp_bridge.agp_alloc_page = ali_alloc_page; - agp_bridge.agp_destroy_page = ali_destroy_page; - agp_bridge.suspend = agp_generic_suspend; - agp_bridge.resume = agp_generic_resume; - agp_bridge.cant_use_aperture = 0; - - return 0; - - (void) pdev; /* unused */ -} - -#endif /* CONFIG_AGP_ALI */ - -#ifdef CONFIG_AGP_SWORKS -typedef struct _serverworks_page_map { - unsigned long *real; - unsigned long *remapped; -} serverworks_page_map; - -static struct _serverworks_private { - struct pci_dev *svrwrks_dev; /* device one */ - volatile u8 *registers; - serverworks_page_map **gatt_pages; - int num_tables; - serverworks_page_map scratch_dir; - - int gart_addr_ofs; - int mm_addr_ofs; -} serverworks_private; - -static int serverworks_create_page_map(serverworks_page_map *page_map) -{ - int i; - - page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL); - if (page_map->real == NULL) { - return -ENOMEM; - } - SetPageReserved(virt_to_page(page_map->real)); - CACHE_FLUSH(); - 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)); - free_page((unsigned long) page_map->real); - page_map->real = NULL; - return -ENOMEM; - } - CACHE_FLUSH(); - - for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { - page_map->remapped[i] = agp_bridge.scratch_page; - } - - return 0; -} - -static void serverworks_free_page_map(serverworks_page_map *page_map) -{ - iounmap(page_map->remapped); - ClearPageReserved(virt_to_page(page_map->real)); - free_page((unsigned long) page_map->real); -} - -static void serverworks_free_gatt_pages(void) -{ - int i; - serverworks_page_map **tables; - serverworks_page_map *entry; - - tables = serverworks_private.gatt_pages; - for(i = 0; i < serverworks_private.num_tables; i++) { - entry = tables[i]; - if (entry != NULL) { - if (entry->real != NULL) { - serverworks_free_page_map(entry); - } - kfree(entry); - } - } - kfree(tables); -} - -static int serverworks_create_gatt_pages(int nr_tables) -{ - serverworks_page_map **tables; - serverworks_page_map *entry; - int retval = 0; - int i; - - tables = kmalloc((nr_tables + 1) * sizeof(serverworks_page_map *), - GFP_KERNEL); - if (tables == NULL) { - return -ENOMEM; - } - memset(tables, 0, sizeof(serverworks_page_map *) * (nr_tables + 1)); - for (i = 0; i < nr_tables; i++) { - entry = kmalloc(sizeof(serverworks_page_map), GFP_KERNEL); - if (entry == NULL) { - retval = -ENOMEM; - break; - } - memset(entry, 0, sizeof(serverworks_page_map)); - tables[i] = entry; - retval = serverworks_create_page_map(entry); - if (retval != 0) break; - } - serverworks_private.num_tables = nr_tables; - serverworks_private.gatt_pages = tables; - - if (retval != 0) serverworks_free_gatt_pages(); - - return retval; -} - -#define SVRWRKS_GET_GATT(addr) (serverworks_private.gatt_pages[\ - GET_PAGE_DIR_IDX(addr)]->remapped) - -#ifndef GET_PAGE_DIR_OFF -#define GET_PAGE_DIR_OFF(addr) (addr >> 22) -#endif - -#ifndef GET_PAGE_DIR_IDX -#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \ - GET_PAGE_DIR_OFF(agp_bridge.gart_bus_addr)) -#endif - -#ifndef GET_GATT_OFF -#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) -#endif - -static int serverworks_create_gatt_table(void) -{ - aper_size_info_lvl2 *value; - serverworks_page_map page_dir; - int retval; - u32 temp; - int i; - - value = A_SIZE_LVL2(agp_bridge.current_size); - retval = serverworks_create_page_map(&page_dir); - if (retval != 0) { - return retval; - } - retval = serverworks_create_page_map(&serverworks_private.scratch_dir); - if (retval != 0) { - serverworks_free_page_map(&page_dir); - return retval; - } - /* Create a fake scratch directory */ - for(i = 0; i < 1024; i++) { - serverworks_private.scratch_dir.remapped[i] = (unsigned long) agp_bridge.scratch_page; - page_dir.remapped[i] = - virt_to_phys(serverworks_private.scratch_dir.real); - page_dir.remapped[i] |= 0x00000001; - } - - retval = serverworks_create_gatt_pages(value->num_entries / 1024); - if (retval != 0) { - serverworks_free_page_map(&page_dir); - serverworks_free_page_map(&serverworks_private.scratch_dir); - return retval; - } - - agp_bridge.gatt_table_real = page_dir.real; - agp_bridge.gatt_table = page_dir.remapped; - agp_bridge.gatt_bus_addr = virt_to_phys(page_dir.real); - - /* 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, - serverworks_private.gart_addr_ofs, - &temp); - agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - - /* Calculate the agp offset */ - - for(i = 0; i < value->num_entries / 1024; i++) { - page_dir.remapped[i] = - virt_to_phys(serverworks_private.gatt_pages[i]->real); - page_dir.remapped[i] |= 0x00000001; - } - - return 0; -} - -static int serverworks_free_gatt_table(void) -{ - serverworks_page_map page_dir; - - page_dir.real = agp_bridge.gatt_table_real; - page_dir.remapped = agp_bridge.gatt_table; - - serverworks_free_gatt_pages(); - serverworks_free_page_map(&page_dir); - serverworks_free_page_map(&serverworks_private.scratch_dir); - return 0; -} - -static int serverworks_fetch_size(void) -{ - int i; - u32 temp; - u32 temp2; - aper_size_info_lvl2 *values; - - values = A_SIZE_LVL2(agp_bridge.aperture_sizes); - pci_read_config_dword(agp_bridge.dev, - serverworks_private.gart_addr_ofs, - &temp); - pci_write_config_dword(agp_bridge.dev, - serverworks_private.gart_addr_ofs, - SVWRKS_SIZE_MASK); - pci_read_config_dword(agp_bridge.dev, - serverworks_private.gart_addr_ofs, - &temp2); - pci_write_config_dword(agp_bridge.dev, - serverworks_private.gart_addr_ofs, - temp); - temp2 &= SVWRKS_SIZE_MASK; - - for (i = 0; i < agp_bridge.num_aperture_sizes; i++) { - if (temp2 == 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 int serverworks_configure(void) -{ - aper_size_info_lvl2 *current_size; - u32 temp; - u8 enable_reg; - u8 cap_ptr; - u32 cap_id; - u16 cap_reg; - - current_size = A_SIZE_LVL2(agp_bridge.current_size); - - /* Get the memory mapped registers */ - pci_read_config_dword(agp_bridge.dev, - serverworks_private.mm_addr_ofs, - &temp); - temp = (temp & PCI_BASE_ADDRESS_MEM_MASK); - serverworks_private.registers = (volatile u8 *) ioremap(temp, 4096); - - OUTREG8(serverworks_private.registers, SVWRKS_GART_CACHE, 0x0a); - - OUTREG32(serverworks_private.registers, SVWRKS_GATTBASE, - agp_bridge.gatt_bus_addr); - - cap_reg = INREG16(serverworks_private.registers, SVWRKS_COMMAND); - cap_reg &= ~0x0007; - cap_reg |= 0x4; - OUTREG16(serverworks_private.registers, SVWRKS_COMMAND, cap_reg); - - pci_read_config_byte(serverworks_private.svrwrks_dev, - SVWRKS_AGP_ENABLE, &enable_reg); - enable_reg |= 0x1; /* Agp Enable bit */ - pci_write_config_byte(serverworks_private.svrwrks_dev, - SVWRKS_AGP_ENABLE, enable_reg); - agp_bridge.tlb_flush(NULL); - - pci_read_config_byte(serverworks_private.svrwrks_dev, 0x34, &cap_ptr); - if (cap_ptr != 0x00) { - do { - pci_read_config_dword(serverworks_private.svrwrks_dev, - cap_ptr, &cap_id); - - if ((cap_id & 0xff) != 0x02) - cap_ptr = (cap_id >> 8) & 0xff; - } - while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00)); - } - agp_bridge.capndx = cap_ptr; - - /* Fill in the mode register */ - pci_read_config_dword(serverworks_private.svrwrks_dev, - agp_bridge.capndx + 4, - &agp_bridge.mode); - - pci_read_config_byte(agp_bridge.dev, - SVWRKS_CACHING, - &enable_reg); - enable_reg &= ~0x3; - pci_write_config_byte(agp_bridge.dev, - SVWRKS_CACHING, - enable_reg); - - pci_read_config_byte(agp_bridge.dev, - SVWRKS_FEATURE, - &enable_reg); - enable_reg |= (1<<6); - pci_write_config_byte(agp_bridge.dev, - SVWRKS_FEATURE, - enable_reg); - - return 0; -} - -static void serverworks_cleanup(void) -{ - iounmap((void *) serverworks_private.registers); -} - -/* - * This routine could be implemented by taking the addresses - * written to the GATT, and flushing them individually. However - * currently it just flushes the whole table. Which is probably - * more efficent, since agp_memory blocks can be a large number of - * entries. - */ - -static void serverworks_tlbflush(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 "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 "TLB flush took more" - "then 3 seconds\n"); - } - } -} - -static unsigned long serverworks_mask_memory(unsigned long addr, int type) -{ - /* Only type 0 is supported by the serverworks chipsets */ - - return addr | agp_bridge.masks[0].mask; -} - -static int serverworks_insert_memory(agp_memory * mem, - off_t pg_start, int type) -{ - int i, j, num_entries; - unsigned long *cur_gatt; - unsigned long addr; - - num_entries = A_SIZE_LVL2(agp_bridge.current_size)->num_entries; - - if (type != 0 || mem->type != 0) { - return -EINVAL; - } - 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 = SVRWRKS_GET_GATT(addr); - if (!PGE_EMPTY(cur_gatt[GET_GATT_OFF(addr)])) { - return -EBUSY; - } - j++; - } - - if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); - mem->is_flushed = TRUE; - } - - for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { - addr = (j * PAGE_SIZE) + agp_bridge.gart_bus_addr; - cur_gatt = SVRWRKS_GET_GATT(addr); - cur_gatt[GET_GATT_OFF(addr)] = mem->memory[i]; - } - agp_bridge.tlb_flush(mem); - return 0; -} - -static int serverworks_remove_memory(agp_memory * mem, off_t pg_start, - int type) -{ - int i; - unsigned long *cur_gatt; - unsigned long addr; - - if (type != 0 || mem->type != 0) { - return -EINVAL; - } - - CACHE_FLUSH(); - agp_bridge.tlb_flush(mem); - - for (i = pg_start; i < (mem->page_count + pg_start); i++) { - addr = (i * PAGE_SIZE) + agp_bridge.gart_bus_addr; - cur_gatt = SVRWRKS_GET_GATT(addr); - cur_gatt[GET_GATT_OFF(addr)] = - (unsigned long) agp_bridge.scratch_page; - } - - agp_bridge.tlb_flush(mem); - return 0; -} - -static gatt_mask serverworks_masks[] = -{ - {0x00000001, 0} -}; - -static aper_size_info_lvl2 serverworks_sizes[7] = -{ - {2048, 524288, 0x80000000}, - {1024, 262144, 0xc0000000}, - {512, 131072, 0xe0000000}, - {256, 65536, 0xf0000000}, - {128, 32768, 0xf8000000}, - {64, 16384, 0xfc000000}, - {32, 8192, 0xfe000000} -}; - -static void serverworks_agp_enable(u32 mode) -{ - struct pci_dev *device = NULL; - u32 command, scratch, cap_id; - u8 cap_ptr; - - pci_read_config_dword(serverworks_private.svrwrks_dev, - agp_bridge.capndx + 4, - &command); - - /* - * PASS1: go throu all devices that claim to be - * AGP devices and collect their data. - */ - - - pci_for_each_dev(device) { - cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); - if (cap_ptr != 0x00) { - do { - pci_read_config_dword(device, - cap_ptr, &cap_id); - - if ((cap_id & 0xff) != 0x02) - cap_ptr = (cap_id >> 8) & 0xff; - } - while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00)); - } - if (cap_ptr != 0x00) { - /* - * Ok, here we have a AGP device. Disable impossible - * settings, and adjust the readqueue to the minimum. - */ - - pci_read_config_dword(device, cap_ptr + 4, &scratch); - - /* adjust RQ depth */ - command = - ((command & ~0xff000000) | - min_t(u32, (mode & 0xff000000), - min_t(u32, (command & 0xff000000), - (scratch & 0xff000000)))); - - /* disable SBA if it's not supported */ - if (!((command & 0x00000200) && - (scratch & 0x00000200) && - (mode & 0x00000200))) - command &= ~0x00000200; - - /* disable FW */ - command &= ~0x00000010; - - command &= ~0x00000008; - - if (!((command & 4) && - (scratch & 4) && - (mode & 4))) - command &= ~0x00000004; - - if (!((command & 2) && - (scratch & 2) && - (mode & 2))) - command &= ~0x00000002; - - if (!((command & 1) && - (scratch & 1) && - (mode & 1))) - command &= ~0x00000001; - } - } - /* - * PASS2: Figure out the 4X/2X/1X setting and enable the - * target (our motherboard chipset). - */ - - if (command & 4) { - command &= ~3; /* 4X */ - } - if (command & 2) { - command &= ~5; /* 2X */ - } - if (command & 1) { - command &= ~6; /* 1X */ - } - command |= 0x00000100; - - pci_write_config_dword(serverworks_private.svrwrks_dev, - agp_bridge.capndx + 8, - command); - - /* - * PASS3: Go throu all AGP devices and update the - * command registers. - */ - - pci_for_each_dev(device) { - cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); - if (cap_ptr != 0x00) - pci_write_config_dword(device, cap_ptr + 8, command); - } -} - -static int __init serverworks_setup (struct pci_dev *pdev) -{ - u32 temp; - u32 temp2; - - serverworks_private.svrwrks_dev = pdev; - - agp_bridge.masks = serverworks_masks; - agp_bridge.num_of_masks = 1; - agp_bridge.aperture_sizes = (void *) serverworks_sizes; - agp_bridge.size_type = LVL2_APER_SIZE; - agp_bridge.num_aperture_sizes = 7; - agp_bridge.dev_private_data = (void *) &serverworks_private; - agp_bridge.needs_scratch_page = TRUE; - agp_bridge.configure = serverworks_configure; - agp_bridge.fetch_size = serverworks_fetch_size; - agp_bridge.cleanup = serverworks_cleanup; - agp_bridge.tlb_flush = serverworks_tlbflush; - agp_bridge.mask_memory = serverworks_mask_memory; - agp_bridge.agp_enable = serverworks_agp_enable; - agp_bridge.cache_flush = global_cache_flush; - agp_bridge.create_gatt_table = serverworks_create_gatt_table; - agp_bridge.free_gatt_table = serverworks_free_gatt_table; - agp_bridge.insert_memory = serverworks_insert_memory; - agp_bridge.remove_memory = serverworks_remove_memory; - agp_bridge.alloc_by_type = agp_generic_alloc_by_type; - agp_bridge.free_by_type = agp_generic_free_by_type; - agp_bridge.agp_alloc_page = agp_generic_alloc_page; - agp_bridge.agp_destroy_page = agp_generic_destroy_page; - agp_bridge.suspend = agp_generic_suspend; - agp_bridge.resume = agp_generic_resume; - agp_bridge.cant_use_aperture = 0; - - pci_read_config_dword(agp_bridge.dev, - SVWRKS_APSIZE, - &temp); - - serverworks_private.gart_addr_ofs = 0x10; - - if(temp & PCI_BASE_ADDRESS_MEM_TYPE_64) { - pci_read_config_dword(agp_bridge.dev, - SVWRKS_APSIZE + 4, - &temp2); - if(temp2 != 0) { - printk("Detected 64 bit aperture address, but top " - "bits are not zero. Disabling agp\n"); - return -ENODEV; - } - serverworks_private.mm_addr_ofs = 0x18; - } else { - serverworks_private.mm_addr_ofs = 0x14; - } - - pci_read_config_dword(agp_bridge.dev, - serverworks_private.mm_addr_ofs, - &temp); - if(temp & PCI_BASE_ADDRESS_MEM_TYPE_64) { - pci_read_config_dword(agp_bridge.dev, - serverworks_private.mm_addr_ofs + 4, - &temp2); - if(temp2 != 0) { - printk("Detected 64 bit MMIO address, but top " - "bits are not zero. Disabling agp\n"); - return -ENODEV; - } - } - - return 0; -} - -#endif /* CONFIG_AGP_SWORKS */ - -#ifdef CONFIG_AGP_HP_ZX1 - -#ifndef log2 -#define log2(x) ffz(~(x)) -#endif - -#define HP_ZX1_IOVA_BASE GB(1UL) -#define HP_ZX1_IOVA_SIZE GB(1UL) -#define HP_ZX1_GART_SIZE (HP_ZX1_IOVA_SIZE / 2) -#define HP_ZX1_SBA_IOMMU_COOKIE 0x0000badbadc0ffeeUL - -#define HP_ZX1_PDIR_VALID_BIT 0x8000000000000000UL -#define HP_ZX1_IOVA_TO_PDIR(va) ((va - hp_private.iova_base) >> \ - hp_private.io_tlb_shift) - -static aper_size_info_fixed hp_zx1_sizes[] = -{ - {0, 0, 0}, /* filled in by hp_zx1_fetch_size() */ -}; - -static gatt_mask hp_zx1_masks[] = -{ - {HP_ZX1_PDIR_VALID_BIT, 0} -}; - -static struct _hp_private { - struct pci_dev *ioc; - volatile u8 *registers; - u64 *io_pdir; // PDIR for entire IOVA - u64 *gatt; // PDIR just for GART (subset of above) - u64 gatt_entries; - u64 iova_base; - u64 gart_base; - u64 gart_size; - u64 io_pdir_size; - int io_pdir_owner; // do we own it, or share it with sba_iommu? - int io_page_size; - int io_tlb_shift; - int io_tlb_ps; // IOC ps config - int io_pages_per_kpage; -} hp_private; - -static int __init hp_zx1_ioc_shared(void) -{ - struct _hp_private *hp = &hp_private; - - printk(KERN_INFO PFX "HP ZX1 IOC: IOPDIR shared with sba_iommu\n"); - - /* - * IOC already configured by sba_iommu module; just use - * its setup. We assume: - * - IOVA space is 1Gb in size - * - first 512Mb is IOMMU, second 512Mb is GART - */ - hp->io_tlb_ps = INREG64(hp->registers, HP_ZX1_TCNFG); - switch (hp->io_tlb_ps) { - case 0: hp->io_tlb_shift = 12; break; - case 1: hp->io_tlb_shift = 13; break; - case 2: hp->io_tlb_shift = 14; break; - case 3: hp->io_tlb_shift = 16; break; - default: - printk(KERN_ERR PFX "Invalid IOTLB page size " - "configuration 0x%x\n", hp->io_tlb_ps); - hp->gatt = 0; - hp->gatt_entries = 0; - return -ENODEV; - } - hp->io_page_size = 1 << hp->io_tlb_shift; - hp->io_pages_per_kpage = PAGE_SIZE / hp->io_page_size; - - hp->iova_base = INREG64(hp->registers, HP_ZX1_IBASE) & ~0x1; - hp->gart_base = hp->iova_base + HP_ZX1_IOVA_SIZE - HP_ZX1_GART_SIZE; - - hp->gart_size = HP_ZX1_GART_SIZE; - hp->gatt_entries = hp->gart_size / hp->io_page_size; - - hp->io_pdir = phys_to_virt(INREG64(hp->registers, HP_ZX1_PDIR_BASE)); - hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)]; - - if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) { - hp->gatt = 0; - hp->gatt_entries = 0; - printk(KERN_ERR PFX "No reserved IO PDIR entry found; " - "GART disabled\n"); - return -ENODEV; - } - - return 0; -} - -static int __init hp_zx1_ioc_owner(u8 ioc_rev) -{ - struct _hp_private *hp = &hp_private; - - printk(KERN_INFO PFX "HP ZX1 IOC: IOPDIR dedicated to GART\n"); - - /* - * Select an IOV page size no larger than system page size. - */ - if (PAGE_SIZE >= KB(64)) { - hp->io_tlb_shift = 16; - hp->io_tlb_ps = 3; - } else if (PAGE_SIZE >= KB(16)) { - hp->io_tlb_shift = 14; - hp->io_tlb_ps = 2; - } else if (PAGE_SIZE >= KB(8)) { - hp->io_tlb_shift = 13; - hp->io_tlb_ps = 1; - } else { - hp->io_tlb_shift = 12; - hp->io_tlb_ps = 0; - } - hp->io_page_size = 1 << hp->io_tlb_shift; - hp->io_pages_per_kpage = PAGE_SIZE / hp->io_page_size; - - hp->iova_base = HP_ZX1_IOVA_BASE; - hp->gart_size = HP_ZX1_GART_SIZE; - hp->gart_base = hp->iova_base + HP_ZX1_IOVA_SIZE - hp->gart_size; - - hp->gatt_entries = hp->gart_size / hp->io_page_size; - hp->io_pdir_size = (HP_ZX1_IOVA_SIZE / hp->io_page_size) * sizeof(u64); - - return 0; -} - -static int __init hp_zx1_ioc_init(void) -{ - struct _hp_private *hp = &hp_private; - struct pci_dev *ioc; - int i; - u8 ioc_rev; - - ioc = pci_find_device(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_ZX1_IOC, NULL); - if (!ioc) { - printk(KERN_ERR PFX "Detected HP ZX1 AGP bridge but no IOC\n"); - return -ENODEV; - } - hp->ioc = ioc; - - pci_read_config_byte(ioc, PCI_REVISION_ID, &ioc_rev); - - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - if (pci_resource_flags(ioc, i) == IORESOURCE_MEM) { - hp->registers = (u8 *) ioremap(pci_resource_start(ioc, - i), - pci_resource_len(ioc, i)); - break; - } - } - if (!hp->registers) { - printk(KERN_ERR PFX "Detected HP ZX1 AGP bridge but no CSRs\n"); - - return -ENODEV; - } - - /* - * If the IOTLB is currently disabled, we can take it over. - * Otherwise, we have to share with sba_iommu. - */ - hp->io_pdir_owner = (INREG64(hp->registers, HP_ZX1_IBASE) & 0x1) == 0; - - if (hp->io_pdir_owner) - return hp_zx1_ioc_owner(ioc_rev); - - return hp_zx1_ioc_shared(); -} - -static int hp_zx1_fetch_size(void) -{ - int size; - - size = hp_private.gart_size / MB(1); - hp_zx1_sizes[0].size = size; - agp_bridge.current_size = (void *) &hp_zx1_sizes[0]; - return size; -} - -static int hp_zx1_configure(void) -{ - struct _hp_private *hp = &hp_private; - - agp_bridge.gart_bus_addr = hp->gart_base; - agp_bridge.capndx = pci_find_capability(agp_bridge.dev, PCI_CAP_ID_AGP); - pci_read_config_dword(agp_bridge.dev, - agp_bridge.capndx + PCI_AGP_STATUS, &agp_bridge.mode); - - if (hp->io_pdir_owner) { - OUTREG64(hp->registers, HP_ZX1_PDIR_BASE, - virt_to_phys(hp->io_pdir)); - OUTREG64(hp->registers, HP_ZX1_TCNFG, hp->io_tlb_ps); - OUTREG64(hp->registers, HP_ZX1_IMASK, ~(HP_ZX1_IOVA_SIZE - 1)); - OUTREG64(hp->registers, HP_ZX1_IBASE, hp->iova_base | 0x1); - OUTREG64(hp->registers, HP_ZX1_PCOM, - hp->iova_base | log2(HP_ZX1_IOVA_SIZE)); - INREG64(hp->registers, HP_ZX1_PCOM); - } - - return 0; -} - -static void hp_zx1_cleanup(void) -{ - struct _hp_private *hp = &hp_private; - - if (hp->io_pdir_owner) - OUTREG64(hp->registers, HP_ZX1_IBASE, 0); - iounmap((void *) hp->registers); -} - -static void hp_zx1_tlbflush(agp_memory * mem) -{ - struct _hp_private *hp = &hp_private; - - OUTREG64(hp->registers, HP_ZX1_PCOM, - hp->gart_base | log2(hp->gart_size)); - INREG64(hp->registers, HP_ZX1_PCOM); -} - -static int hp_zx1_create_gatt_table(void) -{ - struct _hp_private *hp = &hp_private; - int i; - - if (hp->io_pdir_owner) { - hp->io_pdir = (u64 *) __get_free_pages(GFP_KERNEL, - get_order(hp->io_pdir_size)); - if (!hp->io_pdir) { - printk(KERN_ERR PFX "Couldn't allocate contiguous " - "memory for I/O PDIR\n"); - hp->gatt = 0; - hp->gatt_entries = 0; - return -ENOMEM; - } - memset(hp->io_pdir, 0, hp->io_pdir_size); - - hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)]; - } - - for (i = 0; i < hp->gatt_entries; i++) { - hp->gatt[i] = (unsigned long) agp_bridge.scratch_page; - } - - return 0; -} - -static int hp_zx1_free_gatt_table(void) -{ - struct _hp_private *hp = &hp_private; - - if (hp->io_pdir_owner) - free_pages((unsigned long) hp->io_pdir, - get_order(hp->io_pdir_size)); - else - hp->gatt[0] = HP_ZX1_SBA_IOMMU_COOKIE; - return 0; -} - -static int hp_zx1_insert_memory(agp_memory * mem, off_t pg_start, int type) -{ - struct _hp_private *hp = &hp_private; - int i, k; - off_t j, io_pg_start; - int io_pg_count; - - if (type != 0 || mem->type != 0) { - return -EINVAL; - } - - io_pg_start = hp->io_pages_per_kpage * pg_start; - io_pg_count = hp->io_pages_per_kpage * mem->page_count; - if ((io_pg_start + io_pg_count) > hp->gatt_entries) { - return -EINVAL; - } - - j = io_pg_start; - while (j < (io_pg_start + io_pg_count)) { - if (hp->gatt[j]) { - return -EBUSY; - } - j++; - } - - if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); - mem->is_flushed = TRUE; - } - - for (i = 0, j = io_pg_start; i < mem->page_count; i++) { - unsigned long paddr; - - paddr = mem->memory[i]; - for (k = 0; - k < hp->io_pages_per_kpage; - k++, j++, paddr += hp->io_page_size) { - hp->gatt[j] = agp_bridge.mask_memory(paddr, type); - } - } - - agp_bridge.tlb_flush(mem); - return 0; -} - -static int hp_zx1_remove_memory(agp_memory * mem, off_t pg_start, int type) -{ - struct _hp_private *hp = &hp_private; - int i, io_pg_start, io_pg_count; - - if (type != 0 || mem->type != 0) { - return -EINVAL; - } - - io_pg_start = hp->io_pages_per_kpage * pg_start; - io_pg_count = hp->io_pages_per_kpage * mem->page_count; - for (i = io_pg_start; i < io_pg_count + io_pg_start; i++) { - hp->gatt[i] = agp_bridge.scratch_page; - } - - agp_bridge.tlb_flush(mem); - return 0; -} - -static unsigned long hp_zx1_mask_memory(unsigned long addr, int type) -{ - return HP_ZX1_PDIR_VALID_BIT | addr; -} - -static unsigned long hp_zx1_unmask_memory(unsigned long addr) -{ - return addr & ~(HP_ZX1_PDIR_VALID_BIT); -} - -static int __init hp_zx1_setup (struct pci_dev *pdev) -{ - agp_bridge.masks = hp_zx1_masks; - agp_bridge.num_of_masks = 1; - agp_bridge.dev_private_data = NULL; - agp_bridge.size_type = FIXED_APER_SIZE; - agp_bridge.needs_scratch_page = FALSE; - agp_bridge.configure = hp_zx1_configure; - agp_bridge.fetch_size = hp_zx1_fetch_size; - agp_bridge.cleanup = hp_zx1_cleanup; - agp_bridge.tlb_flush = hp_zx1_tlbflush; - agp_bridge.mask_memory = hp_zx1_mask_memory; - agp_bridge.unmask_memory = hp_zx1_unmask_memory; - agp_bridge.agp_enable = agp_generic_agp_enable; - agp_bridge.cache_flush = global_cache_flush; - agp_bridge.create_gatt_table = hp_zx1_create_gatt_table; - agp_bridge.free_gatt_table = hp_zx1_free_gatt_table; - agp_bridge.insert_memory = hp_zx1_insert_memory; - agp_bridge.remove_memory = hp_zx1_remove_memory; - agp_bridge.alloc_by_type = agp_generic_alloc_by_type; - agp_bridge.free_by_type = agp_generic_free_by_type; - agp_bridge.agp_alloc_page = agp_generic_alloc_page; - agp_bridge.agp_destroy_page = agp_generic_destroy_page; - agp_bridge.cant_use_aperture = 1; - - return hp_zx1_ioc_init(); - - (void) pdev; /* unused */ -} - -#endif /* CONFIG_AGP_HP_ZX1 */ /* per-chipset initialization data. * note -- all chipsets for a single vendor MUST be grouped together @@ -4335,301 +750,401 @@ } agp_bridge_info[] __initdata = { #ifdef CONFIG_AGP_ALI - { PCI_DEVICE_ID_AL_M1541_0, - PCI_VENDOR_ID_AL, - ALI_M1541, - "Ali", - "M1541", - ali_generic_setup }, - { PCI_DEVICE_ID_AL_M1621_0, - PCI_VENDOR_ID_AL, - ALI_M1621, - "Ali", - "M1621", - ali_generic_setup }, - { PCI_DEVICE_ID_AL_M1631_0, - PCI_VENDOR_ID_AL, - ALI_M1631, - "Ali", - "M1631", - ali_generic_setup }, - { PCI_DEVICE_ID_AL_M1632_0, - PCI_VENDOR_ID_AL, - ALI_M1632, - "Ali", - "M1632", - ali_generic_setup }, - { PCI_DEVICE_ID_AL_M1641_0, - PCI_VENDOR_ID_AL, - ALI_M1641, - "Ali", - "M1641", - ali_generic_setup }, - { PCI_DEVICE_ID_AL_M1644_0, - PCI_VENDOR_ID_AL, - ALI_M1644, - "Ali", - "M1644", - ali_generic_setup }, - { PCI_DEVICE_ID_AL_M1647_0, - PCI_VENDOR_ID_AL, - ALI_M1647, - "Ali", - "M1647", - ali_generic_setup }, - { PCI_DEVICE_ID_AL_M1651_0, - PCI_VENDOR_ID_AL, - ALI_M1651, - "Ali", - "M1651", - ali_generic_setup }, - { 0, - PCI_VENDOR_ID_AL, - ALI_GENERIC, - "Ali", - "Generic", - ali_generic_setup }, + { + device_id: PCI_DEVICE_ID_AL_M1541_0, + vendor_id: PCI_VENDOR_ID_AL, + chipset: ALI_M1541, + vendor_name: "Ali", + chipset_name: "M1541", + chipset_setup: ali_generic_setup, + }, + { + device_id: PCI_DEVICE_ID_AL_M1621_0, + vendor_id: PCI_VENDOR_ID_AL, + chipset: ALI_M1621, + vendor_name: "Ali", + chipset_name: "M1621", + chipset_setup: ali_generic_setup, + }, + { + device_id: PCI_DEVICE_ID_AL_M1631_0, + vendor_id: PCI_VENDOR_ID_AL, + chipset: ALI_M1631, + vendor_name: "Ali", + chipset_name: "M1631", + chipset_setup: ali_generic_setup, + }, + { + device_id: PCI_DEVICE_ID_AL_M1632_0, + vendor_id: PCI_VENDOR_ID_AL, + chipset: ALI_M1632, + vendor_name: "Ali", + chipset_name: "M1632", + chipset_setup: ali_generic_setup, + }, + { + device_id: PCI_DEVICE_ID_AL_M1641_0, + vendor_id: PCI_VENDOR_ID_AL, + chipset: ALI_M1641, + vendor_name: "Ali", + chipset_name: "M1641", + chipset_setup: ali_generic_setup, + }, + { + device_id: PCI_DEVICE_ID_AL_M1644_0, + vendor_id: PCI_VENDOR_ID_AL, + chipset: ALI_M1644, + vendor_name: "Ali", + chipset_name: "M1644", + chipset_setup: ali_generic_setup, + }, + { + device_id: PCI_DEVICE_ID_AL_M1647_0, + vendor_id: PCI_VENDOR_ID_AL, + chipset: ALI_M1647, + vendor_name: "Ali", + chipset_name: "M1647", + chipset_setup: ali_generic_setup, + }, + { + device_id: PCI_DEVICE_ID_AL_M1651_0, + vendor_id: PCI_VENDOR_ID_AL, + chipset: ALI_M1651, + vendor_name: "Ali", + chipset_name: "M1651", + chipset_setup: ali_generic_setup, + }, + { + device_id: 0, + vendor_id: PCI_VENDOR_ID_AL, + chipset: ALI_GENERIC, + vendor_name: "Ali", + chipset_name: "Generic", + chipset_setup: ali_generic_setup, + }, #endif /* CONFIG_AGP_ALI */ #ifdef CONFIG_AGP_AMD - { PCI_DEVICE_ID_AMD_IRONGATE_0, - PCI_VENDOR_ID_AMD, - AMD_IRONGATE, - "AMD", - "Irongate", - amd_irongate_setup }, - { PCI_DEVICE_ID_AMD_761_0, - PCI_VENDOR_ID_AMD, - AMD_761, - "AMD", - "761", - amd_irongate_setup }, - { PCI_DEVICE_ID_AMD_762_0, - PCI_VENDOR_ID_AMD, - AMD_762, - "AMD", - "760MP", - amd_irongate_setup }, - { 0, - PCI_VENDOR_ID_AMD, - AMD_GENERIC, - "AMD", - "Generic", - amd_irongate_setup }, + { + device_id: PCI_DEVICE_ID_AMD_IRONGATE_0, + vendor_id: PCI_VENDOR_ID_AMD, + chipset: AMD_IRONGATE, + vendor_name: "AMD", + chipset_name: "Irongate", + chipset_setup: amd_irongate_setup, + }, + { + device_id: PCI_DEVICE_ID_AMD_761_0, + vendor_id: PCI_VENDOR_ID_AMD, + chipset: AMD_761, + vendor_name: "AMD", + chipset_name: "761", + chipset_setup: amd_irongate_setup, + }, + { + device_id: PCI_DEVICE_ID_AMD_762_0, + vendor_id: PCI_VENDOR_ID_AMD, + chipset: AMD_762, + vendor_name: "AMD", + chipset_name: "760MP", + chipset_setup: amd_irongate_setup, + }, + { + device_id: 0, + vendor_id: PCI_VENDOR_ID_AMD, + chipset: AMD_GENERIC, + vendor_name: "AMD", + chipset_name: "Generic", + chipset_setup: amd_irongate_setup, + }, #endif /* CONFIG_AGP_AMD */ #ifdef CONFIG_AGP_INTEL - { PCI_DEVICE_ID_INTEL_82443LX_0, - PCI_VENDOR_ID_INTEL, - INTEL_LX, - "Intel", - "440LX", - intel_generic_setup }, - { PCI_DEVICE_ID_INTEL_82443BX_0, - PCI_VENDOR_ID_INTEL, - INTEL_BX, - "Intel", - "440BX", - intel_generic_setup }, - { PCI_DEVICE_ID_INTEL_82443GX_0, - PCI_VENDOR_ID_INTEL, - INTEL_GX, - "Intel", - "440GX", - intel_generic_setup }, - { PCI_DEVICE_ID_INTEL_815_0, - PCI_VENDOR_ID_INTEL, - INTEL_I815, - "Intel", - "i815", - intel_generic_setup }, - { PCI_DEVICE_ID_INTEL_820_0, - PCI_VENDOR_ID_INTEL, - INTEL_I820, - "Intel", - "i820", - intel_820_setup }, - { PCI_DEVICE_ID_INTEL_820_UP_0, - PCI_VENDOR_ID_INTEL, - INTEL_I820, - "Intel", - "i820", - intel_820_setup }, - { PCI_DEVICE_ID_INTEL_830_M_0, - PCI_VENDOR_ID_INTEL, - INTEL_I830_M, - "Intel", - "i830M", - intel_830mp_setup }, - { PCI_DEVICE_ID_INTEL_845_G_0, - PCI_VENDOR_ID_INTEL, - INTEL_I845_G, - "Intel", - "i845G", - intel_830mp_setup }, - { PCI_DEVICE_ID_INTEL_840_0, - PCI_VENDOR_ID_INTEL, - INTEL_I840, - "Intel", - "i840", - intel_840_setup }, - { PCI_DEVICE_ID_INTEL_845_0, - PCI_VENDOR_ID_INTEL, - INTEL_I845, - "Intel", - "i845", - intel_845_setup }, - { PCI_DEVICE_ID_INTEL_850_0, - PCI_VENDOR_ID_INTEL, - INTEL_I850, - "Intel", - "i850", -intel_850_setup }, - { PCI_DEVICE_ID_INTEL_860_0, - PCI_VENDOR_ID_INTEL, - INTEL_I860, - "Intel", - "i860", - intel_860_setup }, - { 0, - PCI_VENDOR_ID_INTEL, - INTEL_GENERIC, - "Intel", - "Generic", - intel_generic_setup }, + { + device_id: PCI_DEVICE_ID_INTEL_82443LX_0, + vendor_id: PCI_VENDOR_ID_INTEL, + chipset: INTEL_LX, + vendor_name: "Intel", + chipset_name: "440LX", + chipset_setup: intel_generic_setup + }, + { + device_id: PCI_DEVICE_ID_INTEL_82443BX_0, + vendor_id: PCI_VENDOR_ID_INTEL, + chipset: INTEL_BX, + vendor_name: "Intel", + chipset_name: "440BX", + chipset_setup: intel_generic_setup + }, + { + device_id: PCI_DEVICE_ID_INTEL_82443GX_0, + vendor_id: PCI_VENDOR_ID_INTEL, + chipset: INTEL_GX, + vendor_name: "Intel", + chipset_name: "440GX", + chipset_setup: intel_generic_setup + }, + { + device_id: PCI_DEVICE_ID_INTEL_815_0, + vendor_id: PCI_VENDOR_ID_INTEL, + chipset: INTEL_I815, + vendor_name: "Intel", + chipset_name: "i815", + chipset_setup: intel_815_setup + }, + { + device_id: PCI_DEVICE_ID_INTEL_820_0, + vendor_id: PCI_VENDOR_ID_INTEL, + chipset: INTEL_I820, + vendor_name: "Intel", + chipset_name: "i820", + chipset_setup: intel_820_setup + }, + { + device_id: PCI_DEVICE_ID_INTEL_820_UP_0, + vendor_id: PCI_VENDOR_ID_INTEL, + chipset: INTEL_I820, + vendor_name: "Intel", + chipset_name: "i820", + chipset_setup: intel_820_setup + }, + { + device_id: PCI_DEVICE_ID_INTEL_830_M_0, + vendor_id: PCI_VENDOR_ID_INTEL, + chipset: INTEL_I830_M, + vendor_name: "Intel", + chipset_name: "i830M", + chipset_setup: intel_830mp_setup + }, + { + device_id: PCI_DEVICE_ID_INTEL_845_G_0, + vendor_id: PCI_VENDOR_ID_INTEL, + chipset: INTEL_I845_G, + vendor_name: "Intel", + chipset_name: "i845G", + chipset_setup: intel_830mp_setup + }, + { + device_id: PCI_DEVICE_ID_INTEL_840_0, + vendor_id: PCI_VENDOR_ID_INTEL, + chipset: INTEL_I840, + vendor_name: "Intel", + chipset_name: "i840", + chipset_setup: intel_840_setup + }, + { + device_id: PCI_DEVICE_ID_INTEL_845_0, + vendor_id: PCI_VENDOR_ID_INTEL, + chipset: INTEL_I845, + vendor_name: "Intel", + chipset_name: "i845", + chipset_setup: intel_845_setup + }, + { + device_id: PCI_DEVICE_ID_INTEL_850_0, + vendor_id: PCI_VENDOR_ID_INTEL, + chipset: INTEL_I850, + vendor_name: "Intel", + chipset_name: "i850", + chipset_setup: intel_850_setup + }, + { + device_id: PCI_DEVICE_ID_INTEL_860_0, + vendor_id: PCI_VENDOR_ID_INTEL, + chipset: INTEL_I860, + vendor_name: "Intel", + chipset_name: "i860", + chipset_setup: intel_860_setup + }, + { + device_id: 0, + vendor_id: PCI_VENDOR_ID_INTEL, + chipset: INTEL_GENERIC, + vendor_name: "Intel", + chipset_name: "Generic", + chipset_setup: intel_generic_setup + }, #endif /* CONFIG_AGP_INTEL */ #ifdef CONFIG_AGP_SIS - { PCI_DEVICE_ID_SI_740, - PCI_VENDOR_ID_SI, - SIS_GENERIC, - "SiS", - "740", - sis_generic_setup }, - { PCI_DEVICE_ID_SI_650, - PCI_VENDOR_ID_SI, - SIS_GENERIC, - "SiS", - "650", - sis_generic_setup }, - { PCI_DEVICE_ID_SI_645, - PCI_VENDOR_ID_SI, - SIS_GENERIC, - "SiS", - "645", - sis_generic_setup }, - { PCI_DEVICE_ID_SI_735, - PCI_VENDOR_ID_SI, - SIS_GENERIC, - "SiS", - "735", - sis_generic_setup }, - { PCI_DEVICE_ID_SI_730, - PCI_VENDOR_ID_SI, - SIS_GENERIC, - "SiS", - "730", - sis_generic_setup }, - { PCI_DEVICE_ID_SI_630, - PCI_VENDOR_ID_SI, - SIS_GENERIC, - "SiS", - "630", - sis_generic_setup }, - { PCI_DEVICE_ID_SI_540, - PCI_VENDOR_ID_SI, - SIS_GENERIC, - "SiS", - "540", - sis_generic_setup }, - { PCI_DEVICE_ID_SI_620, - PCI_VENDOR_ID_SI, - SIS_GENERIC, - "SiS", - "620", - sis_generic_setup }, - { PCI_DEVICE_ID_SI_530, - PCI_VENDOR_ID_SI, - SIS_GENERIC, - "SiS", - "530", - sis_generic_setup }, - { PCI_DEVICE_ID_SI_550, - PCI_VENDOR_ID_SI, - SIS_GENERIC, - "SiS", - "550", - sis_generic_setup }, - { 0, - PCI_VENDOR_ID_SI, - SIS_GENERIC, - "SiS", - "Generic", - sis_generic_setup }, + { + device_id: PCI_DEVICE_ID_SI_740, + vendor_id: PCI_VENDOR_ID_SI, + chipset: SIS_GENERIC, + vendor_name: "SiS", + chipset_name: "740", + chipset_setup: sis_generic_setup + }, + { + device_id: PCI_DEVICE_ID_SI_650, + vendor_id: PCI_VENDOR_ID_SI, + chipset: SIS_GENERIC, + vendor_name: "SiS", + chipset_name: "650", + chipset_setup: sis_generic_setup + }, + { + device_id: PCI_DEVICE_ID_SI_645, + vendor_id: PCI_VENDOR_ID_SI, + chipset: SIS_GENERIC, + vendor_name: "SiS", + chipset_name: "645", + chipset_setup: sis_generic_setup + }, + { + device_id: PCI_DEVICE_ID_SI_735, + vendor_id: PCI_VENDOR_ID_SI, + chipset: SIS_GENERIC, + vendor_name: "SiS", + chipset_name: "735", + chipset_setup: sis_generic_setup + }, + { + device_id: PCI_DEVICE_ID_SI_745, + vendor_id: PCI_VENDOR_ID_SI, + chipset: SIS_GENERIC, + vendor_name: "SiS", + chipset_name: "745", + chipset_setup: sis_generic_setup + }, + { + device_id: PCI_DEVICE_ID_SI_730, + vendor_id: PCI_VENDOR_ID_SI, + chipset: SIS_GENERIC, + vendor_name: "SiS", + chipset_name: "730", + chipset_setup: sis_generic_setup + }, + { + device_id: PCI_DEVICE_ID_SI_630, + vendor_id: PCI_VENDOR_ID_SI, + chipset: SIS_GENERIC, + vendor_name: "SiS", + chipset_name: "630", + chipset_setup: sis_generic_setup + }, + { + device_id: PCI_DEVICE_ID_SI_540, + vendor_id: PCI_VENDOR_ID_SI, + chipset: SIS_GENERIC, + vendor_name: "SiS", + chipset_name: "540", + chipset_setup: sis_generic_setup + }, + { + device_id: PCI_DEVICE_ID_SI_620, + vendor_id: PCI_VENDOR_ID_SI, + chipset: SIS_GENERIC, + vendor_name: "SiS", + chipset_name: "620", + chipset_setup: sis_generic_setup + }, + { + device_id: PCI_DEVICE_ID_SI_530, + vendor_id: PCI_VENDOR_ID_SI, + chipset: SIS_GENERIC, + vendor_name: "SiS", + chipset_name: "530", + chipset_setup: sis_generic_setup + }, + { + device_id: PCI_DEVICE_ID_SI_550, + vendor_id: PCI_VENDOR_ID_SI, + chipset: SIS_GENERIC, + vendor_name: "SiS", + chipset_name: "550", + chipset_setup: sis_generic_setup + }, + { + device_id: 0, + vendor_id: PCI_VENDOR_ID_SI, + chipset: SIS_GENERIC, + vendor_name: "SiS", + chipset_name: "Generic", + chipset_setup: sis_generic_setup + }, #endif /* CONFIG_AGP_SIS */ #ifdef CONFIG_AGP_VIA - { PCI_DEVICE_ID_VIA_8501_0, - PCI_VENDOR_ID_VIA, - VIA_MVP4, - "Via", - "MVP4", - via_generic_setup }, - { PCI_DEVICE_ID_VIA_82C597_0, - PCI_VENDOR_ID_VIA, - VIA_VP3, - "Via", - "VP3", - via_generic_setup }, - { PCI_DEVICE_ID_VIA_82C598_0, - PCI_VENDOR_ID_VIA, - VIA_MVP3, - "Via", - "MVP3", - via_generic_setup }, - { PCI_DEVICE_ID_VIA_82C691_0, - PCI_VENDOR_ID_VIA, - VIA_APOLLO_PRO, - "Via", - "Apollo Pro", - via_generic_setup }, - { PCI_DEVICE_ID_VIA_8371_0, - PCI_VENDOR_ID_VIA, - VIA_APOLLO_KX133, - "Via", - "Apollo Pro KX133", - via_generic_setup }, - { PCI_DEVICE_ID_VIA_8363_0, - PCI_VENDOR_ID_VIA, - VIA_APOLLO_KT133, - "Via", - "Apollo Pro KT133", - via_generic_setup }, - { PCI_DEVICE_ID_VIA_8367_0, - PCI_VENDOR_ID_VIA, - VIA_APOLLO_KT133, - "Via", - "Apollo Pro KT266", - via_generic_setup }, - { 0, - PCI_VENDOR_ID_VIA, - VIA_GENERIC, - "Via", - "Generic", - via_generic_setup }, + { + device_id: PCI_DEVICE_ID_VIA_8501_0, + vendor_id: PCI_VENDOR_ID_VIA, + chipset: VIA_MVP4, + vendor_name: "Via", + chipset_name: "MVP4", + chipset_setup: via_generic_setup + }, + { + device_id: PCI_DEVICE_ID_VIA_82C597_0, + vendor_id: PCI_VENDOR_ID_VIA, + chipset: VIA_VP3, + vendor_name: "Via", + chipset_name: "VP3", + chipset_setup: via_generic_setup + }, + { + device_id: PCI_DEVICE_ID_VIA_82C598_0, + vendor_id: PCI_VENDOR_ID_VIA, + chipset: VIA_MVP3, + vendor_name: "Via", + chipset_name: "MVP3", + chipset_setup: via_generic_setup + }, + { + device_id: PCI_DEVICE_ID_VIA_82C691_0, + vendor_id: PCI_VENDOR_ID_VIA, + chipset: VIA_APOLLO_PRO, + vendor_name: "Via", + chipset_name: "Apollo Pro", + chipset_setup: via_generic_setup + }, + { + device_id: PCI_DEVICE_ID_VIA_8371_0, + vendor_id: PCI_VENDOR_ID_VIA, + chipset: VIA_APOLLO_KX133, + vendor_name: "Via", + chipset_name: "Apollo Pro KX133", + chipset_setup: via_generic_setup + }, + { + device_id: PCI_DEVICE_ID_VIA_8363_0, + vendor_id: PCI_VENDOR_ID_VIA, + chipset: VIA_APOLLO_KT133, + vendor_name: "Via", + chipset_name: "Apollo Pro KT133", + chipset_setup: via_generic_setup + }, + { + device_id: PCI_DEVICE_ID_VIA_8367_0, + vendor_id: PCI_VENDOR_ID_VIA, + chipset: VIA_APOLLO_KT133, + vendor_name: "Via", + chipset_name: "Apollo Pro KT266", + chipset_setup: via_generic_setup + }, + { + device_id: 0, + vendor_id: PCI_VENDOR_ID_VIA, + chipset: VIA_GENERIC, + vendor_name: "Via", + chipset_name: "Generic", + chipset_setup: via_generic_setup + }, #endif /* CONFIG_AGP_VIA */ #ifdef CONFIG_AGP_HP_ZX1 - { PCI_DEVICE_ID_HP_ZX1_LBA, - PCI_VENDOR_ID_HP, - HP_ZX1, - "HP", - "ZX1", - hp_zx1_setup }, + { + device_id: PCI_DEVICE_ID_HP_ZX1_LBA, + vendor_id: PCI_VENDOR_ID_HP, + chipset: HP_ZX1, + vendor_name: "HP", + chipset_name: "ZX1", + chipset_setup: hp_zx1_setup + }, #endif - { 0, }, /* dummy final entry, always present */ + { }, /* dummy final entry, always present */ }; @@ -4710,14 +1225,10 @@ /* Supported Device Scanning routine */ -static int __init agp_find_supported_device(void) +static int __init agp_find_supported_device(struct pci_dev *dev) { - struct pci_dev *dev = NULL; u8 cap_ptr = 0x00; - if ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8, NULL)) == NULL) - return -ENODEV; - agp_bridge.dev = dev; /* Need to test for I810 here */ @@ -4816,12 +1327,12 @@ case PCI_DEVICE_ID_INTEL_830_M_0: i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_830_M_1, - NULL); + PCI_DEVICE_ID_INTEL_830_M_1, + NULL); if(i810_dev && PCI_FUNC(i810_dev->devfn) != 0) { i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_830_M_1, - i810_dev); + PCI_DEVICE_ID_INTEL_830_M_1, + i810_dev); } if (i810_dev == NULL) { @@ -4873,24 +1384,21 @@ } } -#endif /* CONFIG_AGP_SWORKS */ +#endif /* CONFIG_AGP_SWORKS */ #ifdef CONFIG_AGP_HP_ZX1 if (dev->vendor == PCI_VENDOR_ID_HP) { - do { - /* ZX1 LBAs can be either PCI or AGP bridges */ - if (pci_find_capability(dev, PCI_CAP_ID_AGP)) { - printk(KERN_INFO PFX "Detected HP ZX1 AGP " - "chipset at %s\n", dev->slot_name); - agp_bridge.type = HP_ZX1; - agp_bridge.dev = dev; - return hp_zx1_setup(dev); - } - dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8, dev); - } while (dev); + /* ZX1 LBAs can be either PCI or AGP bridges */ + if (pci_find_capability(dev, PCI_CAP_ID_AGP)) { + printk(KERN_INFO PFX "Detected HP ZX1 AGP " + "chipset at %s\n", dev->slot_name); + agp_bridge.type = HP_ZX1; + agp_bridge.dev = dev; + return hp_zx1_setup(dev); + } return -ENODEV; } -#endif /* CONFIG_AGP_HP_ZX1 */ +#endif /* CONFIG_AGP_HP_ZX1 */ /* find capndx */ cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); @@ -4951,13 +1459,13 @@ #define AGPGART_VERSION_MAJOR 0 #define AGPGART_VERSION_MINOR 99 -static agp_version agp_current_version = +static struct agp_version agp_current_version = { - AGPGART_VERSION_MAJOR, - AGPGART_VERSION_MINOR + major: AGPGART_VERSION_MAJOR, + minor: AGPGART_VERSION_MINOR, }; -static int __init agp_backend_initialize(void) +static int __init agp_backend_initialize(struct pci_dev *dev) { int size_value, rc, got_gatt=0, got_keylist=0; @@ -4966,7 +1474,7 @@ agp_bridge.max_memory_agp = agp_find_max(); agp_bridge.version = &agp_current_version; - rc = agp_find_supported_device(); + rc = agp_find_supported_device(dev); if (rc) { /* not KERN_ERR because error msg should have already printed */ printk(KERN_DEBUG PFX "no supported devices found.\n"); @@ -5077,14 +1585,16 @@ &agp_copy_info }; -static int __init agp_init(void) +static int agp_probe (struct pci_dev *dev, const struct pci_device_id *ent) { int ret_val; - printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Jeff Hartmann\n", - AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR); + if (agp_bridge.type != NOT_SUPPORTED) { + printk (KERN_DEBUG "Oops, don't init a 2nd agpgart device.\n"); + return -ENODEV; + } - ret_val = agp_backend_initialize(); + ret_val = agp_backend_initialize(dev); if (ret_val) { agp_bridge.type = NOT_SUPPORTED; return ret_val; @@ -5102,12 +1612,50 @@ return 0; } +static struct pci_device_id agp_pci_table[] __initdata = { + { + class: (PCI_CLASS_BRIDGE_HOST << 8), + class_mask: ~0, + vendor: PCI_ANY_ID, + device: PCI_ANY_ID, + subvendor: PCI_ANY_ID, + subdevice: PCI_ANY_ID, + }, + { } +}; + +MODULE_DEVICE_TABLE(pci, agp_pci_table); + +static struct pci_driver agp_pci_driver = { + name: "agpgart", + id_table: agp_pci_table, + probe: agp_probe, +}; + +static int __init agp_init(void) +{ + int ret_val; + + printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Jeff Hartmann\n", + AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR); + + ret_val = pci_module_init(&agp_pci_driver); + if (ret_val) { + agp_bridge.type = NOT_SUPPORTED; + return ret_val; + } + return 0; +} + static void __exit agp_cleanup(void) { - pm_unregister_all(agp_power); - agp_frontend_cleanup(); - agp_backend_cleanup(); - inter_module_unregister("drm_agp"); + pci_unregister_driver(&agp_pci_driver); + if (agp_bridge.type != NOT_SUPPORTED) { + pm_unregister_all(agp_power); + agp_frontend_cleanup(); + agp_backend_cleanup(); + inter_module_unregister("drm_agp"); + } } module_init(agp_init); diff -Nru a/drivers/char/agp/agpgart_fe.c b/drivers/char/agp/agpgart_fe.c --- a/drivers/char/agp/agpgart_fe.c Mon Jul 15 12:01:54 2002 +++ b/drivers/char/agp/agpgart_fe.c Mon Jul 15 12:01:54 2002 @@ -24,29 +24,16 @@ * */ -#define __NO_VERSION__ -#include #include #include #include -#include -#include -#include -#include -#include -#include +#include #include #include -#include #include #include #include -#include -#include #include -#include -#include -#include #include "agp.h" diff -Nru a/include/linux/agp_backend.h b/include/linux/agp_backend.h --- a/include/linux/agp_backend.h Mon Jul 15 12:01:54 2002 +++ b/include/linux/agp_backend.h Mon Jul 15 12:01:54 2002 @@ -81,13 +81,13 @@ HP_ZX1, }; -typedef struct _agp_version { +struct agp_version { u16 major; u16 minor; -} agp_version; +}; typedef struct _agp_kern_info { - agp_version version; + struct agp_version version; struct pci_dev *device; enum chipset_type chipset; unsigned long mode; diff -Nru a/include/linux/agpgart.h b/include/linux/agpgart.h --- a/include/linux/agpgart.h Mon Jul 15 12:01:54 2002 +++ b/include/linux/agpgart.h Mon Jul 15 12:01:54 2002 @@ -53,13 +53,13 @@ #include #include -typedef struct _agp_version { +struct agp_version { __u16 major; __u16 minor; -} agp_version; +}; typedef struct _agp_info { - agp_version version; /* version of the driver */ + struct agp_version version; /* version of the driver */ __u32 bridge_id; /* bridge vendor/device */ __u32 agp_mode; /* mode info of bridge */ off_t aper_base; /* base of aperture */ @@ -117,7 +117,7 @@ #define AGP_LOCK_INIT() sema_init(&(agp_fe.agp_mutex), 1) #ifndef _AGP_BACKEND_H -typedef struct _agp_version { +struct _agp_version { u16 major; u16 minor; } agp_version; @@ -125,7 +125,7 @@ #endif typedef struct _agp_info { - agp_version version; /* version of the driver */ + struct agp_version version; /* version of the driver */ u32 bridge_id; /* bridge vendor/device */ u32 agp_mode; /* mode info of bridge */ off_t aper_base; /* base of aperture */