diff options
author | Jeff Hartmann <jhartmann@valinux.com> | 2000-01-13 06:36:12 +0000 |
---|---|---|
committer | Jeff Hartmann <jhartmann@valinux.com> | 2000-01-13 06:36:12 +0000 |
commit | 49c8510611af16b5fbd313d7f0fdcb06a9315629 (patch) | |
tree | 7120e2afa49d66cf2c63eba51992b7e8125b007b | |
parent | 94fcb29e3b96cb750b674463a3c1d224086024b1 (diff) |
dma checkin, still need to figure out how to pass TT_FLAGS and do some
testing
-rw-r--r-- | libdrm/xf86drm.c | 6 | ||||
-rw-r--r-- | linux-core/drmP.h | 4 | ||||
-rw-r--r-- | linux-core/mga_drv.c | 2 | ||||
-rw-r--r-- | linux/bufs.c | 2 | ||||
-rw-r--r-- | linux/drm.h | 12 | ||||
-rw-r--r-- | linux/drmP.h | 4 | ||||
-rw-r--r-- | linux/i810_bufs.c | 2 | ||||
-rw-r--r-- | linux/mga_bufs.c | 167 | ||||
-rw-r--r-- | linux/mga_dma.c | 20 | ||||
-rw-r--r-- | linux/mga_drv.c | 2 | ||||
-rw-r--r-- | linux/mga_drv.h | 4 | ||||
-rw-r--r-- | shared-core/drm.h | 12 | ||||
-rw-r--r-- | shared/drm.h | 12 |
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 { |