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>