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:
Eric Anholt 2002-05-31 03:44:52 +00:00
parent e19e0e4148
commit 76b60581df
12 changed files with 146 additions and 298 deletions

View file

@ -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 );
}

View file

@ -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 {

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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?)"},

View file

@ -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 );
}

View file

@ -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 {

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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?)"},