dma checkin, still need to figure out how to pass TT_FLAGS and do some

testing
This commit is contained in:
Jeff Hartmann 2000-01-13 06:36:12 +00:00
parent 94fcb29e3b
commit 49c8510611
13 changed files with 227 additions and 22 deletions

View file

@ -419,7 +419,7 @@ int drmAddMap(int fd,
return 0;
}
int drmAddBufs(int fd, int count, int size, int flags)
int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags)
{
drm_buf_desc_t request;
@ -747,13 +747,13 @@ int drmDestroyDrawable(int fd, drmDrawable handle)
int drmAgpAcquire(int fd)
{
if (ioctl(fd, DRM_IOCTL_AGP_ACQUIRE)) return -errno;
if (ioctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL)) return -errno;
return 0;
}
int drmAgpRelease(int fd)
{
if (ioctl(fd, DRM_IOCTL_AGP_RELEASE)) return -errno;
if (ioctl(fd, DRM_IOCTL_AGP_RELEASE, NULL)) return -errno;
return 0;
}

View file

@ -386,6 +386,9 @@ typedef struct drm_device_dma {
int page_count;
unsigned long *pagelist;
unsigned long byte_count;
enum {
_DRM_DMA_USE_AGP = 0x01
} flags;
/* DMA support */
drm_buf_t *this_buffer; /* Buffer being sent */
@ -511,6 +514,7 @@ typedef struct drm_device {
drm_agp_head_t *agp;
#endif
unsigned long *ctx_bitmap;
void *SAREAprivate;
} drm_device_t;

View file

@ -381,6 +381,7 @@ int mga_init(void)
mga_takedown(dev);
return retcode;
}
mga_dma_init(dev);
DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
MGA_NAME,
@ -408,6 +409,7 @@ void mga_cleanup(void)
DRM_INFO("Module unloaded\n");
}
drm_ctxbitmap_cleanup(dev);
mga_dma_cleanup(dev);
mga_takedown(dev);
if (dev->agp) {
drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);

View file

@ -176,7 +176,7 @@ int drm_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
if (dev->queue_count) return -EBUSY; /* Not while in use */
alignment = (request.flags & DRM_PAGE_ALIGN) ? PAGE_ALIGN(size) :size;
alignment = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size):size;
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;

View file

@ -159,7 +159,12 @@ typedef enum drm_dma_flags { /* These values *MUST* match xf86drm.h */
/* Flags for DMA buffer request */
_DRM_DMA_WAIT = 0x10, /* Wait for free buffers */
_DRM_DMA_SMALLER_OK = 0x20, /* Smaller-than-requested buffers ok */
_DRM_DMA_LARGER_OK = 0x40 /* Larger-than-requested buffers ok */
_DRM_DMA_LARGER_OK = 0x40, /* Larger-than-requested buffers ok */
/* Specially for MGA, but not limited to use by it */
_DRM_DMA_VERTEX = 0x01000000,
_DRM_DMA_SETUP = 0x02000000,
_DRM_DMA_BLIT = 0x04000000
} drm_dma_flags_t;
typedef struct drm_buf_desc {
@ -168,8 +173,11 @@ typedef struct drm_buf_desc {
int low_mark; /* Low water mark */
int high_mark; /* High water mark */
enum {
DRM_PAGE_ALIGN = 0x01 /* Align on page boundaries for DMA */
_DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA */
_DRM_AGP_BUFFER = 0x02 /* Buffer is in agp space */
} flags;
unsigned long agp_start; /* Start address of where the agp buffers
* are in the agp aperture */
} drm_buf_desc_t;
typedef struct drm_buf_info {

View file

@ -386,6 +386,9 @@ typedef struct drm_device_dma {
int page_count;
unsigned long *pagelist;
unsigned long byte_count;
enum {
_DRM_DMA_USE_AGP = 0x01
} flags;
/* DMA support */
drm_buf_t *this_buffer; /* Buffer being sent */
@ -511,6 +514,7 @@ typedef struct drm_device {
drm_agp_head_t *agp;
#endif
unsigned long *ctx_bitmap;
void *SAREAprivate;
} drm_device_t;

View file

@ -72,7 +72,7 @@ int i810_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
if (dev->queue_count) return -EBUSY; /* Not while in use */
alignment = (request.flags & DRM_PAGE_ALIGN) ? PAGE_ALIGN(size) :size;
alignment = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size) :size;
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;

View file

@ -34,10 +34,132 @@
#include "drmP.h"
#include "linux/un.h"
int mga_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
int mga_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_device_dma_t *dma = dev->dma;
drm_buf_desc_t request;
drm_buf_entry_t *entry;
drm_buf_t *buf;
unsigned long offset;
unsigned long agp_offset;
int count;
int order;
int size;
int alignment;
int page_order;
int total;
int byte_count;
if (!dma) return -EINVAL;
copy_from_user_ret(&request,
(drm_buf_desc_t *)arg,
sizeof(request),
-EFAULT);
count = request.count;
order = drm_order(request.size);
size = 1 << order;
agp_offset = request.agp_start;
alignment = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size) :size;
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;
byte_count = 0;
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
if (dev->queue_count) return -EBUSY; /* Not while in use */
spin_lock(&dev->count_lock);
if (dev->buf_use) {
spin_unlock(&dev->count_lock);
return -EBUSY;
}
atomic_inc(&dev->buf_alloc);
spin_unlock(&dev->count_lock);
down(&dev->struct_sem);
entry = &dma->bufs[order];
if (entry->buf_count) {
up(&dev->struct_sem);
atomic_dec(&dev->buf_alloc);
return -ENOMEM; /* May only call once for each order */
}
entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
DRM_MEM_BUFS);
if (!entry->buflist) {
up(&dev->struct_sem);
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
memset(entry->buflist, 0, count * sizeof(*entry->buflist));
entry->buf_size = size;
entry->page_order = page_order;
while(entry->buf_count < count) {
for(offset = 0; offset + size <= total && entry->buf_count < count;
offset += alignment, ++entry->buf_count) {
buf = &entry->buflist[entry->buf_count];
buf->idx = dma->buf_count + entry->buf_count;
buf->total = alignment;
buf->order = order;
buf->used = 0;
buf->offset = agp_offset - dev->agp->base + offset;/* ?? */
buf->bus_address = agp_offset + offset;
buf->next = NULL;
buf->waiting = 0;
buf->pending = 0;
init_waitqueue_head(&buf->dma_wait);
buf->pid = 0;
#if DRM_DMA_HISTOGRAM
buf->time_queued = 0;
buf->time_dispatched = 0;
buf->time_completed = 0;
buf->time_freed = 0;
#endif
DRM_DEBUG("buffer %d @ %p\n",
entry->buf_count, buf->address);
}
byte_count += PAGE_SIZE << page_order;
}
dma->buflist = drm_realloc(dma->buflist,
dma->buf_count * sizeof(*dma->buflist),
(dma->buf_count + entry->buf_count)
* sizeof(*dma->buflist),
DRM_MEM_BUFS);
for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
dma->buflist[i] = &entry->buflist[i - dma->buf_count];
dma->buf_count += entry->buf_count;
dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
drm_freelist_create(&entry->freelist, entry->buf_count);
for (i = 0; i < entry->buf_count; i++) {
drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
}
up(&dev->struct_sem);
request.count = entry->buf_count;
request.size = size;
copy_to_user_ret((drm_buf_desc_t *)arg,
&request,
sizeof(request),
-EFAULT);
atomic_dec(&dev->buf_alloc);
return 0;
}
int mga_addbufs_pci(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_device_dma_t *dma = dev->dma;
drm_buf_desc_t request;
@ -72,7 +194,7 @@ int mga_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
if (dev->queue_count) return -EBUSY; /* Not while in use */
alignment = (request.flags & DRM_PAGE_ALIGN) ? PAGE_ALIGN(size) :size;
alignment = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size) :size;
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;
@ -195,6 +317,22 @@ int mga_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
return 0;
}
int mga_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_buf_desc_t request;
copy_from_user_ret(&request,
(drm_buf_desc_t *)arg,
sizeof(request),
-EFAULT);
if(request.flags & _DRM_AGP_BUFFER)
return mga_addbufs_agp(inode, filp, cmd, arg);
else
return mga_addbufs_pci(inode, filp, cmd, arg);
}
int mga_infobufs(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
@ -377,8 +515,25 @@ int mga_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
-EFAULT);
if (request.count >= dma->buf_count) {
virtual = do_mmap(filp, 0, dma->byte_count,
PROT_READ|PROT_WRITE, MAP_SHARED, 0);
if(dma->flags & _DRM_DMA_USE_AGP) {
/* This is an ugly vicious hack */
drm_map_t *map = NULL;
for(i = 0; i < dev->map_count; i++) {
map = dev->maplist[i];
if(map->type == _DRM_AGP) break;
}
if (i >= dev->map_count || !map) {
retcode = -EINVAL;
goto done;
}
virtual = do_mmap(filp, 0, map->size, PROT_READ|PROT_WRITE,
MAP_SHARED, map->handle);
}
else {
virtual = do_mmap(filp, 0, dma->byte_count,
PROT_READ|PROT_WRITE, MAP_SHARED, 0);
}
if (virtual > -1024UL) {
/* Real error */
retcode = (signed long)virtual;

View file

@ -104,6 +104,7 @@ void mga_dma_init(drm_device_t *dev)
buffer.max_dwords = 16384;
buffer.num_dwords = 16384;
buffer.first_time = 1;
MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG);
}
void mga_dma_cleanup(drm_device_t *dev)
@ -120,25 +121,26 @@ static inline void mga_prim_overflow(drm_device_t *dev)
}
static inline void mga_dma_dispatch(drm_device_t *dev, unsigned long address,
unsigned long length)
unsigned long length,
transferType_t transferType)
{
transferType_t transferType = TT_GENERAL;
int use_agp = PDEA_pagpxfer_enable;
static int softrap = 1;
CHECK_OVERFLOW(10);
DMAOUTREG(MGAREG_DWGSYNC, 0); /* For debugging */
DMAOUTREG(MGAREG_DMAPAD, 0);
DMAOUTREG(MGAREG_DMAPAD, 0);
DMAOUTREG(MGAREG_SECADDRESS, address | transferType);
DMAOUTREG(MGAREG_SECEND, (address + length) | use_agp);
DMAOUTREG(MGAREG_DMAPAD, 0);
DMAOUTREG(MGAREG_DMAPAD, 0);
#if 0
#if 1
DMAOUTREG(MGAREG_DWGSYNC, MGA_SYNC_TAG); /* For debugging */
#else
DMAOUTREG(MGAREG_DMAPAD, 0);
#endif
DMAOUTREG(MGAREG_SOFTRAP, softrap);
MGA_WRITE(MGAREG_DWGSYNC, 0);
MGA_WRITE(MGAREG_PRIMEND, (buffer.phys_head + buffer.num_dwords) |
use_agp);
buffer.last_softrap = softrap;
@ -146,21 +148,26 @@ static inline void mga_dma_dispatch(drm_device_t *dev, unsigned long address,
static inline void mga_dma_quiescent(drm_device_t *dev)
{
#if 0
while(MGA_READ(MGAREG_SECADDRESS) != buffer.last_softrap)
;
MGA_WRITE(MGAREG_DWGSYNC, MGA_SYNC_TAG);
#endif
while(MGA_READ(MGAREG_DWGSYNC) != MGA_SYNC_TAG)
;
}
static inline void mga_dma_ready(drm_device_t *dev)
{
#if 0
while(MGA_READ(MGAREG_SECADDRESS) != buffer.last_softrap)
;
#endif
mga_dma_quiescent(dev);
}
static inline int mga_dma_is_ready(drm_device_t *dev)
{
#if 0
/* Need a better way of doing this */
if(buffer.first_time == 1) {
buffer.first_time = 0;
@ -171,6 +178,9 @@ static inline int mga_dma_is_ready(drm_device_t *dev)
return 1;
else
return 0;
#endif
mga_dma_quiescent(dev);
return 1;
}

View file

@ -381,6 +381,7 @@ int mga_init(void)
mga_takedown(dev);
return retcode;
}
mga_dma_init(dev);
DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
MGA_NAME,
@ -408,6 +409,7 @@ void mga_cleanup(void)
DRM_INFO("Module unloaded\n");
}
drm_ctxbitmap_cleanup(dev);
mga_dma_cleanup(dev);
mga_takedown(dev);
if (dev->agp) {
drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);

View file

@ -54,6 +54,8 @@ extern int mga_control(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int mga_lock(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern void mga_dma_init(drm_device_t *dev);
extern void mga_dma_cleanup(drm_device_t *dev);
/* mga_bufs.c */
@ -67,6 +69,8 @@ extern int mga_freebufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int mga_mapbufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int mga_addmap(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);

View file

@ -159,7 +159,12 @@ typedef enum drm_dma_flags { /* These values *MUST* match xf86drm.h */
/* Flags for DMA buffer request */
_DRM_DMA_WAIT = 0x10, /* Wait for free buffers */
_DRM_DMA_SMALLER_OK = 0x20, /* Smaller-than-requested buffers ok */
_DRM_DMA_LARGER_OK = 0x40 /* Larger-than-requested buffers ok */
_DRM_DMA_LARGER_OK = 0x40, /* Larger-than-requested buffers ok */
/* Specially for MGA, but not limited to use by it */
_DRM_DMA_VERTEX = 0x01000000,
_DRM_DMA_SETUP = 0x02000000,
_DRM_DMA_BLIT = 0x04000000
} drm_dma_flags_t;
typedef struct drm_buf_desc {
@ -168,8 +173,11 @@ typedef struct drm_buf_desc {
int low_mark; /* Low water mark */
int high_mark; /* High water mark */
enum {
DRM_PAGE_ALIGN = 0x01 /* Align on page boundaries for DMA */
_DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA */
_DRM_AGP_BUFFER = 0x02 /* Buffer is in agp space */
} flags;
unsigned long agp_start; /* Start address of where the agp buffers
* are in the agp aperture */
} drm_buf_desc_t;
typedef struct drm_buf_info {

View file

@ -159,7 +159,12 @@ typedef enum drm_dma_flags { /* These values *MUST* match xf86drm.h */
/* Flags for DMA buffer request */
_DRM_DMA_WAIT = 0x10, /* Wait for free buffers */
_DRM_DMA_SMALLER_OK = 0x20, /* Smaller-than-requested buffers ok */
_DRM_DMA_LARGER_OK = 0x40 /* Larger-than-requested buffers ok */
_DRM_DMA_LARGER_OK = 0x40, /* Larger-than-requested buffers ok */
/* Specially for MGA, but not limited to use by it */
_DRM_DMA_VERTEX = 0x01000000,
_DRM_DMA_SETUP = 0x02000000,
_DRM_DMA_BLIT = 0x04000000
} drm_dma_flags_t;
typedef struct drm_buf_desc {
@ -168,8 +173,11 @@ typedef struct drm_buf_desc {
int low_mark; /* Low water mark */
int high_mark; /* High water mark */
enum {
DRM_PAGE_ALIGN = 0x01 /* Align on page boundaries for DMA */
_DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA */
_DRM_AGP_BUFFER = 0x02 /* Buffer is in agp space */
} flags;
unsigned long agp_start; /* Start address of where the agp buffers
* are in the agp aperture */
} drm_buf_desc_t;
typedef struct drm_buf_info {