Messages in this thread Patch in this message | | | Date | Thu, 03 Apr 2003 12:33:59 +0900 | From | ISHIKAWA Mutsumi <> | Subject | Re: [BUG] E7x05 chipset bug in 2.5 kernels' AGPGART driver. |
| |
>>>>> In <20030402221046.GA30881@suse.de> >>>>> Dave Jones <davej@codemonkey.org.uk> wrote: >> On Wed, Apr 02, 2003 at 08:50:03PM +0200, Fendrakyn wrote:
>> > The last problem is more important and I have yet to find a solution. It seems >> > like the driver stores device 0 in his agp_bridge->dev (0x255d for E7205, >> > 0x2550 for E7505) but it uses registers from device 1 (0x2552) thus the >> > chipset cannot be configured properly. The fetch_size function fails to >> > determine aperture size.
>> Yep, the other issues (compile problems) are fixed up and will be going >> to Linus real soon now, this problem though is something that is being >> looked at by Matt (i7x05 gart driver author) right now. >> Hopefully that'll also get fixed up with the changes being readied for 2.5.67 >> >> The reason i7x05 does things differently is that the generic-3.0 code >> looks at the devices hanging of the device 0 (in that case, agp gfx cards). >> I realised last week that the generic code is broken, as every other >> agp chipset has the agp cards as secondaries of the agp bridge, not the >> host bridge. Rather than fudge things like this, it looks like a lot >> of the generic-3.0 stuff will be ripped out. It doesn't really work >> properly, and is of questionable use.
I've checked Intel E7205 and E7505 spec sheets. But I can not find why we should use device #1 (virtual agp bridge) instaed of device #0 (MCH). I rewrite E7x05 agpgart driver to use device #0. It works fine for me (I tested it on E7505 motherboard with AGPx4 card and AGPx8 card). To use MCH registers (on device #0) is generic way for Intel agpgart driver, so the driver can merge into intel-agp.c easyly.
I put the patchset (against current agpgart BK tree) on the URL. Please test them:
http://hanzubon.jp/agpgart/e7x05-agp-intel-agp-merge-4-1.diff http://hanzubon.jp/agpgart/e7x05-agp-intel-agp-merge-4-2.diff http://hanzubon.jp/agpgart/agp_enable_fallback_fix.diff
e7x05-agp-intel-agp-merge-4-1.diff: main part of the patch to integrate e7x05 support into intel-agp.c
e7x05-agp-intel-agp-merge-4-2.diff: drop i7505-agp.c and update Kconfig and Makefile.
agp_enable_fallback_fix.diff: fix agp_generic_enable() function's fall back mehacnism to agp 2.0 mode. It is already sent and merged to dj's tree (thanks :-) It is not directly related of E7x05 AGP issue, but it is needed to test the E7x05 driver.
diff -urN linux-2.5.orig/drivers/char/agp/agp.h linux-2.5/drivers/char/agp/agp.h --- linux-2.5.orig/drivers/char/agp/agp.h 2003-04-03 12:03:14.000000000 +0900 +++ linux-2.5/drivers/char/agp/agp.h 2003-04-03 12:12:11.000000000 +0900 @@ -273,14 +273,8 @@ #define I810_DRAM_ROW_0 0x00000001 #define I810_DRAM_ROW_0_SDRAM 0x00000001 -/* Intel 7505 registers */ -#define INTEL_I7505_NAPBASELO 0x10 -#define INTEL_I7505_APSIZE 0x74 -#define INTEL_I7505_NCAPID 0x60 -#define INTEL_I7505_NISTAT 0x6c -#define INTEL_I7505_ATTBASE 0x78 -#define INTEL_I7505_ERRSTS 0x42 -#define INTEL_I7505_AGPCTRL 0x70 +/* Intel E7205/7505 register */ +#define INTEL_E7X05_MCHCFG 0x50 /* VIA register */ #define VIA_APBASE 0x10 diff -urN linux-2.5.orig/drivers/char/agp/intel-agp.c linux-2.5/drivers/char/agp/intel-agp.c --- linux-2.5.orig/drivers/char/agp/intel-agp.c 2003-04-03 12:03:17.000000000 +0900 +++ linux-2.5/drivers/char/agp/intel-agp.c 2003-04-03 12:16:30.000000000 +0900 @@ -5,6 +5,11 @@ /* * Intel(R) 855GM/852GM and 865G support added by David Dawes * <dawes@tungstengraphics.com>. + * + * Intel(R) E7205/E7505 support rewrite and added by + * ISHIKAWA Mutsumi <ishikawa@debian.org>. + * Original auther of the driver is Matthew E Tolentino + * <matthew.e.tolentino@intel.com> */ #include <linux/module.h> @@ -647,6 +652,29 @@ return 0; } +static int intel_e7x05_fetch_size(void) +{ + int i; + u16 tmp; + struct aper_size_info_16 *values; + + /* + * For AGP 3.0 APSIZE is now 16 bits + */ + pci_read_config_word (agp_bridge->dev, INTEL_APSIZE, &tmp); + tmp &= 0xfff; + values = A_SIZE_16(agp_bridge->aperture_sizes); + + for (i=0; i < agp_bridge->num_aperture_sizes; i++) { + if (tmp == 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) { @@ -960,6 +988,35 @@ return 0; } +static int intel_e7x05_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 */ + 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_E7X05_MCHCFG, &temp2); + pci_write_config_word(agp_bridge->dev, INTEL_E7X05_MCHCFG, temp2 | (1 << 9)); + + return 0; +} + static unsigned long intel_mask_memory(unsigned long addr, int type) { /* Memory type is ignored */ @@ -1246,6 +1303,35 @@ return 0; } +static int __init intel_e7x05_setup (struct pci_dev *pdev) +{ + agp_bridge->masks = intel_generic_masks; + 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_e7x05_configure; + agp_bridge->fetch_size = intel_e7x05_fetch_size; + agp_bridge->cleanup = intel_cleanup; + agp_bridge->tlb_flush = intel_8xx_tlbflush; + agp_bridge->mask_memory = intel_mask_memory; + agp_bridge->agp_enable = agp_generic_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; +} + struct agp_device_ids intel_agp_device_ids[] __initdata = { { @@ -1329,6 +1415,18 @@ .chipset_name = "865G", .chipset_setup = intel_845_setup }, + { + .device_id = PCI_DEVICE_ID_INTEL_7505_0, + .chipset = INTEL_E7X05, + .chipset_name = "E7505", + .chipset_setup = intel_e7x05_setup + }, + { + .device_id = PCI_DEVICE_ID_INTEL_7205_0, + .chipset = INTEL_E7X05, + .chipset_name = "E7205", + .chipset_setup = intel_e7x05_setup + }, { }, /* dummy final entry, always present */ }; diff -urN linux-2.5.orig/include/linux/agp_backend.h linux-2.5/include/linux/agp_backend.h --- linux-2.5.orig/include/linux/agp_backend.h 2003-04-03 12:03:35.000000000 +0900 +++ linux-2.5/include/linux/agp_backend.h 2003-04-03 12:12:11.000000000 +0900 @@ -53,7 +53,7 @@ INTEL_I850, INTEL_I860, INTEL_460GX, - INTEL_I7505, + INTEL_E7X05, VIA_GENERIC, SIS_GENERIC, AMD_GENERIC, diff -urN linux-2.5.orig/drivers/char/agp/Kconfig linux-2.5/drivers/char/agp/Kconfig --- linux-2.5.orig/drivers/char/agp/Kconfig 2003-04-03 12:03:21.000000000 +0900 +++ linux-2.5/drivers/char/agp/Kconfig 2003-04-03 12:12:11.000000000 +0900 @@ -34,13 +34,14 @@ depends on AGP config AGP_INTEL - tristate "Intel 440LX/BX/GX and I815/I820/830M/I830MP/I840/I845/845G/I850/852GM/855GM/I860/865G support" + tristate "Intel 440LX/BX/GX and I815/I820/830M/I830MP/I840/I845/845G/I850/852GM/855GM/I860/865G/E7205/E7505 support" depends on AGP help 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 and full support for the 810, 815, 830M, 845G, - 852GM, 855GM and 865G integrated graphics chipsets. + XFree86 4.x on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, + 860, E7205 and E7505 chipsets and full support for the 810, + 815, 830M, 845G, 852GM, 855GM and 865G integrated graphics + chipsets. You should say Y here if you use XFree86 3.3.6 or 4.x and want to use GLX or DRI, or if you have any Intel integrated graphics @@ -138,16 +139,3 @@ tristate depends on AGP && (ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL) default AGP - -# Put AGP 3.0 entries below here. - -config AGP_I7x05 - tristate "Intel 7205/7505 support (AGP 3.0)" - depends on AGP3 - help - This option gives you AGP support for the GLX component of the - XFree86 4.x on Intel I7505 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 - diff -urN linux-2.5.orig/drivers/char/agp/Makefile linux-2.5/drivers/char/agp/Makefile --- linux-2.5.orig/drivers/char/agp/Makefile 2003-04-03 12:03:10.000000000 +0900 +++ linux-2.5/drivers/char/agp/Makefile 2003-04-03 12:12:11.000000000 +0900 @@ -18,6 +18,3 @@ obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o obj-$(CONFIG_AGP_AMD_8151) += amd-k8-agp.o obj-$(CONFIG_AGP_ALPHA_CORE) += alpha-agp.o - -obj-$(CONFIG_AGP_I7x05) += i7x05-agp.o - diff -urN linux-2.5.orig/drivers/char/agp/i7x05-agp.c linux-2.5/drivers/char/agp/i7x05-agp.c --- linux-2.5.orig/drivers/char/agp/i7x05-agp.c 2003-04-03 12:03:07.000000000 +0900 +++ linux-2.5/drivers/char/agp/i7x05-agp.c 1970-01-01 09:00:00.000000000 +0900 @@ -1,240 +0,0 @@ -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/agp_backend.h> -#include "agp.h" - -static int intel_7505_fetch_size(void) -{ - int i; - u16 tmp; - struct aper_size_info_16 *values; - - /* - * For AGP 3.0 APSIZE is now 16 bits - */ - pci_read_config_word (agp_bridge->dev, INTEL_I7505_APSIZE, &tmp); - tmp = (tmp & 0xfff); - - values = A_SIZE_16(agp_bridge->aperture_sizes); - - for (i=0; i < agp_bridge->num_aperture_sizes; i++) { - if (tmp == 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_7505_tlbflush(agp_memory *mem) -{ - u32 temp; - pci_read_config_dword(agp_bridge->dev, INTEL_I7505_AGPCTRL, &temp); - pci_write_config_dword(agp_bridge->dev, INTEL_I7505_AGPCTRL, temp & ~(1 << 7)); - pci_read_config_dword(agp_bridge->dev, INTEL_I7505_AGPCTRL, &temp); - pci_write_config_dword(agp_bridge->dev, INTEL_I7505_AGPCTRL, temp | (1 << 7)); -} - -static void intel_7505_cleanup(void) -{ - struct aper_size_info_16 *previous_size; - - previous_size = A_SIZE_16(agp_bridge->previous_size); - pci_write_config_byte(agp_bridge->dev, INTEL_I7505_APSIZE, - previous_size->size_value); -} - - -static int intel_7505_configure(void) -{ - u32 temp; - 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_I7505_APSIZE, - current_size->size_value); - - /* address to map to */ - pci_read_config_dword(agp_bridge->dev, INTEL_I7505_NAPBASELO, &temp); - agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - - /* attbase */ - pci_write_config_dword(agp_bridge->dev, INTEL_I7505_ATTBASE, - agp_bridge->gatt_bus_addr); - - /* agpctrl */ - pci_write_config_dword(agp_bridge->dev, INTEL_I7505_AGPCTRL, 0x0000); - - /* clear error registers */ - pci_write_config_byte(agp_bridge->dev, INTEL_I7505_ERRSTS, 0xff); - return 0; -} - -static struct aper_size_info_16 intel_7505_sizes[7] = -{ - {256, 65536, 6, 0xf00}, - {128, 32768, 5, 0xf20}, - {64, 16384, 4, 0xf30}, - {32, 8192, 3, 0xf38}, - {16, 4096, 2, 0xf3c}, - {8, 2048, 1, 0xf3e}, - {4, 1024, 0, 0xf3f} -}; - -static unsigned long i7x05_mask_memory(unsigned long addr, int type) -{ - /* Memory type is ignored */ - return addr | agp_bridge->masks[0].mask; -} - -static struct gatt_mask i7x05_generic_masks[] = -{ - {.mask = 0x00000017, .type = 0} -}; - - -static int __init intel_7505_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = i7x05_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_7505_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_7505_configure; - agp_bridge->fetch_size = intel_7505_fetch_size; - agp_bridge->cleanup = intel_7505_cleanup; - agp_bridge->tlb_flush = intel_7505_tlbflush; - agp_bridge->mask_memory = i7x05_mask_memory; - agp_bridge->agp_enable = agp_generic_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; -} - -struct agp_device_ids i7x05_agp_device_ids[] __initdata = -{ - { - .device_id = PCI_DEVICE_ID_INTEL_7505_0, - .chipset = INTEL_I7505, - .chipset_name = "i7505", - }, - { - .device_id = PCI_DEVICE_ID_INTEL_7205_0, - .chipset = INTEL_I7505, - .chipset_name = "i7205", - }, - { }, /* dummy final entry, always present */ -}; - -/* scan table above for supported devices */ -static int __init agp_lookup_host_bridge (struct pci_dev *pdev) -{ - int j=0; - struct agp_device_ids *devs; - - devs = i7x05_agp_device_ids; - - while (devs[j].chipset_name != NULL) { - if (pdev->device == devs[j].device_id) { - printk (KERN_INFO PFX "Detected Intel %s chipset\n", - devs[j].chipset_name); - agp_bridge->type = devs[j].chipset; - - if (devs[j].chipset_setup != NULL) - return devs[j].chipset_setup(pdev); - else - return intel_7505_setup(pdev); - } - j++; - } - - printk(KERN_ERR PFX "Unsupported Intel chipset (device id: %04x),", - pdev->device); - return -ENODEV; -} - -static struct agp_driver i7x05_agp_driver = { - .owner = THIS_MODULE, -}; - -static int __init agp_i7x05_probe (struct pci_dev *dev, const struct pci_device_id *ent) -{ - u8 cap_ptr = 0; - - cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); - if (cap_ptr == 0) - return -ENODEV; - - if (agp_lookup_host_bridge(dev) != -ENODEV) { - agp_bridge->dev = dev; - agp_bridge->capndx = cap_ptr; - /* Fill in the mode register */ - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode); - i7x05_agp_driver.dev = dev; - agp_register_driver(&i7x05_agp_driver); - return 0; - } - return -ENODEV; -} - - -static struct pci_device_id agp_i7x05_pci_table[] __initdata = { - { - .class = (PCI_CLASS_BRIDGE_HOST << 8), - .class_mask = ~0, - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { } -}; - -MODULE_DEVICE_TABLE(pci, agp_i7x05_pci_table); - -static struct __initdata pci_driver agp_i7x05_pci_driver = { - .name = "agpgart-i7x05", - .id_table = agp_i7x05_pci_table, - .probe = agp_i7x05_probe, -}; - -int __init agp_i7x05_init(void) -{ - int ret_val; - - ret_val = pci_module_init(&agp_i7x05_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - return ret_val; -} - -static void __exit agp_i7x05_cleanup(void) -{ - agp_unregister_driver(&i7x05_agp_driver); - pci_unregister_driver(&agp_i7x05_pci_driver); -} - -module_init(agp_i7x05_init); -module_exit(agp_i7x05_cleanup); - -MODULE_AUTHOR("Matthew E Tolentino <matthew.e.tolentino@intel.com>"); -MODULE_LICENSE("GPL and additional rights"); - --- linux-2.5/drivers/char/agp/generic.c.orig 2003-03-27 01:17:44.000000000 +0900 +++ linux-2.5/drivers/char/agp/generic.c 2003-03-27 01:18:45.000000000 +0900 @@ -415,18 +415,15 @@ } } #endif - - if (major < 3) { - pci_read_config_dword(agp_bridge->dev, + pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_STATUS, &command); - command = agp_collect_device_status(mode, command); - command |= 0x100; - - pci_write_config_dword(agp_bridge->dev, + command = agp_collect_device_status(mode, command); + command |= 0x100; + + pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_COMMAND, command); - agp_device_command(command, 0); - } + agp_device_command(command, 0); } int agp_generic_create_gatt_table(void)
-- ISHIKAWA Mutsumi <ishikawa@linux.or.jp>, <ishikawa@debian.org>, <ishikawa@netvillage.co.jp> - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |