Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 26 Nov 2001 21:37:46 GMT
From:      Joe Orthoefer <joeo@nks.net>
To:        FreeBSD-gnats-submit@freebsd.org
Cc:        joeo@cracktown.com, dfr@freebsd.org
Subject:   i386/32301: Fix for agpgart for the AMD-751 and related parts
Message-ID:  <200111262137.fAQLbkq00423@juju.nks.net>

next in thread | raw e-mail | index | archive | help

>Number:         32301
>Category:       i386
>Synopsis:       Fix for agpgart for the AMD-751 and related parts
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Nov 26 13:40:00 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:     joeo@nks.net
>Release:        FreeBSD 4.4-RELEASE i386
>Organization:
Networked Knowledge Systems
>Environment:
System: FreeBSD juju.nks.net 4.4-RELEASE FreeBSD 4.4-RELEASE #3: Mon Nov 5 20:51:27 GMT 2001 root@juju.nks.net:/usr/src/sys/compile/juju i386


>Description:
	AGP functionality for this chipset isn't working with the supplied
	driver.  The page directory needs its entries offset into it
	by an amount determined by the base address of the aperture.
	
>How-To-Repeat:

>Fix:
	This patch should correctly populate the page directory with
	the addresses of the gatt tables.  Also the linux driver for
	this chipset seems to indicate that the programatic interface
	for the amd_751 (irongate northbridge part), amd_761 (improved
	part capable of AGP4x operation, socket A?), and amd_762 
	(part of the 760mp chipset) are identical for AGP functionality. 

*** agpreg.h.old        Mon Nov 26 19:30:39 2001
--- agpreg.h   Tue Nov 20 20:10:54 2001
***************
*** 81,86 ****
--- 81,87 ----
  /*
   * Config offsets for the AMD 751 chipset.
   */
+ #define AGP_AMD751_APBASE     0x10
  #define AGP_AMD751_REGISTERS  0x14
  #define AGP_AMD751_APCTRL     0xac
  #define AGP_AMD751_MODECTRL   0xb0

*** agp_amd.c.old	Mon Nov 26 21:10:45 2001
--- agp_amd.c	Mon Nov 26 21:05:14 2001
***************
*** 58,66 ****
  
  struct agp_amd_gatt {
  	u_int32_t	ag_entries;
  	u_int32_t      *ag_vdir;	/* virtual address of page dir */
  	vm_offset_t	ag_pdir;	/* physical address of page dir */
- 	u_int32_t      *ag_virtual;	/* virtual address of gatt */
  };
  
  struct agp_amd_softc {
--- 58,67 ----
  
  struct agp_amd_gatt {
  	u_int32_t	ag_entries;
+ 	u_int32_t      *ag_virtual;	/* virtual address of gatt */
+ 	vm_offset_t	ag_physical;	/* physical address of the gatt */
  	u_int32_t      *ag_vdir;	/* virtual address of page dir */
  	vm_offset_t	ag_pdir;	/* physical address of page dir */
  };
  
  struct agp_amd_softc {
***************
*** 78,84 ****
  	u_int32_t apsize = AGP_GET_APERTURE(dev);
  	u_int32_t entries = apsize >> AGP_PAGE_SHIFT;
  	struct agp_amd_gatt *gatt;
! 	int i, npages;
  
  	if (bootverbose)
  		device_printf(dev,
--- 79,85 ----
  	u_int32_t apsize = AGP_GET_APERTURE(dev);
  	u_int32_t entries = apsize >> AGP_PAGE_SHIFT;
  	struct agp_amd_gatt *gatt;
! 	int i, npages, pdir_offset;
  
  	if (bootverbose)
  		device_printf(dev,
***************
*** 92,113 ****
  	/*
  	 * The AMD751 uses a page directory to map a non-contiguous
  	 * gatt so we don't need to use contigmalloc.
  	 */
- 	gatt->ag_entries = entries;
- 	gatt->ag_virtual = malloc(entries * sizeof(u_int32_t),
- 				  M_AGP, M_NOWAIT);
- 	if (!gatt->ag_virtual) {
- 		if (bootverbose)
- 			device_printf(dev, "allocation failed\n");
- 		free(gatt, M_AGP);
- 		return 0;
- 	}
- 	bzero(gatt->ag_virtual, entries * sizeof(u_int32_t));
  
  	/*
  	 * Allocate the page directory.
  	 */
  	gatt->ag_vdir = malloc(AGP_PAGE_SIZE, M_AGP, M_NOWAIT);
  	if (!gatt->ag_vdir) {
  		if (bootverbose)
  			device_printf(dev,
--- 93,108 ----
  	/*
  	 * The AMD751 uses a page directory to map a non-contiguous
  	 * gatt so we don't need to use contigmalloc.
+ 	 * Malloc indiviual gatt pages and map them into the page
+ 	 * directory.   
  	 */
  
  	/*
  	 * Allocate the page directory.
  	 */
  	gatt->ag_vdir = malloc(AGP_PAGE_SIZE, M_AGP, M_NOWAIT);
+ 	bzero(gatt->ag_vdir, AGP_PAGE_SIZE);
+ 
  	if (!gatt->ag_vdir) {
  		if (bootverbose)
  			device_printf(dev,
***************
*** 116,130 ****
  		free(gatt, M_AGP);
  		return 0;
  	}
- 	bzero(gatt->ag_vdir, AGP_PAGE_SIZE);
  	gatt->ag_pdir = vtophys((vm_offset_t) gatt->ag_vdir);
! 	gatt->ag_pdir = vtophys(gatt->ag_virtual);
  
  	/*
  	 * Map the pages of the GATT into the page directory.
  	 */
  	npages = ((entries * sizeof(u_int32_t) + AGP_PAGE_SIZE - 1)
  		  >> AGP_PAGE_SHIFT);
  	for (i = 0; i < npages; i++) {
  		vm_offset_t va;
  		vm_offset_t pa;
--- 111,157 ----
  		free(gatt, M_AGP);
  		return 0;
  	}
  	gatt->ag_pdir = vtophys((vm_offset_t) gatt->ag_vdir);
! 		if (bootverbose)
!                   device_printf(dev,
!                        "gatt -> ag_pdir %8x\n",
! 			(vm_offset_t) gatt->ag_pdir );
! 
! 	/*
! 	 * Allocate the gatt pages
! 	 */
! 	gatt->ag_entries = entries;
! 	if (bootverbose)
!                 device_printf(dev,
!                               "allocating GATT for %d AGP page entries\n",
!                               gatt->ag_entries = entries);
! 
! 	gatt->ag_virtual = malloc(entries * sizeof(u_int32_t),
! 				  M_AGP, M_NOWAIT);
! 
! 	if (!gatt->ag_virtual) {
! 		if (bootverbose)
! 			device_printf(dev, "allocation failed\n");
! 		free(gatt, M_AGP);
! 		return 0;
! 	}
! 	bzero(gatt->ag_virtual, entries * sizeof(u_int32_t));
! 	gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual);
  	
  	/*
  	 * Map the pages of the GATT into the page directory.
+ 	 *
+ 	 * The gatt page addresses are mapped into the directory
+ 	 * offset by an amount dependent on the base address of the 
+ 	 * aperture.  This is an offset into the page directory
+ 	 * not an offset added to the addresses of the gatt pages.
  	 */
+ 	
+ 	pdir_offset = pci_read_config(dev, AGP_AMD751_APBASE, 4) >> 22;
+ 
  	npages = ((entries * sizeof(u_int32_t) + AGP_PAGE_SIZE - 1)
  		  >> AGP_PAGE_SHIFT);
+ 
  	for (i = 0; i < npages; i++) {
  		vm_offset_t va;
  		vm_offset_t pa;
***************
*** 131,137 ****
  
  		va = ((vm_offset_t) gatt->ag_virtual) + i * AGP_PAGE_SIZE;
  		pa = vtophys(va);
! 		gatt->ag_vdir[i] = pa | 1;
  	}
  
  	/*
--- 158,164 ----
  
  		va = ((vm_offset_t) gatt->ag_virtual) + i * AGP_PAGE_SIZE;
  		pa = vtophys(va);
! 		gatt->ag_vdir[i + pdir_offset ] = pa | 1;
  	}
  
  	/*
***************
*** 163,168 ****
--- 190,201 ----
  	switch (pci_get_devid(dev)) {
  	case 0x70061022:
  		return ("AMD 751 host to AGP bridge");
+ 
+ 	case 0x700e1022:
+ 		return ("AMD 761 host to AGP bridge");
+ 
+ 	case 0x700c1022:
+ 		return ("AMD 762 host to AGP bridge");
  	};
  
  	return NULL;
***************
*** 301,309 ****
  
  	vas = ffs(aperture / 32*1024*1024) - 1;
  	
  	pci_write_config(dev, AGP_AMD751_APCTRL,
! 			 ((pci_read_config(dev, AGP_AMD751_APCTRL, 1) & ~0x06)
! 			  | vas << 1), 1);
  
  	return 0;
  }
--- 335,348 ----
  
  	vas = ffs(aperture / 32*1024*1024) - 1;
  
+ 	/*
+ 	 * while the size register is bits 1-3 of APCTRL, bit 0 needs
+ 	 * be set for the size value to be "valid"
+ 	 */
+ 	
  	pci_write_config(dev, AGP_AMD751_APCTRL,
! 		(((pci_read_config(dev, AGP_AMD751_APCTRL, 1) & ~0x06) 
! 		  | ((vas << 1) | 1))), 1); 
  
  	return 0;
  }
***************
*** 316,322 ****
  	if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
  		return EINVAL;
  
! 	sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical | 1;
  	return 0;
  }
  
--- 355,366 ----
  	if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
  		return EINVAL;
  
! 	sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical | 1 ; 
! 
! 	/* ivalidate the cache */
! 	AGP_FLUSH_TLB(dev);
! 	
! 	
  	return 0;
  }
  
>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200111262137.fAQLbkq00423>