summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Hartmann <jhartmann@valinux.com>2000-01-13 06:36:12 +0000
committerJeff Hartmann <jhartmann@valinux.com>2000-01-13 06:36:12 +0000
commit49c8510611af16b5fbd313d7f0fdcb06a9315629 (patch)
tree7120e2afa49d66cf2c63eba51992b7e8125b007b
parent94fcb29e3b96cb750b674463a3c1d224086024b1 (diff)
dma checkin, still need to figure out how to pass TT_FLAGS and do some
testing
-rw-r--r--libdrm/xf86drm.c6
-rw-r--r--linux-core/drmP.h4
-rw-r--r--linux-core/mga_drv.c2
-rw-r--r--linux/bufs.c2
-rw-r--r--linux/drm.h12
-rw-r--r--linux/drmP.h4
-rw-r--r--linux/i810_bufs.c2
-rw-r--r--linux/mga_bufs.c167
-rw-r--r--linux/mga_dma.c20
-rw-r--r--linux/mga_drv.c2
-rw-r--r--linux/mga_drv.h4
-rw-r--r--shared-core/drm.h12
-rw-r--r--shared/drm.h12
13 files changed, 227 insertions, 22 deletions
diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c
index 51a53a2a..9ce98410 100644
--- a/libdrm/xf86drm.c
+++ b/libdrm/xf86drm.c
@@ -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;
}
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 4bd2f690..74516821 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -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;
diff --git a/linux-core/mga_drv.c b/linux-core/mga_drv.c
index b703db9a..f7c636a2 100644
--- a/linux-core/mga_drv.c
+++ b/linux-core/mga_drv.c
@@ -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);
diff --git a/linux/bufs.c b/linux/bufs.c
index 975c8890..c016734c 100644
--- a/linux/bufs.c
+++ b/linux/bufs.c
@@ -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;
diff --git a/linux/drm.h b/linux/drm.h
index 37562c4e..a26cacbb 100644
--- a/linux/drm.h
+++ b/linux/drm.h
@@ -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 {
diff --git a/linux/drmP.h b/linux/drmP.h
index 4bd2f690..74516821 100644
--- a/linux/drmP.h
+++ b/linux/drmP.h
@@ -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;
diff --git a/linux/i810_bufs.c b/linux/i810_bufs.c
index 1266868c..10a65f82 100644
--- a/linux/i810_bufs.c
+++ b/linux/i810_bufs.c
@@ -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;
diff --git a/linux/mga_bufs.c b/linux/mga_bufs.c
index 0e9e22f8..40fe4beb 100644
--- a/linux/mga_bufs.c
+++ b/linux/mga_bufs.c
@@ -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;
diff --git a/linux/mga_dma.c b/linux/mga_dma.c
index 8c7e6adc..4fa8cd16 100644
--- a/linux/mga_dma.c
+++ b/linux/mga_dma.c
@@ -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;
}
diff --git a/linux/mga_drv.c b/linux/mga_drv.c
index b703db9a..f7c636a2 100644
--- a/linux/mga_drv.c
+++ b/linux/mga_drv.c
@@ -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);
diff --git a/linux/mga_drv.h b/linux/mga_drv.h
index 2ad86204..f29fa5e2 100644
--- a/linux/mga_drv.h
+++ b/linux/mga_drv.h
@@ -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);
diff --git a/shared-core/drm.h b/shared-core/drm.h
index 37562c4e..a26cacbb 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -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 {
diff --git a/shared/drm.h b/shared/drm.h
index 37562c4e..a26cacbb 100644
--- a/shared/drm.h
+++ b/shared/drm.h
@@ -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 {