mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2025-12-25 20:00:13 +01:00
pcigart code ported for FreeBSD. Untested, disabled by default. Flip
__REALLY_HAVE_SG in drm_os_freebsd.h to test.
This commit is contained in:
parent
e19e0e4148
commit
76b60581df
12 changed files with 146 additions and 298 deletions
|
|
@ -46,21 +46,10 @@
|
|||
static unsigned long DRM(ati_alloc_pcigart_table)( void )
|
||||
{
|
||||
unsigned long address;
|
||||
struct page *page;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||
|
||||
address = __get_free_pages( GFP_KERNEL, ATI_PCIGART_TABLE_ORDER );
|
||||
if ( address == 0UL ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
page = virt_to_page( address );
|
||||
|
||||
for ( i = 0 ; i <= ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
|
||||
atomic_inc( &page->count );
|
||||
SetPageReserved( page );
|
||||
}
|
||||
address = (unsigned long) malloc( (1 << ATI_PCIGART_TABLE_ORDER) * PAGE_SIZE, DRM(M_DRM), M_WAITOK );
|
||||
|
||||
DRM_DEBUG( "%s: returning 0x%08lx\n", __FUNCTION__, address );
|
||||
return address;
|
||||
|
|
@ -68,18 +57,9 @@ static unsigned long DRM(ati_alloc_pcigart_table)( void )
|
|||
|
||||
static void DRM(ati_free_pcigart_table)( unsigned long address )
|
||||
{
|
||||
struct page *page;
|
||||
int i;
|
||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||
|
||||
page = virt_to_page( address );
|
||||
|
||||
for ( i = 0 ; i <= ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
|
||||
atomic_dec( &page->count );
|
||||
ClearPageReserved( page );
|
||||
}
|
||||
|
||||
free_pages( address, ATI_PCIGART_TABLE_ORDER );
|
||||
free( (void *)address, DRM(M_DRM));
|
||||
}
|
||||
|
||||
int DRM(ati_pcigart_init)( drm_device_t *dev,
|
||||
|
|
@ -87,9 +67,8 @@ int DRM(ati_pcigart_init)( drm_device_t *dev,
|
|||
dma_addr_t *bus_addr)
|
||||
{
|
||||
drm_sg_mem_t *entry = dev->sg;
|
||||
unsigned long address = 0;
|
||||
unsigned long pages;
|
||||
u32 *pci_gart, page_base, bus_address = 0;
|
||||
u32 *pci_gart=0, page_base, bus_address = 0;
|
||||
int i, j, ret = 0;
|
||||
|
||||
if ( !entry ) {
|
||||
|
|
@ -97,8 +76,8 @@ int DRM(ati_pcigart_init)( drm_device_t *dev,
|
|||
goto done;
|
||||
}
|
||||
|
||||
address = DRM(ati_alloc_pcigart_table)();
|
||||
if ( !address ) {
|
||||
pci_gart = (u32 *)DRM(ati_alloc_pcigart_table)();
|
||||
if ( !pci_gart ) {
|
||||
DRM_ERROR( "cannot allocate PCI GART page!\n" );
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -108,33 +87,30 @@ int DRM(ati_pcigart_init)( drm_device_t *dev,
|
|||
goto done;
|
||||
}
|
||||
|
||||
bus_address = pci_map_single(dev->pdev, (void *)address,
|
||||
/* FIXME non-vtophys==bustophys-arches */
|
||||
bus_address = vtophys( pci_gart );
|
||||
/*pci_map_single(dev->pdev, (void *)address,
|
||||
ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
|
||||
PCI_DMA_TODEVICE);
|
||||
PCI_DMA_TODEVICE);*/
|
||||
if (bus_address == 0) {
|
||||
DRM_ERROR( "unable to map PCIGART pages!\n" );
|
||||
DRM(ati_free_pcigart_table)( address );
|
||||
address = 0;
|
||||
DRM(ati_free_pcigart_table)( (unsigned long)pci_gart );
|
||||
pci_gart = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
pci_gart = (u32 *)address;
|
||||
|
||||
pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
|
||||
? entry->pages : ATI_MAX_PCIGART_PAGES;
|
||||
|
||||
memset( pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32) );
|
||||
bzero( pci_gart, ATI_MAX_PCIGART_PAGES * sizeof(u32) );
|
||||
|
||||
for ( i = 0 ; i < pages ; i++ ) {
|
||||
/* we need to support large memory configurations */
|
||||
entry->busaddr[i] = pci_map_single(dev->pdev,
|
||||
page_address( entry->pagelist[i] ),
|
||||
PAGE_SIZE,
|
||||
PCI_DMA_TODEVICE);
|
||||
/* FIXME non-vtophys==bustophys-arches */
entry->busaddr[i] = vtophys( entry->handle + (i*PAGE_SIZE) );
|
||||
if (entry->busaddr[i] == 0) {
|
||||
DRM_ERROR( "unable to map PCIGART pages!\n" );
|
||||
DRM(ati_pcigart_cleanup)( dev, address, bus_address );
|
||||
address = 0;
|
||||
DRM(ati_pcigart_cleanup)( dev, (unsigned long)pci_gart, bus_address );
|
||||
pci_gart = 0;
|
||||
bus_address = 0;
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -148,14 +124,10 @@ int DRM(ati_pcigart_init)( drm_device_t *dev,
|
|||
|
||||
ret = 1;
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
asm volatile ( "wbinvd" ::: "memory" );
|
||||
#else
|
||||
mb();
|
||||
#endif
|
||||
DRM_OS_READMEMORYBARRIER;
|
||||
|
||||
done:
|
||||
*addr = address;
|
||||
*addr = (unsigned long)pci_gart;
|
||||
*bus_addr = bus_address;
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -165,8 +137,6 @@ int DRM(ati_pcigart_cleanup)( drm_device_t *dev,
|
|||
dma_addr_t bus_addr)
|
||||
{
|
||||
drm_sg_mem_t *entry = dev->sg;
|
||||
unsigned long pages;
|
||||
int i;
|
||||
|
||||
/* we need to support large memory configurations */
|
||||
if ( !entry ) {
|
||||
|
|
@ -174,21 +144,6 @@ int DRM(ati_pcigart_cleanup)( drm_device_t *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if ( bus_addr ) {
|
||||
pci_unmap_single(dev->pdev, bus_addr,
|
||||
ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
|
||||
? entry->pages : ATI_MAX_PCIGART_PAGES;
|
||||
|
||||
for ( i = 0 ; i < pages ; i++ ) {
|
||||
if ( !entry->busaddr[i] ) break;
|
||||
pci_unmap_single(dev->pdev, entry->busaddr[i],
|
||||
PAGE_SIZE, PCI_DMA_TODEVICE);
|
||||
}
|
||||
}
|
||||
|
||||
if ( addr ) {
|
||||
DRM(ati_free_pcigart_table)( addr );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -374,6 +374,7 @@ typedef struct drm_sg_mem {
|
|||
void *virtual;
|
||||
int pages;
|
||||
struct page **pagelist;
|
||||
dma_addr_t *busaddr;
|
||||
} drm_sg_mem_t;
|
||||
|
||||
typedef struct drm_sigdata {
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ static drm_ioctl_desc_t DRM(ioctls)[] = {
|
|||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { DRM(agp_unbind), 1, 1 },
|
||||
#endif
|
||||
|
||||
#if __REALLY_HAVE_SG
|
||||
#if __HAVE_SG
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { DRM(sg_alloc), 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { DRM(sg_free), 1, 1 },
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ typedef struct drm_chipinfo
|
|||
char *name;
|
||||
} drm_chipinfo_t;
|
||||
|
||||
typedef u_int32_t dma_addr_t;
|
||||
typedef u_int32_t atomic_t;
|
||||
typedef u_int32_t cycles_t;
|
||||
typedef u_int32_t spinlock_t;
|
||||
|
|
|
|||
|
|
@ -27,25 +27,15 @@
|
|||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include <linux/config.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include "drmP.h"
|
||||
|
||||
#define DEBUG_SCATTER 0
|
||||
|
||||
#if __REALLY_HAVE_SG
|
||||
|
||||
void DRM(sg_cleanup)( drm_sg_mem_t *entry )
|
||||
{
|
||||
struct page *page;
|
||||
int i;
|
||||
|
||||
for ( i = 0 ; i < entry->pages ; i++ ) {
|
||||
page = entry->pagelist[i];
|
||||
if ( page )
|
||||
ClearPageReserved( page );
|
||||
}
|
||||
|
||||
vfree( entry->virtual );
|
||||
free( entry->virtual, DRM(M_DRM) );
|
||||
|
||||
DRM(free)( entry->busaddr,
|
||||
entry->pages * sizeof(*entry->busaddr),
|
||||
|
|
@ -58,33 +48,26 @@ void DRM(sg_cleanup)( drm_sg_mem_t *entry )
|
|||
DRM_MEM_SGLISTS );
|
||||
}
|
||||
|
||||
int DRM(sg_alloc)( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int DRM(sg_alloc)( DRM_OS_IOCTL )
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
DRM_OS_DEVICE;
|
||||
drm_scatter_gather_t request;
|
||||
drm_sg_mem_t *entry;
|
||||
unsigned long pages, i, j;
|
||||
pgd_t *pgd;
|
||||
pmd_t *pmd;
|
||||
pte_t *pte;
|
||||
unsigned long pages;
|
||||
|
||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||
|
||||
if ( dev->sg )
|
||||
return -EINVAL;
|
||||
return EINVAL;
|
||||
|
||||
if ( copy_from_user( &request,
|
||||
(drm_scatter_gather_t *)arg,
|
||||
sizeof(request) ) )
|
||||
return -EFAULT;
|
||||
DRM_OS_KRNFROMUSR(request, (drm_scatter_gather_t *)data,
|
||||
sizeof(request) );
|
||||
|
||||
entry = DRM(alloc)( sizeof(*entry), DRM_MEM_SGLISTS );
|
||||
if ( !entry )
|
||||
return -ENOMEM;
|
||||
return ENOMEM;
|
||||
|
||||
memset( entry, 0, sizeof(*entry) );
|
||||
bzero( entry, sizeof(*entry) );
|
||||
|
||||
pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages );
|
||||
|
|
@ -94,10 +77,10 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
|
|||
DRM_MEM_PAGES );
|
||||
if ( !entry->pagelist ) {
|
||||
DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS );
|
||||
return -ENOMEM;
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
|
||||
bzero(entry->pagelist, pages * sizeof(*entry->pagelist));
|
||||
|
||||
entry->busaddr = DRM(alloc)( pages * sizeof(*entry->busaddr),
|
||||
DRM_MEM_PAGES );
|
||||
|
|
@ -108,11 +91,11 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
|
|||
DRM(free)( entry,
|
||||
sizeof(*entry),
|
||||
DRM_MEM_SGLISTS );
|
||||
return -ENOMEM;
|
||||
return ENOMEM;
|
||||
}
|
||||
memset( (void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr) );
|
||||
bzero( (void *)entry->busaddr, pages * sizeof(*entry->busaddr) );
|
||||
|
||||
entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
|
||||
entry->virtual = malloc( pages << PAGE_SHIFT, DRM(M_DRM), M_WAITOK );
|
||||
if ( !entry->virtual ) {
|
||||
DRM(free)( entry->busaddr,
|
||||
entry->pages * sizeof(*entry->busaddr),
|
||||
|
|
@ -123,45 +106,21 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
|
|||
DRM(free)( entry,
|
||||
sizeof(*entry),
|
||||
DRM_MEM_SGLISTS );
|
||||
return -ENOMEM;
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
/* This also forces the mapping of COW pages, so our page list
|
||||
* will be valid. Please don't remove it...
|
||||
*/
|
||||
memset( entry->virtual, 0, pages << PAGE_SHIFT );
|
||||
bzero( entry->virtual, pages << PAGE_SHIFT );
|
||||
|
||||
entry->handle = (unsigned long)entry->virtual;
|
||||
|
||||
DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle );
|
||||
DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
|
||||
|
||||
for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) {
|
||||
pgd = pgd_offset_k( i );
|
||||
if ( !pgd_present( *pgd ) )
|
||||
goto failed;
|
||||
|
||||
pmd = pmd_offset( pgd, i );
|
||||
if ( !pmd_present( *pmd ) )
|
||||
goto failed;
|
||||
|
||||
pte = pte_offset( pmd, i );
|
||||
if ( !pte_present( *pte ) )
|
||||
goto failed;
|
||||
|
||||
entry->pagelist[j] = pte_page( *pte );
|
||||
|
||||
SetPageReserved( entry->pagelist[j] );
|
||||
}
|
||||
|
||||
request.handle = entry->handle;
|
||||
|
||||
if ( copy_to_user( (drm_scatter_gather_t *)arg,
|
||||
&request,
|
||||
sizeof(request) ) ) {
|
||||
DRM(sg_cleanup)( entry );
|
||||
return -EFAULT;
|
||||
}
|
||||
DRM_OS_KRNTOUSR( (drm_scatter_gather_t *)data,
|
||||
request,
|
||||
sizeof(request) );
|
||||
|
||||
dev->sg = entry;
|
||||
|
||||
|
|
@ -207,29 +166,24 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
|
|||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
DRM(sg_cleanup)( entry );
|
||||
return -ENOMEM;
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
int DRM(sg_free)( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int DRM(sg_free)( DRM_OS_IOCTL )
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
DRM_OS_DEVICE;
|
||||
drm_scatter_gather_t request;
|
||||
drm_sg_mem_t *entry;
|
||||
|
||||
if ( copy_from_user( &request,
|
||||
(drm_scatter_gather_t *)arg,
|
||||
sizeof(request) ) )
|
||||
return -EFAULT;
|
||||
DRM_OS_KRNFROMUSR( request, (drm_scatter_gather_t *)data,
|
||||
sizeof(request) );
|
||||
|
||||
entry = dev->sg;
|
||||
dev->sg = NULL;
|
||||
|
||||
if ( !entry || entry->handle != request.handle )
|
||||
return -EINVAL;
|
||||
return EINVAL;
|
||||
|
||||
DRM_DEBUG( "sg free virtual = %p\n", entry->virtual );
|
||||
|
||||
|
|
@ -237,3 +191,16 @@ int DRM(sg_free)( struct inode *inode, struct file *filp,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* __REALLY_HAVE_SG */
|
||||
|
||||
int DRM(sg_alloc)( DRM_OS_IOCTL )
|
||||
{
|
||||
return DRM_OS_ERR(EINVAL);
|
||||
}
|
||||
int DRM(sg_free)( DRM_OS_IOCTL )
|
||||
{
|
||||
return DRM_OS_ERR(EINVAL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -61,39 +61,39 @@ drm_chipinfo_t DRM(devicelist)[] = {
|
|||
{0x1002, 0x4c46, 1, "ATI Rage 128 Mobility LF"},
|
||||
{0x1002, 0x4d46, 1, "ATI Rage 128 Mobility MF (AGP 4x)"},
|
||||
{0x1002, 0x4d4c, 1, "ATI Rage 128 Mobility ML"},
|
||||
{0x1002, 0x5041, 0, "ATI Rage 128 Pro PA (PCI)"},
|
||||
{0x1002, 0x5041, __REALLY_HAVE_SG, "ATI Rage 128 Pro PA (PCI)"},
|
||||
{0x1002, 0x5042, 1, "ATI Rage 128 Pro PB (AGP 2x)"},
|
||||
{0x1002, 0x5043, 1, "ATI Rage 128 Pro PC (AGP 4x)"},
|
||||
{0x1002, 0x5044, 0, "ATI Rage 128 Pro PD (PCI)"},
|
||||
{0x1002, 0x5044, __REALLY_HAVE_SG, "ATI Rage 128 Pro PD (PCI)"},
|
||||
{0x1002, 0x5045, 1, "ATI Rage 128 Pro PE (AGP 2x)"},
|
||||
{0x1002, 0x5046, 1, "ATI Rage 128 Pro PF (AGP 4x)"},
|
||||
{0x1002, 0x5047, 0, "ATI Rage 128 Pro PG (PCI)"},
|
||||
{0x1002, 0x5047, __REALLY_HAVE_SG, "ATI Rage 128 Pro PG (PCI)"},
|
||||
{0x1002, 0x5048, 1, "ATI Rage 128 Pro PH (AGP)"},
|
||||
{0x1002, 0x5049, 1, "ATI Rage 128 Pro PI (AGP)"},
|
||||
{0x1002, 0x504a, 0, "ATI Rage 128 Pro PJ (PCI)"},
|
||||
{0x1002, 0x504a, __REALLY_HAVE_SG, "ATI Rage 128 Pro PJ (PCI)"},
|
||||
{0x1002, 0x504b, 1, "ATI Rage 128 Pro PK (AGP)"},
|
||||
{0x1002, 0x504c, 1, "ATI Rage 128 Pro PL (AGP)"},
|
||||
{0x1002, 0x504d, 0, "ATI Rage 128 Pro PM (PCI)"},
|
||||
{0x1002, 0x504d, __REALLY_HAVE_SG, "ATI Rage 128 Pro PM (PCI)"},
|
||||
{0x1002, 0x504e, 1, "ATI Rage 128 Pro PN (AGP)"},
|
||||
{0x1002, 0x505f, 1, "ATI Rage 128 Pro PO (AGP)"},
|
||||
{0x1002, 0x5050, 0, "ATI Rage 128 Pro PP (PCI)"},
|
||||
{0x1002, 0x5050, __REALLY_HAVE_SG, "ATI Rage 128 Pro PP (PCI)"},
|
||||
{0x1002, 0x5051, 1, "ATI Rage 128 Pro PQ (AGP)"},
|
||||
{0x1002, 0x5052, 1, "ATI Rage 128 Pro PR (AGP)"},
|
||||
{0x1002, 0x5053, 0, "ATI Rage 128 Pro PS (PCI)"},
|
||||
{0x1002, 0x5053, __REALLY_HAVE_SG, "ATI Rage 128 Pro PS (PCI)"},
|
||||
{0x1002, 0x5054, 1, "ATI Rage 128 Pro PT (AGP)"},
|
||||
{0x1002, 0x5055, 1, "ATI Rage 128 Pro PU (AGP)"},
|
||||
{0x1002, 0x5056, 0, "ATI Rage 128 Pro PV (PCI)"},
|
||||
{0x1002, 0x5056, __REALLY_HAVE_SG, "ATI Rage 128 Pro PV (PCI)"},
|
||||
{0x1002, 0x5057, 1, "ATI Rage 128 Pro PW (AGP)"},
|
||||
{0x1002, 0x5058, 1, "ATI Rage 128 Pro PX (AGP)"},
|
||||
{0x1002, 0x5245, 0, "ATI Rage 128 GL (PCI)"},
|
||||
{0x1002, 0x5245, __REALLY_HAVE_SG, "ATI Rage 128 GL (PCI)"},
|
||||
{0x1002, 0x5246, 1, "ATI Rage 128 GL (AGP 2x)"},
|
||||
{0x1002, 0x524b, 0, "ATI Rage 128 VR (PCI)"},
|
||||
{0x1002, 0x524b, __REALLY_HAVE_SG, "ATI Rage 128 VR (PCI)"},
|
||||
{0x1002, 0x524c, 1, "ATI Rage 128 VR (AGP 2x)"},
|
||||
{0x1002, 0x5345, 0, "ATI Rage 128 SE (PCI)"},
|
||||
{0x1002, 0x5345, __REALLY_HAVE_SG, "ATI Rage 128 SE (PCI)"},
|
||||
{0x1002, 0x5346, 1, "ATI Rage 128 SF (AGP 2x)"},
|
||||
{0x1002, 0x5347, 1, "ATI Rage 128 SG (AGP 4x)"},
|
||||
{0x1002, 0x5348, 0, "ATI Rage 128 SH (unknown)"},
|
||||
{0x1002, 0x534b, 0, "ATI Rage 128 SK (PCI)"},
|
||||
{0x1002, 0x534b, __REALLY_HAVE_SG, "ATI Rage 128 SK (PCI)"},
|
||||
{0x1002, 0x534c, 1, "ATI Rage 128 SL (AGP 2x)"},
|
||||
{0x1002, 0x534d, 1, "ATI Rage 128 SM (AGP 4x)"},
|
||||
{0x1002, 0x534e, 1, "ATI Rage 128 (AGP 4x?)"},
|
||||
|
|
|
|||
|
|
@ -46,21 +46,10 @@
|
|||
static unsigned long DRM(ati_alloc_pcigart_table)( void )
|
||||
{
|
||||
unsigned long address;
|
||||
struct page *page;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||
|
||||
address = __get_free_pages( GFP_KERNEL, ATI_PCIGART_TABLE_ORDER );
|
||||
if ( address == 0UL ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
page = virt_to_page( address );
|
||||
|
||||
for ( i = 0 ; i <= ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
|
||||
atomic_inc( &page->count );
|
||||
SetPageReserved( page );
|
||||
}
|
||||
address = (unsigned long) malloc( (1 << ATI_PCIGART_TABLE_ORDER) * PAGE_SIZE, DRM(M_DRM), M_WAITOK );
|
||||
|
||||
DRM_DEBUG( "%s: returning 0x%08lx\n", __FUNCTION__, address );
|
||||
return address;
|
||||
|
|
@ -68,18 +57,9 @@ static unsigned long DRM(ati_alloc_pcigart_table)( void )
|
|||
|
||||
static void DRM(ati_free_pcigart_table)( unsigned long address )
|
||||
{
|
||||
struct page *page;
|
||||
int i;
|
||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||
|
||||
page = virt_to_page( address );
|
||||
|
||||
for ( i = 0 ; i <= ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
|
||||
atomic_dec( &page->count );
|
||||
ClearPageReserved( page );
|
||||
}
|
||||
|
||||
free_pages( address, ATI_PCIGART_TABLE_ORDER );
|
||||
free( (void *)address, DRM(M_DRM));
|
||||
}
|
||||
|
||||
int DRM(ati_pcigart_init)( drm_device_t *dev,
|
||||
|
|
@ -87,9 +67,8 @@ int DRM(ati_pcigart_init)( drm_device_t *dev,
|
|||
dma_addr_t *bus_addr)
|
||||
{
|
||||
drm_sg_mem_t *entry = dev->sg;
|
||||
unsigned long address = 0;
|
||||
unsigned long pages;
|
||||
u32 *pci_gart, page_base, bus_address = 0;
|
||||
u32 *pci_gart=0, page_base, bus_address = 0;
|
||||
int i, j, ret = 0;
|
||||
|
||||
if ( !entry ) {
|
||||
|
|
@ -97,8 +76,8 @@ int DRM(ati_pcigart_init)( drm_device_t *dev,
|
|||
goto done;
|
||||
}
|
||||
|
||||
address = DRM(ati_alloc_pcigart_table)();
|
||||
if ( !address ) {
|
||||
pci_gart = (u32 *)DRM(ati_alloc_pcigart_table)();
|
||||
if ( !pci_gart ) {
|
||||
DRM_ERROR( "cannot allocate PCI GART page!\n" );
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -108,33 +87,30 @@ int DRM(ati_pcigart_init)( drm_device_t *dev,
|
|||
goto done;
|
||||
}
|
||||
|
||||
bus_address = pci_map_single(dev->pdev, (void *)address,
|
||||
/* FIXME non-vtophys==bustophys-arches */
|
||||
bus_address = vtophys( pci_gart );
|
||||
/*pci_map_single(dev->pdev, (void *)address,
|
||||
ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
|
||||
PCI_DMA_TODEVICE);
|
||||
PCI_DMA_TODEVICE);*/
|
||||
if (bus_address == 0) {
|
||||
DRM_ERROR( "unable to map PCIGART pages!\n" );
|
||||
DRM(ati_free_pcigart_table)( address );
|
||||
address = 0;
|
||||
DRM(ati_free_pcigart_table)( (unsigned long)pci_gart );
|
||||
pci_gart = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
pci_gart = (u32 *)address;
|
||||
|
||||
pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
|
||||
? entry->pages : ATI_MAX_PCIGART_PAGES;
|
||||
|
||||
memset( pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32) );
|
||||
bzero( pci_gart, ATI_MAX_PCIGART_PAGES * sizeof(u32) );
|
||||
|
||||
for ( i = 0 ; i < pages ; i++ ) {
|
||||
/* we need to support large memory configurations */
|
||||
entry->busaddr[i] = pci_map_single(dev->pdev,
|
||||
page_address( entry->pagelist[i] ),
|
||||
PAGE_SIZE,
|
||||
PCI_DMA_TODEVICE);
|
||||
/* FIXME non-vtophys==bustophys-arches */
entry->busaddr[i] = vtophys( entry->handle + (i*PAGE_SIZE) );
|
||||
if (entry->busaddr[i] == 0) {
|
||||
DRM_ERROR( "unable to map PCIGART pages!\n" );
|
||||
DRM(ati_pcigart_cleanup)( dev, address, bus_address );
|
||||
address = 0;
|
||||
DRM(ati_pcigart_cleanup)( dev, (unsigned long)pci_gart, bus_address );
|
||||
pci_gart = 0;
|
||||
bus_address = 0;
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -148,14 +124,10 @@ int DRM(ati_pcigart_init)( drm_device_t *dev,
|
|||
|
||||
ret = 1;
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
asm volatile ( "wbinvd" ::: "memory" );
|
||||
#else
|
||||
mb();
|
||||
#endif
|
||||
DRM_OS_READMEMORYBARRIER;
|
||||
|
||||
done:
|
||||
*addr = address;
|
||||
*addr = (unsigned long)pci_gart;
|
||||
*bus_addr = bus_address;
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -165,8 +137,6 @@ int DRM(ati_pcigart_cleanup)( drm_device_t *dev,
|
|||
dma_addr_t bus_addr)
|
||||
{
|
||||
drm_sg_mem_t *entry = dev->sg;
|
||||
unsigned long pages;
|
||||
int i;
|
||||
|
||||
/* we need to support large memory configurations */
|
||||
if ( !entry ) {
|
||||
|
|
@ -174,21 +144,6 @@ int DRM(ati_pcigart_cleanup)( drm_device_t *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if ( bus_addr ) {
|
||||
pci_unmap_single(dev->pdev, bus_addr,
|
||||
ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
|
||||
? entry->pages : ATI_MAX_PCIGART_PAGES;
|
||||
|
||||
for ( i = 0 ; i < pages ; i++ ) {
|
||||
if ( !entry->busaddr[i] ) break;
|
||||
pci_unmap_single(dev->pdev, entry->busaddr[i],
|
||||
PAGE_SIZE, PCI_DMA_TODEVICE);
|
||||
}
|
||||
}
|
||||
|
||||
if ( addr ) {
|
||||
DRM(ati_free_pcigart_table)( addr );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -374,6 +374,7 @@ typedef struct drm_sg_mem {
|
|||
void *virtual;
|
||||
int pages;
|
||||
struct page **pagelist;
|
||||
dma_addr_t *busaddr;
|
||||
} drm_sg_mem_t;
|
||||
|
||||
typedef struct drm_sigdata {
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ static drm_ioctl_desc_t DRM(ioctls)[] = {
|
|||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { DRM(agp_unbind), 1, 1 },
|
||||
#endif
|
||||
|
||||
#if __REALLY_HAVE_SG
|
||||
#if __HAVE_SG
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { DRM(sg_alloc), 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { DRM(sg_free), 1, 1 },
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ typedef struct drm_chipinfo
|
|||
char *name;
|
||||
} drm_chipinfo_t;
|
||||
|
||||
typedef u_int32_t dma_addr_t;
|
||||
typedef u_int32_t atomic_t;
|
||||
typedef u_int32_t cycles_t;
|
||||
typedef u_int32_t spinlock_t;
|
||||
|
|
|
|||
|
|
@ -27,25 +27,15 @@
|
|||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include <linux/config.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include "drmP.h"
|
||||
|
||||
#define DEBUG_SCATTER 0
|
||||
|
||||
#if __REALLY_HAVE_SG
|
||||
|
||||
void DRM(sg_cleanup)( drm_sg_mem_t *entry )
|
||||
{
|
||||
struct page *page;
|
||||
int i;
|
||||
|
||||
for ( i = 0 ; i < entry->pages ; i++ ) {
|
||||
page = entry->pagelist[i];
|
||||
if ( page )
|
||||
ClearPageReserved( page );
|
||||
}
|
||||
|
||||
vfree( entry->virtual );
|
||||
free( entry->virtual, DRM(M_DRM) );
|
||||
|
||||
DRM(free)( entry->busaddr,
|
||||
entry->pages * sizeof(*entry->busaddr),
|
||||
|
|
@ -58,33 +48,26 @@ void DRM(sg_cleanup)( drm_sg_mem_t *entry )
|
|||
DRM_MEM_SGLISTS );
|
||||
}
|
||||
|
||||
int DRM(sg_alloc)( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int DRM(sg_alloc)( DRM_OS_IOCTL )
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
DRM_OS_DEVICE;
|
||||
drm_scatter_gather_t request;
|
||||
drm_sg_mem_t *entry;
|
||||
unsigned long pages, i, j;
|
||||
pgd_t *pgd;
|
||||
pmd_t *pmd;
|
||||
pte_t *pte;
|
||||
unsigned long pages;
|
||||
|
||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||
|
||||
if ( dev->sg )
|
||||
return -EINVAL;
|
||||
return EINVAL;
|
||||
|
||||
if ( copy_from_user( &request,
|
||||
(drm_scatter_gather_t *)arg,
|
||||
sizeof(request) ) )
|
||||
return -EFAULT;
|
||||
DRM_OS_KRNFROMUSR(request, (drm_scatter_gather_t *)data,
|
||||
sizeof(request) );
|
||||
|
||||
entry = DRM(alloc)( sizeof(*entry), DRM_MEM_SGLISTS );
|
||||
if ( !entry )
|
||||
return -ENOMEM;
|
||||
return ENOMEM;
|
||||
|
||||
memset( entry, 0, sizeof(*entry) );
|
||||
bzero( entry, sizeof(*entry) );
|
||||
|
||||
pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages );
|
||||
|
|
@ -94,10 +77,10 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
|
|||
DRM_MEM_PAGES );
|
||||
if ( !entry->pagelist ) {
|
||||
DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS );
|
||||
return -ENOMEM;
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
|
||||
bzero(entry->pagelist, pages * sizeof(*entry->pagelist));
|
||||
|
||||
entry->busaddr = DRM(alloc)( pages * sizeof(*entry->busaddr),
|
||||
DRM_MEM_PAGES );
|
||||
|
|
@ -108,11 +91,11 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
|
|||
DRM(free)( entry,
|
||||
sizeof(*entry),
|
||||
DRM_MEM_SGLISTS );
|
||||
return -ENOMEM;
|
||||
return ENOMEM;
|
||||
}
|
||||
memset( (void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr) );
|
||||
bzero( (void *)entry->busaddr, pages * sizeof(*entry->busaddr) );
|
||||
|
||||
entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
|
||||
entry->virtual = malloc( pages << PAGE_SHIFT, DRM(M_DRM), M_WAITOK );
|
||||
if ( !entry->virtual ) {
|
||||
DRM(free)( entry->busaddr,
|
||||
entry->pages * sizeof(*entry->busaddr),
|
||||
|
|
@ -123,45 +106,21 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
|
|||
DRM(free)( entry,
|
||||
sizeof(*entry),
|
||||
DRM_MEM_SGLISTS );
|
||||
return -ENOMEM;
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
/* This also forces the mapping of COW pages, so our page list
|
||||
* will be valid. Please don't remove it...
|
||||
*/
|
||||
memset( entry->virtual, 0, pages << PAGE_SHIFT );
|
||||
bzero( entry->virtual, pages << PAGE_SHIFT );
|
||||
|
||||
entry->handle = (unsigned long)entry->virtual;
|
||||
|
||||
DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle );
|
||||
DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
|
||||
|
||||
for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) {
|
||||
pgd = pgd_offset_k( i );
|
||||
if ( !pgd_present( *pgd ) )
|
||||
goto failed;
|
||||
|
||||
pmd = pmd_offset( pgd, i );
|
||||
if ( !pmd_present( *pmd ) )
|
||||
goto failed;
|
||||
|
||||
pte = pte_offset( pmd, i );
|
||||
if ( !pte_present( *pte ) )
|
||||
goto failed;
|
||||
|
||||
entry->pagelist[j] = pte_page( *pte );
|
||||
|
||||
SetPageReserved( entry->pagelist[j] );
|
||||
}
|
||||
|
||||
request.handle = entry->handle;
|
||||
|
||||
if ( copy_to_user( (drm_scatter_gather_t *)arg,
|
||||
&request,
|
||||
sizeof(request) ) ) {
|
||||
DRM(sg_cleanup)( entry );
|
||||
return -EFAULT;
|
||||
}
|
||||
DRM_OS_KRNTOUSR( (drm_scatter_gather_t *)data,
|
||||
request,
|
||||
sizeof(request) );
|
||||
|
||||
dev->sg = entry;
|
||||
|
||||
|
|
@ -207,29 +166,24 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
|
|||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
DRM(sg_cleanup)( entry );
|
||||
return -ENOMEM;
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
int DRM(sg_free)( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int DRM(sg_free)( DRM_OS_IOCTL )
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
DRM_OS_DEVICE;
|
||||
drm_scatter_gather_t request;
|
||||
drm_sg_mem_t *entry;
|
||||
|
||||
if ( copy_from_user( &request,
|
||||
(drm_scatter_gather_t *)arg,
|
||||
sizeof(request) ) )
|
||||
return -EFAULT;
|
||||
DRM_OS_KRNFROMUSR( request, (drm_scatter_gather_t *)data,
|
||||
sizeof(request) );
|
||||
|
||||
entry = dev->sg;
|
||||
dev->sg = NULL;
|
||||
|
||||
if ( !entry || entry->handle != request.handle )
|
||||
return -EINVAL;
|
||||
return EINVAL;
|
||||
|
||||
DRM_DEBUG( "sg free virtual = %p\n", entry->virtual );
|
||||
|
||||
|
|
@ -237,3 +191,16 @@ int DRM(sg_free)( struct inode *inode, struct file *filp,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* __REALLY_HAVE_SG */
|
||||
|
||||
int DRM(sg_alloc)( DRM_OS_IOCTL )
|
||||
{
|
||||
return DRM_OS_ERR(EINVAL);
|
||||
}
|
||||
int DRM(sg_free)( DRM_OS_IOCTL )
|
||||
{
|
||||
return DRM_OS_ERR(EINVAL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -61,39 +61,39 @@ drm_chipinfo_t DRM(devicelist)[] = {
|
|||
{0x1002, 0x4c46, 1, "ATI Rage 128 Mobility LF"},
|
||||
{0x1002, 0x4d46, 1, "ATI Rage 128 Mobility MF (AGP 4x)"},
|
||||
{0x1002, 0x4d4c, 1, "ATI Rage 128 Mobility ML"},
|
||||
{0x1002, 0x5041, 0, "ATI Rage 128 Pro PA (PCI)"},
|
||||
{0x1002, 0x5041, __REALLY_HAVE_SG, "ATI Rage 128 Pro PA (PCI)"},
|
||||
{0x1002, 0x5042, 1, "ATI Rage 128 Pro PB (AGP 2x)"},
|
||||
{0x1002, 0x5043, 1, "ATI Rage 128 Pro PC (AGP 4x)"},
|
||||
{0x1002, 0x5044, 0, "ATI Rage 128 Pro PD (PCI)"},
|
||||
{0x1002, 0x5044, __REALLY_HAVE_SG, "ATI Rage 128 Pro PD (PCI)"},
|
||||
{0x1002, 0x5045, 1, "ATI Rage 128 Pro PE (AGP 2x)"},
|
||||
{0x1002, 0x5046, 1, "ATI Rage 128 Pro PF (AGP 4x)"},
|
||||
{0x1002, 0x5047, 0, "ATI Rage 128 Pro PG (PCI)"},
|
||||
{0x1002, 0x5047, __REALLY_HAVE_SG, "ATI Rage 128 Pro PG (PCI)"},
|
||||
{0x1002, 0x5048, 1, "ATI Rage 128 Pro PH (AGP)"},
|
||||
{0x1002, 0x5049, 1, "ATI Rage 128 Pro PI (AGP)"},
|
||||
{0x1002, 0x504a, 0, "ATI Rage 128 Pro PJ (PCI)"},
|
||||
{0x1002, 0x504a, __REALLY_HAVE_SG, "ATI Rage 128 Pro PJ (PCI)"},
|
||||
{0x1002, 0x504b, 1, "ATI Rage 128 Pro PK (AGP)"},
|
||||
{0x1002, 0x504c, 1, "ATI Rage 128 Pro PL (AGP)"},
|
||||
{0x1002, 0x504d, 0, "ATI Rage 128 Pro PM (PCI)"},
|
||||
{0x1002, 0x504d, __REALLY_HAVE_SG, "ATI Rage 128 Pro PM (PCI)"},
|
||||
{0x1002, 0x504e, 1, "ATI Rage 128 Pro PN (AGP)"},
|
||||
{0x1002, 0x505f, 1, "ATI Rage 128 Pro PO (AGP)"},
|
||||
{0x1002, 0x5050, 0, "ATI Rage 128 Pro PP (PCI)"},
|
||||
{0x1002, 0x5050, __REALLY_HAVE_SG, "ATI Rage 128 Pro PP (PCI)"},
|
||||
{0x1002, 0x5051, 1, "ATI Rage 128 Pro PQ (AGP)"},
|
||||
{0x1002, 0x5052, 1, "ATI Rage 128 Pro PR (AGP)"},
|
||||
{0x1002, 0x5053, 0, "ATI Rage 128 Pro PS (PCI)"},
|
||||
{0x1002, 0x5053, __REALLY_HAVE_SG, "ATI Rage 128 Pro PS (PCI)"},
|
||||
{0x1002, 0x5054, 1, "ATI Rage 128 Pro PT (AGP)"},
|
||||
{0x1002, 0x5055, 1, "ATI Rage 128 Pro PU (AGP)"},
|
||||
{0x1002, 0x5056, 0, "ATI Rage 128 Pro PV (PCI)"},
|
||||
{0x1002, 0x5056, __REALLY_HAVE_SG, "ATI Rage 128 Pro PV (PCI)"},
|
||||
{0x1002, 0x5057, 1, "ATI Rage 128 Pro PW (AGP)"},
|
||||
{0x1002, 0x5058, 1, "ATI Rage 128 Pro PX (AGP)"},
|
||||
{0x1002, 0x5245, 0, "ATI Rage 128 GL (PCI)"},
|
||||
{0x1002, 0x5245, __REALLY_HAVE_SG, "ATI Rage 128 GL (PCI)"},
|
||||
{0x1002, 0x5246, 1, "ATI Rage 128 GL (AGP 2x)"},
|
||||
{0x1002, 0x524b, 0, "ATI Rage 128 VR (PCI)"},
|
||||
{0x1002, 0x524b, __REALLY_HAVE_SG, "ATI Rage 128 VR (PCI)"},
|
||||
{0x1002, 0x524c, 1, "ATI Rage 128 VR (AGP 2x)"},
|
||||
{0x1002, 0x5345, 0, "ATI Rage 128 SE (PCI)"},
|
||||
{0x1002, 0x5345, __REALLY_HAVE_SG, "ATI Rage 128 SE (PCI)"},
|
||||
{0x1002, 0x5346, 1, "ATI Rage 128 SF (AGP 2x)"},
|
||||
{0x1002, 0x5347, 1, "ATI Rage 128 SG (AGP 4x)"},
|
||||
{0x1002, 0x5348, 0, "ATI Rage 128 SH (unknown)"},
|
||||
{0x1002, 0x534b, 0, "ATI Rage 128 SK (PCI)"},
|
||||
{0x1002, 0x534b, __REALLY_HAVE_SG, "ATI Rage 128 SK (PCI)"},
|
||||
{0x1002, 0x534c, 1, "ATI Rage 128 SL (AGP 2x)"},
|
||||
{0x1002, 0x534d, 1, "ATI Rage 128 SM (AGP 4x)"},
|
||||
{0x1002, 0x534e, 1, "ATI Rage 128 (AGP 4x?)"},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue