Sophie

Sophie

distrib > PLD > ac > amd64 > by-pkgid > 950ec4453099b5125884e99014f11757 > files > 98

kernel24-2.4.34-1.src.rpm

diff -urN linux-2.4.22.org/drivers/char/agp/agpgart_be.c linux-2.4.22/drivers/char/agp/agpgart_be.c
--- linux-2.4.22.org/drivers/char/agp/agpgart_be.c	2003-11-21 18:32:42.000000000 +0100
+++ linux-2.4.22/drivers/char/agp/agpgart_be.c	2003-11-21 18:34:41.000000000 +0100
@@ -53,6 +53,10 @@
 #include <asm/msr.h>
 #endif
 
+#ifdef CONFIG_AGP_UNINORTH
+#include <asm/uninorth.h>
+#endif
+
 #include <linux/agp_backend.h>
 #include "agp.h"
 
@@ -81,7 +85,7 @@
 {
 #if defined(__i386__) || defined(__x86_64__)
 	asm volatile ("wbinvd":::"memory");
-#elif defined(__alpha__) || defined(__ia64__) || defined(__sparc__)
+#elif defined(__alpha__) || defined(__ia64__) || defined(__sparc__) || defined(__powerpc__)
 	/* ??? I wonder if we'll really need to flush caches, or if the
 	   core logic can manage to keep the system coherent.  The ARM
 	   speaks only of using `cflush' to get things in memory in
@@ -5918,6 +5922,405 @@
 }
 #endif /* CONFIG_AGP_ATI */
 
+#ifdef CONFIG_AGP_UNINORTH
+
+static int uninorth_fetch_size(void)
+{
+	int i;
+	u32 temp;
+	aper_size_info_32 *values;
+
+	pci_read_config_dword(agp_bridge.dev, UNI_N_CFG_GART_BASE, &temp);
+	temp &= ~(0xfffff000);
+	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;
+		}
+	}
+
+	agp_bridge.previous_size =
+	    agp_bridge.current_size = (void *) (values + 1);
+	agp_bridge.aperture_size_idx = 1;
+	return values[1].size;
+
+	return 0;
+}
+
+static void uninorth_tlbflush(agp_memory * mem)
+{
+	pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL,
+			UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL);
+	pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL,
+			UNI_N_CFG_GART_ENABLE);
+	pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL,
+			UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_2xRESET);
+	pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL,
+			UNI_N_CFG_GART_ENABLE);
+}
+
+static void uninorth_cleanup(void)
+{
+	pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL,
+			UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL);
+	pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL,
+			0);
+	pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL,
+			UNI_N_CFG_GART_2xRESET);
+	pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL,
+			0);
+}
+
+static int uninorth_configure(void)
+{
+	aper_size_info_32 *current_size;
+	
+	current_size = A_SIZE_32(agp_bridge.current_size);
+
+	printk("agp: configuring for size idx: %d\n", current_size->size_value);
+	
+	/* aperture size and gatt addr */
+	pci_write_config_dword(agp_bridge.dev,
+		UNI_N_CFG_GART_BASE,
+		(agp_bridge.gatt_bus_addr & 0xfffff000)
+			| current_size->size_value);
+
+	/* HACK ALERT
+	 * UniNorth seem to be buggy enough not to handle properly when
+	 * the AGP aperture isn't mapped at bus physical address 0
+	 */
+	agp_bridge.gart_bus_addr = 0;
+	pci_write_config_dword(agp_bridge.dev,
+		UNI_N_CFG_AGP_BASE, agp_bridge.gart_bus_addr);
+	
+	return 0;
+}
+
+static unsigned long uninorth_mask_memory(unsigned long addr, int type)
+{
+	return addr;/* | agp_bridge.masks[0].mask;*/
+}
+
+static int uninorth_insert_memory(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_32(temp)->num_entries;
+
+	if (type != 0 || mem->type != 0) {
+		/* The generic routines know nothing of memory types */
+		return -EINVAL;
+	}
+	if ((pg_start + mem->page_count) > num_entries) {
+		return -EINVAL;
+	}
+	j = pg_start;
+
+	while (j < (pg_start + mem->page_count)) {
+		if (!PGE_EMPTY(agp_bridge.gatt_table[j])) {
+			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++) {
+		agp_bridge.gatt_table[j] = cpu_to_le32((mem->memory[i] & 0xfffff000) | 0x00000001UL);
+		flush_dcache_range(__va(mem->memory[i]), __va(mem->memory[i])+0x1000);
+	}
+	(void)in_le32((volatile u32*)&agp_bridge.gatt_table[pg_start]);
+	mb();
+	flush_dcache_range((unsigned long)&agp_bridge.gatt_table[pg_start], 
+		(unsigned long)&agp_bridge.gatt_table[pg_start + mem->page_count]);
+
+	agp_bridge.tlb_flush(mem);
+	return 0;
+}
+
+static void uninorth_agp_enable(u32 mode)
+{
+	struct pci_dev *device = NULL;
+	u32 command, scratch, cap_id;
+	u8 cap_ptr;
+
+	pci_read_config_dword(agp_bridge.dev,
+			      agp_bridge.capndx + 4,
+			      &command);
+
+	/*
+	 * PASS1: go throu all devices that claim to be
+	 *        AGP devices and collect their data.
+	 */
+
+	while ((device = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8,
+					device)) != NULL) {
+		pci_read_config_dword(device, 0x04, &scratch);
+
+		if (!(scratch & 0x00100000))
+			continue;
+
+		pci_read_config_byte(device, 0x34, &cap_ptr);
+
+		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 if it's not supported */
+			if (!((command & 0x00000010) &&
+			      (scratch & 0x00000010) &&
+			      (mode & 0x00000010)))
+				command &= ~0x00000010;
+
+			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;
+
+	uninorth_tlbflush(NULL);
+
+	do {
+		pci_write_config_dword(agp_bridge.dev,
+				       agp_bridge.capndx + 8,
+				       command);
+		pci_read_config_dword(agp_bridge.dev,
+				       agp_bridge.capndx + 8,
+				       &scratch);
+	} while((scratch & 0x100) == 0);
+
+	/*
+	 * PASS3: Go throu all AGP devices and update the
+	 *        command registers.
+	 */
+
+	while ((device = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8,
+					device)) != NULL) {
+		pci_read_config_dword(device, 0x04, &scratch);
+
+		if (!(scratch & 0x00100000))
+			continue;
+
+		pci_read_config_byte(device, 0x34, &cap_ptr);
+
+		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)
+			pci_write_config_dword(device, cap_ptr + 8, command);
+	}
+
+	uninorth_tlbflush(NULL);
+}
+
+static int uninorth_create_gatt_table(void)
+{
+	char *table;
+	char *table_end;
+	int size;
+	int page_order;
+	int num_entries;
+	int i;
+	void *temp;
+	struct page *page;
+
+	/* The generic routines can't handle 2 level gatt's */
+	if (agp_bridge.size_type == LVL2_APER_SIZE) {
+		return -EINVAL;
+	}
+
+	table = NULL;
+	i = agp_bridge.aperture_size_idx;
+	temp = agp_bridge.current_size;
+	size = page_order = num_entries = 0;
+
+	do {
+		size = A_SIZE_32(temp)->size;
+		page_order = A_SIZE_32(temp)->page_order;
+		num_entries = A_SIZE_32(temp)->num_entries;
+
+		table = (char *) __get_free_pages(GFP_KERNEL, page_order);
+
+		if (table == NULL) {
+			i++;
+			agp_bridge.current_size = A_IDX32();
+		} else {
+			agp_bridge.aperture_size_idx = i;
+		}
+	} while ((table == NULL) &&
+			 (i < agp_bridge.num_aperture_sizes));
+
+	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++)
+		SetPageReserved(page);
+
+	agp_bridge.gatt_table_real = (unsigned long *) table;
+	agp_bridge.gatt_table = (unsigned long *)table;
+	agp_bridge.gatt_bus_addr = virt_to_phys(table);
+
+	for (i = 0; i < num_entries; i++) {
+		agp_bridge.gatt_table[i] =
+		    (unsigned long) agp_bridge.scratch_page;
+	}
+
+	flush_dcache_range((unsigned long)table, (unsigned long)table_end);
+
+	return 0;
+}
+
+static int uninorth_free_gatt_table(void)
+{
+	int page_order;
+	char *table, *table_end;
+	void *temp;
+	struct page *page;
+
+	temp = agp_bridge.current_size;
+	page_order = A_SIZE_32(temp)->page_order;
+
+	/* Do not worry about freeing memory, because if this is
+	 * called, then all agp memory is deallocated and removed
+	 * from the table.
+	 */
+
+	table = (char *) agp_bridge.gatt_table_real;
+	table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
+
+	for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
+		ClearPageReserved(page);
+
+	free_pages((unsigned long) agp_bridge.gatt_table_real, page_order);
+
+	return 0;
+}
+
+/* Setup function */
+static gatt_mask uninorth_masks[] =
+{
+	{0x00000000, 0}
+};
+
+static aper_size_info_32 uninorth_sizes[7] =
+{
+#if 0 /* Not sure uninorth supports that high aperture sizes */
+	{256, 65536, 6, 64},
+	{128, 32768, 5, 32},
+	{64, 16384, 4, 16},
+#endif	
+	{32, 8192, 3, 8},
+	{16, 4096, 2, 4},
+	{8, 2048, 1, 2},
+	{4, 1024, 0, 1}
+};
+
+static int __init uninorth_setup (struct pci_dev *pdev)
+{
+	agp_bridge.masks = uninorth_masks;
+	agp_bridge.num_of_masks = 1;
+	agp_bridge.aperture_sizes = (void *)uninorth_sizes;
+	agp_bridge.size_type = U32_APER_SIZE;
+	agp_bridge.num_aperture_sizes = 4; //7;
+	agp_bridge.dev_private_data = NULL;
+	agp_bridge.needs_scratch_page = FALSE;
+	agp_bridge.configure = uninorth_configure;
+	agp_bridge.fetch_size = uninorth_fetch_size;
+	agp_bridge.cleanup = uninorth_cleanup;
+	agp_bridge.tlb_flush = uninorth_tlbflush;
+	agp_bridge.mask_memory = uninorth_mask_memory;
+	agp_bridge.agp_enable = uninorth_agp_enable;
+	agp_bridge.cache_flush = global_cache_flush;
+	agp_bridge.create_gatt_table = uninorth_create_gatt_table;
+	agp_bridge.free_gatt_table = uninorth_free_gatt_table;
+	agp_bridge.insert_memory = uninorth_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 = 1;
+
+	return 0;
+	
+	(void) pdev; /* unused */
+}
+
+#endif /* CONFIG_AGP_UNINORTH */
+
 /* per-chipset initialization data.
  * note -- all chipsets for a single vendor MUST be grouped together
  */
@@ -6462,6 +6865,27 @@
 	  ati_generic_setup },
 #endif /* CONFIG_AGP_ATI */
 
+#ifdef CONFIG_AGP_UNINORTH
+	{ PCI_DEVICE_ID_APPLE_UNI_N_AGP,
+		PCI_VENDOR_ID_APPLE,
+		APPLE_UNINORTH,
+		"Apple",
+		"UniNorth",
+		uninorth_setup },
+	{ PCI_DEVICE_ID_APPLE_UNI_N_AGP_P,
+		PCI_VENDOR_ID_APPLE,
+		APPLE_UNINORTH,
+		"Apple",
+		"UniNorth/Pangea",
+		uninorth_setup },
+	{ PCI_DEVICE_ID_APPLE_UNI_N_AGP15,
+		PCI_VENDOR_ID_APPLE,
+		APPLE_UNINORTH,
+		"Apple",
+		"UniNorth 1.5",
+		uninorth_setup },
+#endif /* CONFIG_AGP_UNINORTH */
+
 	{ 0, }, /* dummy final entry, always present */
 };
 
diff -urN linux-2.4.22.org/drivers/char/Config.in linux-2.4.22/drivers/char/Config.in
--- linux-2.4.22.org/drivers/char/Config.in	2003-11-21 18:32:29.000000000 +0100
+++ linux-2.4.22/drivers/char/Config.in	2003-11-21 18:34:42.000000000 +0100
@@ -210,6 +210,9 @@
       comment '  from the tpqic02-support package.  It is available at'
       comment '  metalab.unc.edu or ftp://titus.cfw.com/pub/Linux/util/'
    fi
+   if [ "$CONFIG_ALL_PPC" = "y" ]; then
+      bool '  Apple UniNorth support' CONFIG_AGP_UNINORTH
+   fi
 fi
 
 tristate 'IPMI top-level message handler' CONFIG_IPMI_HANDLER
diff -urN linux-2.4.22.org/include/linux/agp_backend.h linux-2.4.22/include/linux/agp_backend.h
--- linux-2.4.22.org/include/linux/agp_backend.h	2003-11-21 18:31:25.000000000 +0100
+++ linux-2.4.22/include/linux/agp_backend.h	2003-11-21 18:35:20.000000000 +0100
@@ -95,6 +95,7 @@
 	NVIDIA_NFORCE3,
 	NVIDIA_GENERIC,
 	HP_ZX1,
+	APPLE_UNINORTH,
 	ATI_RS100,
 	ATI_RS200,
 	ATI_RS250,