mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-05-07 19:18:04 +02:00
Working dma solution (has texture errors)
This commit is contained in:
parent
27526cad35
commit
d1cb058afa
10 changed files with 918 additions and 489 deletions
|
|
@ -25,6 +25,7 @@
|
|||
*
|
||||
* Authors: Rickard E. (Rik) Faith <faith@precisioninsight.com>
|
||||
* Jeff Hartmann <jhartmann@precisioninsight.com>
|
||||
* Keith Whitwell <keithw@precisioninsight.com>
|
||||
*
|
||||
* $XFree86$
|
||||
*
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
#include "drmP.h"
|
||||
#include "i810_drm_public.h"
|
||||
#include "i810_drv.h"
|
||||
#include "i810_dma.h"
|
||||
|
||||
#include <linux/interrupt.h> /* For task queue support */
|
||||
#include <linux/time.h> /* For do_gettimeofday */
|
||||
|
|
@ -49,24 +51,31 @@
|
|||
#define I810_READ16(reg) I810_DEREF16(reg)
|
||||
#define I810_WRITE16(reg,val) do { I810_DEREF16(reg) = val; } while (0)
|
||||
|
||||
#define RING_LOCALS() unsigned int outring, ringmask; volatile char *virt;
|
||||
#define BEGIN_LP_RING(n) \
|
||||
if (dev_priv->ring.space < n*4) i810_wait_ring(dev, n*4, 0); \
|
||||
dev_priv->ring.space -= n*4; \
|
||||
outring = dev_priv->ring.tail; \
|
||||
ringmask = dev_priv->ring.tail_mask; \
|
||||
virt = dev_priv->ring.virtual_start;
|
||||
#define RING_LOCALS unsigned int outring, ringmask; volatile char *virt;
|
||||
|
||||
#define ADVANCE_LP_RING() { \
|
||||
dev_priv->ring.tail = outring; \
|
||||
I810_WRITE(LP_RING + RING_TAIL, outring); \
|
||||
}
|
||||
|
||||
#define OUT_RING(n) { \
|
||||
*(volatile unsigned int *)(virt + outring) = n; \
|
||||
outring += 4; \
|
||||
outring &= ringmask; \
|
||||
}
|
||||
#define BEGIN_LP_RING(n) do { \
|
||||
if (I810_VERBOSE) \
|
||||
printk("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__); \
|
||||
if (dev_priv->ring.space < n*4) i810_wait_ring(dev, n*4, 0); \
|
||||
dev_priv->ring.space -= n*4; \
|
||||
outring = dev_priv->ring.tail; \
|
||||
ringmask = dev_priv->ring.tail_mask; \
|
||||
virt = dev_priv->ring.virtual_start; \
|
||||
} while (0)
|
||||
|
||||
#define ADVANCE_LP_RING() do { \
|
||||
if (I810_VERBOSE) printk("ADVANCE_LP_RING\n"); \
|
||||
dev_priv->ring.tail = outring; \
|
||||
I810_WRITE(LP_RING + RING_TAIL, outring); \
|
||||
} while(0)
|
||||
|
||||
#define OUT_RING(n) do { \
|
||||
if (I810_VERBOSE) printk(" OUT_RING %x\n", (int)(n)); \
|
||||
*(volatile unsigned int *)(virt + outring) = n; \
|
||||
outring += 4; \
|
||||
outring &= ringmask; \
|
||||
} while (0);
|
||||
|
||||
static unsigned long i810_alloc_page(drm_device_t *dev)
|
||||
{
|
||||
|
|
@ -101,28 +110,28 @@ static int i810_alloc_kernel_queue(drm_device_t *dev)
|
|||
down(&dev->struct_sem);
|
||||
|
||||
if(dev->queue_count != 0) {
|
||||
/* Reseting the kernel context here is not
|
||||
* a race, since it can only happen when that
|
||||
* queue is empty.
|
||||
*/
|
||||
queue = dev->queuelist[DRM_KERNEL_CONTEXT];
|
||||
printk("Kernel queue already allocated\n");
|
||||
/* Reseting the kernel context here is not
|
||||
* a race, since it can only happen when that
|
||||
* queue is empty.
|
||||
*/
|
||||
queue = dev->queuelist[DRM_KERNEL_CONTEXT];
|
||||
printk("Kernel queue already allocated\n");
|
||||
} else {
|
||||
queue = drm_alloc(sizeof(*queue), DRM_MEM_QUEUES);
|
||||
if(!queue) {
|
||||
up(&dev->struct_sem);
|
||||
printk("out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
++dev->queue_count;
|
||||
dev->queuelist = drm_alloc(sizeof(*dev->queuelist),
|
||||
DRM_MEM_QUEUES);
|
||||
if(!dev->queuelist) {
|
||||
up(&dev->struct_sem);
|
||||
drm_free(queue, sizeof(*queue), DRM_MEM_QUEUES);
|
||||
printk("out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
queue = drm_alloc(sizeof(*queue), DRM_MEM_QUEUES);
|
||||
if(!queue) {
|
||||
up(&dev->struct_sem);
|
||||
printk("out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
++dev->queue_count;
|
||||
dev->queuelist = drm_alloc(sizeof(*dev->queuelist),
|
||||
DRM_MEM_QUEUES);
|
||||
if(!dev->queuelist) {
|
||||
up(&dev->struct_sem);
|
||||
drm_free(queue, sizeof(*queue), DRM_MEM_QUEUES);
|
||||
printk("out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
memset(queue, 0, sizeof(*queue));
|
||||
|
|
@ -154,7 +163,7 @@ static int i810_alloc_kernel_queue(drm_device_t *dev)
|
|||
|
||||
static int i810_dma_cleanup(drm_device_t *dev)
|
||||
{
|
||||
DRM_DEBUG("i810_dma_cleanup\n");
|
||||
printk("i810_dma_cleanup\n");
|
||||
|
||||
if(dev->dev_private) {
|
||||
drm_i810_private_t *dev_priv =
|
||||
|
|
@ -178,8 +187,7 @@ static int i810_dma_cleanup(drm_device_t *dev)
|
|||
|
||||
static int __gettimeinmillis(void)
|
||||
{
|
||||
struct timeval timep;
|
||||
|
||||
struct timeval timep;
|
||||
do_gettimeofday(&timep);
|
||||
return(timep.tv_sec * 1000) + (timep.tv_usec / 1000);
|
||||
}
|
||||
|
|
@ -187,14 +195,14 @@ static int __gettimeinmillis(void)
|
|||
static int i810_wait_ring(drm_device_t *dev, int n, int timeout_millis)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
drm_i810_ring_buffer *ring = &(dev_priv->ring);
|
||||
drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
|
||||
int iters = 0;
|
||||
int startTime = 0;
|
||||
int curTime = 0;
|
||||
|
||||
if (timeout_millis == 0) timeout_millis = 3000;
|
||||
|
||||
DRM_DEBUG( "i810_wait_ring %d\n", n);
|
||||
printk( "i810_wait_ring %d\n", n);
|
||||
|
||||
while (ring->space < n) {
|
||||
int i;
|
||||
|
|
@ -211,8 +219,9 @@ static int i810_wait_ring(drm_device_t *dev, int n, int timeout_millis)
|
|||
} else if (curTime - startTime > timeout_millis) {
|
||||
DRM_ERROR("space: %d wanted %d\n", ring->space, n);
|
||||
DRM_ERROR("lockup\n");
|
||||
schedule(); /* JEFF - what to do here ??? */
|
||||
}
|
||||
|
||||
|
||||
for (i = 0 ; i < 2000 ; i++) ;
|
||||
}
|
||||
|
||||
|
|
@ -222,9 +231,9 @@ static int i810_wait_ring(drm_device_t *dev, int n, int timeout_millis)
|
|||
static void i810_kernel_lost_context(drm_device_t *dev)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
drm_i810_ring_buffer *ring = &(dev_priv->ring);
|
||||
drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
|
||||
|
||||
DRM_DEBUG("i810_kernel_lost_context, old ring (%x,%x)\n",
|
||||
printk("i810_kernel_lost_context, old ring (%x,%x)\n",
|
||||
ring->head, ring->tail);
|
||||
|
||||
ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
|
||||
|
|
@ -232,49 +241,26 @@ static void i810_kernel_lost_context(drm_device_t *dev)
|
|||
ring->space = ring->head - (ring->tail+8);
|
||||
if (ring->space < 0) ring->space += ring->Size;
|
||||
|
||||
DRM_DEBUG("new ring (%x,%x)\n", ring->head, ring->tail);
|
||||
printk("new ring (%x,%x)\n", ring->head, ring->tail);
|
||||
}
|
||||
|
||||
static inline void i810_ring_write_status(drm_device_t *dev)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
RING_LOCALS();
|
||||
RING_LOCALS;
|
||||
|
||||
i810_kernel_lost_context(dev);
|
||||
dev_priv->counter++;
|
||||
#if 1
|
||||
BEGIN_LP_RING(8);
|
||||
#else
|
||||
BEGIN_LP_RING(16);
|
||||
#endif
|
||||
|
||||
BEGIN_LP_RING(6);
|
||||
OUT_RING(CMD_REPORT_HEAD);
|
||||
OUT_RING(0);
|
||||
#if 1
|
||||
OUT_RING(CMD_STORE_DWORD_IDX);
|
||||
OUT_RING(5 * sizeof(unsigned long));
|
||||
OUT_RING(dev_priv->counter);
|
||||
OUT_RING(0);
|
||||
|
||||
#endif
|
||||
/* Add a breakpoint interrupt at the end */
|
||||
#if 1
|
||||
OUT_RING(0);
|
||||
OUT_RING(GFX_OP_BREAKPOINT_INTERRUPT);
|
||||
#endif
|
||||
/* Add a blit here just to see if my commands work */
|
||||
#if 0
|
||||
OUT_RING(0x02000000);
|
||||
OUT_RING(0);
|
||||
OUT_RING(0x50c00004);
|
||||
OUT_RING(0xcc0800);
|
||||
OUT_RING(0x1900320);
|
||||
OUT_RING(0);
|
||||
OUT_RING(0x800);
|
||||
OUT_RING(0xb80000);
|
||||
OUT_RING(0x02000000);
|
||||
OUT_RING(0);
|
||||
#endif
|
||||
OUT_RING(0);
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
/* Wait for ring to complete */
|
||||
i810_wait_ring(dev, dev_priv->ring.Size - 8, 0);
|
||||
}
|
||||
|
|
@ -284,35 +270,42 @@ static inline void i810_print_status_page(drm_device_t *dev)
|
|||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
u32 *temp = (u32 *)dev_priv->hw_status_page;
|
||||
|
||||
DRM_DEBUG( "hw_status: Interrupt Status : %lx\n", temp[0]);
|
||||
DRM_DEBUG( "hw_status: LpRing Head ptr : %lx\n", temp[1]);
|
||||
DRM_DEBUG( "hw_status: IRing Head ptr : %lx\n", temp[2]);
|
||||
DRM_DEBUG( "hw_status: Reserved : %lx\n", temp[3]);
|
||||
DRM_DEBUG( "hw_status: Driver Counter : %d\n", temp[5]);
|
||||
printk( "hw_status: Interrupt Status : %x\n", temp[0]);
|
||||
printk( "hw_status: LpRing Head ptr : %x\n", temp[1]);
|
||||
printk( "hw_status: IRing Head ptr : %x\n", temp[2]);
|
||||
printk( "hw_status: Reserved : %x\n", temp[3]);
|
||||
printk( "hw_status: Driver Counter : %d\n", temp[5]);
|
||||
}
|
||||
|
||||
static int i810_dma_initialize(drm_device_t *dev,
|
||||
drm_i810_private_t *dev_priv,
|
||||
drm_i810_init_t *init)
|
||||
{
|
||||
DRM_DEBUG( "i810_dma_init\n");
|
||||
drm_map_t *sarea_map;
|
||||
|
||||
printk( "i810_dma_init\n");
|
||||
dev->dev_private = (void *) dev_priv;
|
||||
memset(dev_priv, 0, sizeof(drm_i810_private_t));
|
||||
if((init->ring_map_idx >= dev->map_count) ||
|
||||
(init->buffer_map_idx >= dev->map_count)) {
|
||||
|
||||
if (init->ring_map_idx >= dev->map_count ||
|
||||
init->buffer_map_idx >= dev->map_count) {
|
||||
i810_dma_cleanup(dev);
|
||||
DRM_ERROR("ring_map or buffer_map are invalid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if(i810_alloc_kernel_queue(dev) != DRM_KERNEL_CONTEXT) {
|
||||
i810_dma_cleanup(dev);
|
||||
DRM_ERROR("Kernel context queue not present\n");
|
||||
return -ENOMEM;
|
||||
if (i810_alloc_kernel_queue(dev) != DRM_KERNEL_CONTEXT) {
|
||||
i810_dma_cleanup(dev);
|
||||
DRM_ERROR("Kernel context queue not present\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dev_priv->ring_map_idx = init->ring_map_idx;
|
||||
dev_priv->buffer_map_idx = init->buffer_map_idx;
|
||||
sarea_map = dev->maplist[0];
|
||||
dev_priv->sarea_priv = (drm_i810_sarea_t *)
|
||||
((u8 *)sarea_map->handle +
|
||||
init->sarea_priv_offset);
|
||||
|
||||
atomic_set(&dev_priv->pending_bufs, 0);
|
||||
atomic_set(&dev_priv->dispatch_lock, 0);
|
||||
|
|
@ -326,7 +319,7 @@ static int i810_dma_initialize(drm_device_t *dev,
|
|||
init->ring_size);
|
||||
dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
|
||||
|
||||
if(dev_priv->ring.virtual_start == NULL) {
|
||||
if (dev_priv->ring.virtual_start == NULL) {
|
||||
i810_dma_cleanup(dev);
|
||||
DRM_ERROR("can not ioremap virtual address for"
|
||||
" ring buffer\n");
|
||||
|
|
@ -337,20 +330,20 @@ static int i810_dma_initialize(drm_device_t *dev,
|
|||
dev_priv->hw_status_page = i810_alloc_page(dev);
|
||||
memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE);
|
||||
if(dev_priv->hw_status_page == 0UL) {
|
||||
i810_dma_cleanup(dev);
|
||||
DRM_ERROR("Can not allocate hardware status page\n");
|
||||
return -ENOMEM;
|
||||
i810_dma_cleanup(dev);
|
||||
DRM_ERROR("Can not allocate hardware status page\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page);
|
||||
printk("hw status page @ %lx\n", dev_priv->hw_status_page);
|
||||
|
||||
I810_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page));
|
||||
DRM_DEBUG("Enabled hardware status page\n");
|
||||
printk("Enabled hardware status page\n");
|
||||
#if 0
|
||||
DRM_DEBUG("Doing first ring buffer write\n");
|
||||
printk("Doing first ring buffer write\n");
|
||||
i810_ring_write_status(dev);
|
||||
DRM_DEBUG("First ring write succeeded\n");
|
||||
printk("First ring write succeeded\n");
|
||||
i810_print_status_page(dev);
|
||||
DRM_DEBUG("Status page dump succeeded\n");
|
||||
printk("Status page dump succeeded\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -385,48 +378,106 @@ int i810_dma_init(struct inode *inode, struct file *filp,
|
|||
return retcode;
|
||||
}
|
||||
|
||||
static inline void i810_dma_dispatch(drm_device_t *dev, unsigned long address,
|
||||
unsigned long length)
|
||||
static void i810_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
unsigned long address = (unsigned long)buf->bus_address;
|
||||
unsigned long start = address - dev->agp->base;
|
||||
RING_LOCALS();
|
||||
int length = buf->used;
|
||||
RING_LOCALS;
|
||||
|
||||
dev_priv->counter++;
|
||||
DRM_DEBUG( "dispatch counter : %d\n", dev_priv->counter);
|
||||
DRM_DEBUG( "i810_dma_dispatch\n");
|
||||
DRM_DEBUG( "start : %lx\n", start);
|
||||
DRM_DEBUG( "length : %d\n", length);
|
||||
DRM_DEBUG( "start + length - 4 : %d\n", start + length - 4);
|
||||
printk( "dispatch counter : %ld\n", dev_priv->counter);
|
||||
printk( "i810_dma_dispatch\n");
|
||||
printk( "start : 0x%lx\n", start);
|
||||
printk( "length : 0x%x\n", length);
|
||||
printk( "start + length - 4 : 0x%lx\n", start + length - 4);
|
||||
i810_kernel_lost_context(dev);
|
||||
|
||||
|
||||
BEGIN_LP_RING(8);
|
||||
OUT_RING(CMD_OP_BATCH_BUFFER);
|
||||
OUT_RING(start | BB1_PROTECTED);
|
||||
OUT_RING((start + length) - 4);
|
||||
OUT_RING(CMD_STORE_DWORD_IDX);
|
||||
OUT_RING(5 * sizeof(unsigned long));
|
||||
OUT_RING(dev_priv->counter);
|
||||
/* Add a breakpoint interrupt at the end */
|
||||
OUT_RING(CMD_REPORT_HEAD);
|
||||
OUT_RING(GFX_OP_BREAKPOINT_INTERRUPT);
|
||||
OUT_RING( CMD_OP_BATCH_BUFFER );
|
||||
OUT_RING( start | BB1_PROTECTED );
|
||||
OUT_RING( start + length - 4 );
|
||||
OUT_RING( CMD_STORE_DWORD_IDX );
|
||||
OUT_RING( 20 );
|
||||
OUT_RING( dev_priv->counter );
|
||||
OUT_RING( CMD_REPORT_HEAD );
|
||||
OUT_RING( GFX_OP_BREAKPOINT_INTERRUPT );
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
/* Wait for ring to flush */
|
||||
#if 0
|
||||
i810_wait_ring(dev, dev_priv->ring.Size - 8, 0);
|
||||
i810_ring_write_status(dev);
|
||||
DRM_DEBUG("ring write succeeded\n");
|
||||
i810_print_status_page(dev);
|
||||
DRM_DEBUG("Status page dump succeeded\n");
|
||||
#endif
|
||||
i810_print_status_page(dev);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void i810_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
|
||||
drm_buf_t *real_buf = dev->dma->buflist[ buf_priv->vertex_real_idx ];
|
||||
unsigned long address = (unsigned long)real_buf->bus_address;
|
||||
unsigned long start = address - dev->agp->base;
|
||||
xf86drmClipRectRec *box = buf_priv->boxes;
|
||||
int length = buf->used;
|
||||
int i = 0;
|
||||
RING_LOCALS;
|
||||
|
||||
if (I810_VERBOSE)
|
||||
printk("dispatch vertex addr 0x%lx, length 0x%x nbox %d\n",
|
||||
address, length, buf_priv->nbox);
|
||||
|
||||
dev_priv->counter++;
|
||||
printk( "dispatch counter : %ld\n", dev_priv->counter);
|
||||
printk( "i810_dma_dispatch\n");
|
||||
printk( "start : %lx\n", start);
|
||||
printk( "length : %d\n", length);
|
||||
printk( "start + length - 4 : %ld\n", start + length - 4);
|
||||
i810_kernel_lost_context(dev);
|
||||
|
||||
if (!buf_priv->vertex_discard) {
|
||||
do {
|
||||
if (i < buf_priv->nbox) {
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR |
|
||||
SC_ENABLE );
|
||||
OUT_RING( GFX_OP_SCISSOR_INFO );
|
||||
OUT_RING( box[i].x1 | (box[i].y1 << 16) );
|
||||
OUT_RING( box[i].x2 | (box[i].y2 << 16) );
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING( CMD_OP_BATCH_BUFFER );
|
||||
OUT_RING( start | BB1_PROTECTED );
|
||||
OUT_RING( start + length - 4 );
|
||||
OUT_RING( 0 );
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
} while (++i < buf_priv->nbox);
|
||||
}
|
||||
|
||||
BEGIN_LP_RING( 6 );
|
||||
OUT_RING( CMD_STORE_DWORD_IDX );
|
||||
OUT_RING( 20 );
|
||||
OUT_RING( dev_priv->counter );
|
||||
OUT_RING( CMD_REPORT_HEAD );
|
||||
OUT_RING( GFX_OP_BREAKPOINT_INTERRUPT );
|
||||
OUT_RING( 0 );
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static inline void i810_dma_quiescent(drm_device_t *dev)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
|
||||
|
||||
DRM_DEBUG( "i810_dma_quiescent\n");
|
||||
printk( "i810_dma_quiescent\n");
|
||||
while(1) {
|
||||
atomic_inc(&dev_priv->dispatch_lock);
|
||||
if(atomic_read(&dev_priv->dispatch_lock) == 1) {
|
||||
|
|
@ -441,13 +492,13 @@ static inline void i810_dma_quiescent(drm_device_t *dev)
|
|||
static inline void i810_dma_ready(drm_device_t *dev)
|
||||
{
|
||||
i810_dma_quiescent(dev);
|
||||
DRM_DEBUG( "i810_dma_ready\n");
|
||||
printk( "i810_dma_ready\n");
|
||||
}
|
||||
|
||||
static inline int i810_dma_is_ready(drm_device_t *dev)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
|
||||
DRM_DEBUG( "i810_dma_is_ready\n");
|
||||
printk( "i810_dma_is_ready\n");
|
||||
atomic_inc(&dev_priv->dispatch_lock);
|
||||
if(atomic_read(&dev_priv->dispatch_lock) == 1) {
|
||||
/* We got the lock */
|
||||
|
|
@ -480,7 +531,7 @@ static void i810_dma_service(int irq, void *device, struct pt_regs *regs)
|
|||
u16 temp;
|
||||
|
||||
atomic_inc(&dev->total_irq);
|
||||
DRM_DEBUG("Interrupt Handler\n");
|
||||
printk("Interrupt Handler\n");
|
||||
i810_print_status_page(dev);
|
||||
temp = I810_READ16(I810REG_INT_IDENTITY_R);
|
||||
temp = temp & ~(0x6000);
|
||||
|
|
@ -511,8 +562,8 @@ static int i810_do_dma(drm_device_t *dev, int locked)
|
|||
int retcode = 0;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
|
||||
unsigned long address;
|
||||
unsigned long length;
|
||||
drm_i810_buf_priv_t *buf_priv;
|
||||
|
||||
|
||||
printk("i810_do_dma\n");
|
||||
if (test_and_set_bit(0, &dev->dma_flag)) {
|
||||
|
|
@ -570,12 +621,23 @@ static int i810_do_dma(drm_device_t *dev, int locked)
|
|||
buf->pending = 1;
|
||||
buf->waiting = 0;
|
||||
buf->list = DRM_LIST_PEND;
|
||||
address = buf->bus_address;
|
||||
length = buf->used;
|
||||
|
||||
printk("dispatch!\n");
|
||||
i810_dma_dispatch(dev, address, length);
|
||||
|
||||
buf_priv = buf->dev_private;
|
||||
if (I810_VERBOSE) printk("i810_do_dma - type %d\n", buf_priv->dma_type);
|
||||
|
||||
switch (buf_priv->dma_type) {
|
||||
case I810_DMA_GENERAL:
|
||||
i810_dma_dispatch_general( dev, buf );
|
||||
break;
|
||||
case I810_DMA_VERTEX:
|
||||
i810_dma_dispatch_vertex( dev, buf );
|
||||
break;
|
||||
default:
|
||||
printk("bad buffer type %x in dispatch\n", buf_priv->dma_type);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
atomic_dec(&dev_priv->pending_bufs);
|
||||
|
||||
if(dma->this_buffer) {
|
||||
|
|
@ -685,67 +747,6 @@ again:
|
|||
return retcode;
|
||||
}
|
||||
|
||||
static int i810_dma_send_buffers(drm_device_t *dev, drm_dma_t *d)
|
||||
{
|
||||
DECLARE_WAITQUEUE(entry, current);
|
||||
drm_buf_t *last_buf = NULL;
|
||||
int retcode = 0;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
d->context = DRM_KERNEL_CONTEXT;
|
||||
|
||||
if ((retcode = drm_dma_enqueue(dev, d))) {
|
||||
return retcode;
|
||||
}
|
||||
|
||||
atomic_inc(&dev_priv->pending_bufs);
|
||||
i810_dma_schedule(dev, 1);
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int i810_dma(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;
|
||||
int retcode = 0;
|
||||
drm_dma_t d;
|
||||
|
||||
DRM_DEBUG("i810_dma start\n");
|
||||
copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT);
|
||||
DRM_DEBUG("%d %d: %d send, %d req\n",
|
||||
current->pid, d.context, d.send_count, d.request_count);
|
||||
|
||||
if (d.send_count < 0 || d.send_count > dma->buf_count) {
|
||||
DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n",
|
||||
current->pid, d.send_count, dma->buf_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (d.request_count < 0 || d.request_count > dma->buf_count) {
|
||||
DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
|
||||
current->pid, d.request_count, dma->buf_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (d.send_count) {
|
||||
retcode = i810_dma_send_buffers(dev, &d);
|
||||
}
|
||||
|
||||
d.granted_count = 0;
|
||||
|
||||
if (!retcode && d.request_count) {
|
||||
retcode = drm_dma_get_buffers(dev, &d);
|
||||
}
|
||||
|
||||
DRM_DEBUG("%d returning, granted = %d\n",
|
||||
current->pid, d.granted_count);
|
||||
copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT);
|
||||
|
||||
DRM_DEBUG("i810_dma end (granted)\n");
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int i810_irq_install(drm_device_t *dev, int irq)
|
||||
{
|
||||
|
|
@ -762,8 +763,8 @@ int i810_irq_install(drm_device_t *dev, int irq)
|
|||
dev->irq = irq;
|
||||
up(&dev->struct_sem);
|
||||
|
||||
DRM_DEBUG( "Interrupt Install : %d\n", irq);
|
||||
DRM_DEBUG("%d\n", irq);
|
||||
printk( "Interrupt Install : %d\n", irq);
|
||||
printk("%d\n", irq);
|
||||
|
||||
dev->context_flag = 0;
|
||||
dev->interrupt_flag = 0;
|
||||
|
|
@ -821,10 +822,10 @@ int i810_irq_uninstall(drm_device_t *dev)
|
|||
|
||||
if (!irq) return -EINVAL;
|
||||
|
||||
DRM_DEBUG( "Interrupt UnInstall: %d\n", irq);
|
||||
printk( "Interrupt UnInstall: %d\n", irq);
|
||||
|
||||
|
||||
DRM_DEBUG("%d\n", irq);
|
||||
printk("%d\n", irq);
|
||||
|
||||
temp = I810_READ16(I810REG_INT_IDENTITY_R);
|
||||
temp = temp & ~(0x6000);
|
||||
|
|
@ -849,7 +850,7 @@ int i810_control(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
drm_control_t ctl;
|
||||
int retcode;
|
||||
|
||||
DRM_DEBUG( "i810_control\n");
|
||||
printk( "i810_control\n");
|
||||
|
||||
copy_from_user_ret(&ctl, (drm_control_t *)arg, sizeof(ctl), -EFAULT);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@
|
|||
#define EXPORT_SYMTAB
|
||||
#include "drmP.h"
|
||||
#include "i810_drv.h"
|
||||
#include "i810_dma.h"
|
||||
|
||||
|
||||
EXPORT_SYMBOL(i810_init);
|
||||
EXPORT_SYMBOL(i810_cleanup);
|
||||
|
||||
|
|
@ -105,6 +108,8 @@ static drm_ioctl_desc_t i810_ioctls[] = {
|
|||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_I810_INIT)] = { i810_dma_init, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_I810_VERTEX)] = { i810_dma_vertex, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_I810_DMA)] = { i810_dma_general, 1, 1 },
|
||||
};
|
||||
|
||||
#define I810_IOCTL_COUNT DRM_ARRAY_SIZE(i810_ioctls)
|
||||
|
|
|
|||
|
|
@ -34,25 +34,30 @@
|
|||
#include "i810_drm_public.h"
|
||||
|
||||
typedef struct _drm_i810_ring_buffer{
|
||||
int tail_mask;
|
||||
unsigned long Start;
|
||||
unsigned long End;
|
||||
unsigned long Size;
|
||||
u8 *virtual_start;
|
||||
int head;
|
||||
int tail;
|
||||
int space;
|
||||
} drm_i810_ring_buffer;
|
||||
int tail_mask;
|
||||
unsigned long Start;
|
||||
unsigned long End;
|
||||
unsigned long Size;
|
||||
u8 *virtual_start;
|
||||
int head;
|
||||
int tail;
|
||||
int space;
|
||||
} drm_i810_ring_buffer_t;
|
||||
|
||||
typedef struct drm_i810_private {
|
||||
int ring_map_idx;
|
||||
int buffer_map_idx;
|
||||
drm_i810_ring_buffer ring;
|
||||
|
||||
drm_i810_ring_buffer_t ring;
|
||||
drm_i810_sarea_t *sarea_priv;
|
||||
|
||||
unsigned long hw_status_page;
|
||||
unsigned long counter;
|
||||
|
||||
atomic_t dispatch_lock;
|
||||
atomic_t pending_bufs;
|
||||
atomic_t in_flush;
|
||||
|
||||
} drm_i810_private_t;
|
||||
|
||||
/* i810_drv.c */
|
||||
|
|
@ -115,41 +120,5 @@ extern int i810_context_switch(drm_device_t *dev, int old, int new);
|
|||
extern int i810_context_switch_complete(drm_device_t *dev, int new);
|
||||
|
||||
|
||||
#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
|
||||
#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
|
||||
#define CMD_REPORT_HEAD (7<<23)
|
||||
#define CMD_STORE_DWORD_IDX ((0x21<<23) | 0x1)
|
||||
#define CMD_OP_BATCH_BUFFER ((0x0<<29)|(0x30<<23)|0x1)
|
||||
|
||||
|
||||
#define BB1_START_ADDR_MASK (~0x7)
|
||||
#define BB1_PROTECTED (1<<0)
|
||||
#define BB1_UNPROTECTED (0<<0)
|
||||
#define BB2_END_ADDR_MASK (~0x7)
|
||||
|
||||
#define I810REG_HWSTAM 0x02098
|
||||
#define I810REG_INT_IDENTITY_R 0x020a4
|
||||
#define I810REG_INT_MASK_R 0x020a8
|
||||
#define I810REG_INT_ENABLE_R 0x020a0
|
||||
|
||||
#define LP_RING 0x2030
|
||||
#define HP_RING 0x2040
|
||||
#define RING_TAIL 0x00
|
||||
#define TAIL_ADDR 0x000FFFF8
|
||||
#define RING_HEAD 0x04
|
||||
#define HEAD_WRAP_COUNT 0xFFE00000
|
||||
#define HEAD_WRAP_ONE 0x00200000
|
||||
#define HEAD_ADDR 0x001FFFFC
|
||||
#define RING_START 0x08
|
||||
#define START_ADDR 0x00FFFFF8
|
||||
#define RING_LEN 0x0C
|
||||
#define RING_NR_PAGES 0x000FF000
|
||||
#define RING_REPORT_MASK 0x00000006
|
||||
#define RING_REPORT_64K 0x00000002
|
||||
#define RING_REPORT_128K 0x00000004
|
||||
#define RING_NO_REPORT 0x00000000
|
||||
#define RING_VALID_MASK 0x00000001
|
||||
#define RING_VALID 0x00000001
|
||||
#define RING_INVALID 0x00000000
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#define __NO_VERSION__
|
||||
#include "drmP.h"
|
||||
#include "i810_drv.h"
|
||||
#include "i810_dma.h"
|
||||
#include "linux/un.h"
|
||||
|
||||
int i810_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
|
|
@ -118,9 +119,6 @@ int i810_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
buf->total = alignment;
|
||||
buf->order = order;
|
||||
buf->used = 0;
|
||||
#if 0
|
||||
printk("offset : %d\n", offset);
|
||||
#endif
|
||||
buf->offset = offset; /* Hrm */
|
||||
buf->bus_address = dev->agp->base + agp_offset + offset;
|
||||
buf->address = (void *)(agp_offset + offset + dev->agp->base);
|
||||
|
|
@ -129,6 +127,10 @@ int i810_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
buf->pending = 0;
|
||||
init_waitqueue_head(&buf->dma_wait);
|
||||
buf->pid = 0;
|
||||
|
||||
buf->dev_private = drm_alloc(sizeof(drm_i810_buf_priv_t), DRM_MEM_BUFS);
|
||||
buf->dev_priv_size = sizeof(drm_i810_buf_priv_t);
|
||||
|
||||
#if DRM_DMA_HISTOGRAM
|
||||
buf->time_queued = 0;
|
||||
buf->time_dispatched = 0;
|
||||
|
|
|
|||
279
linux/i810_clear.c
Normal file
279
linux/i810_clear.c
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
/* i810_state.c -- State support for i810 g200/g400 -*- linux-c -*-
|
||||
*
|
||||
* Created: February 2000 by keithw@precisioninsight.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Keith Whitwell <keithw@precisioninsight.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "drmP.h"
|
||||
#include "i810_drv.h"
|
||||
#include "i810_dma.h"
|
||||
#include "i810_drm_public.h"
|
||||
|
||||
|
||||
|
||||
static int i810DmaGeneral(drm_device_t *dev, drm_i810_general_t *args)
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
drm_buf_t *buf = dma->buflist[ args->idx ];
|
||||
drm_i810_buf_priv_t *buf_priv = (drm_i810_buf_priv_t *)buf->dev_private;
|
||||
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
|
||||
drm_dma_t d;
|
||||
|
||||
buf_priv->dma_type = I810_DMA_GENERAL;
|
||||
buf->used = args->used;
|
||||
|
||||
if (I810_VERBOSE)
|
||||
printk("i810DmaGeneral idx %d used %d\n", args->idx, buf->used);
|
||||
|
||||
d.context = DRM_KERNEL_CONTEXT;
|
||||
d.send_count = 1;
|
||||
d.send_indices = &buf->idx;
|
||||
d.send_sizes = &buf->used;
|
||||
d.flags = 0;
|
||||
d.request_count = 0;
|
||||
d.request_size = 0;
|
||||
d.request_indices = NULL;
|
||||
d.request_sizes = NULL;
|
||||
d.granted_count = 0;
|
||||
|
||||
atomic_inc(&dev_priv->pending_bufs);
|
||||
if((drm_dma_enqueue(dev, &d)) != 0)
|
||||
atomic_dec(&dev_priv->pending_bufs);
|
||||
i810_dma_schedule(dev, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int i810DmaVertex(drm_device_t *dev, drm_i810_vertex_t *args)
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
|
||||
drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_i810_buf_priv_t *buf_priv;
|
||||
drm_buf_t *buf;
|
||||
drm_dma_t d;
|
||||
|
||||
|
||||
buf = dma->buflist[ args->idx ];
|
||||
buf->used = args->real_used;
|
||||
|
||||
if (I810_VERBOSE)
|
||||
printk("i810DmaVertex idx %d used %d\n", args->idx, buf->used);
|
||||
|
||||
buf_priv = buf->dev_private;
|
||||
buf_priv->dma_type = I810_DMA_VERTEX;
|
||||
buf_priv->vertex_real_idx = args->real_idx;
|
||||
buf_priv->vertex_discard = args->discard;
|
||||
buf_priv->nbox = sarea_priv->nbox;
|
||||
|
||||
if (buf_priv->nbox >= I810_NR_SAREA_CLIPRECTS)
|
||||
buf_priv->nbox = I810_NR_SAREA_CLIPRECTS;
|
||||
|
||||
if (buf_priv->nbox)
|
||||
memcpy( buf_priv->boxes,
|
||||
sarea_priv->boxes,
|
||||
buf_priv->nbox * sizeof(xf86drmClipRectRec));
|
||||
|
||||
d.context = DRM_KERNEL_CONTEXT;
|
||||
d.send_count = 1;
|
||||
d.send_indices = &buf->idx;
|
||||
d.send_sizes = &buf->used;
|
||||
d.flags = 0;
|
||||
d.request_count = 0;
|
||||
d.request_size = 0;
|
||||
d.request_indices = NULL;
|
||||
d.request_sizes = NULL;
|
||||
d.granted_count = 0;
|
||||
|
||||
atomic_inc(&dev_priv->pending_bufs);
|
||||
if((drm_dma_enqueue(dev, &d)) != 0)
|
||||
atomic_dec(&dev_priv->pending_bufs);
|
||||
i810_dma_schedule(dev, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int i810_dma_general(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_i810_general_t general;
|
||||
int retcode = 0;
|
||||
|
||||
copy_from_user_ret(&general, (drm_i810_general_t *)arg, sizeof(general),
|
||||
-EFAULT);
|
||||
|
||||
printk("i810 dma general idx %d used %d\n",
|
||||
general.idx, general.used);
|
||||
|
||||
retcode = i810DmaGeneral(dev, &general);
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int i810_dma_vertex(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_i810_vertex_t vertex;
|
||||
int retcode = 0;
|
||||
|
||||
copy_from_user_ret(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex),
|
||||
-EFAULT);
|
||||
|
||||
printk("i810 dma vertex, idx %d used %d real_idx %d discard %d\n",
|
||||
vertex.idx, vertex.real_used, vertex.real_idx,
|
||||
vertex.discard);
|
||||
|
||||
retcode = i810DmaVertex(dev, &vertex);
|
||||
|
||||
return retcode;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int i810_dma(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;
|
||||
int retcode = 0;
|
||||
drm_dma_t d;
|
||||
|
||||
copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT);
|
||||
DRM_DEBUG("%d %d: %d send, %d req\n",
|
||||
current->pid, d.context, d.send_count, d.request_count);
|
||||
|
||||
/* Per-context queues are unworkable if you are trying to do
|
||||
* state management from the client.
|
||||
*/
|
||||
d.context = DRM_KERNEL_CONTEXT;
|
||||
d.flags &= ~_DRM_DMA_WHILE_LOCKED;
|
||||
|
||||
/* Please don't send us buffers.
|
||||
*/
|
||||
if (d.send_count != 0) {
|
||||
DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
|
||||
current->pid, d.send_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* We'll send you buffers.
|
||||
*/
|
||||
if (d.request_count < 0 || d.request_count > dma->buf_count) {
|
||||
DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
|
||||
current->pid, d.request_count, dma->buf_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
d.granted_count = 0;
|
||||
|
||||
if (!retcode && d.request_count) {
|
||||
retcode = drm_dma_get_buffers(dev, &d);
|
||||
}
|
||||
|
||||
printk("i810_dma: %d returning, granted = %d\n",
|
||||
current->pid, d.granted_count);
|
||||
|
||||
copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT);
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
static int i810_dma_send_buffers(drm_device_t *dev, drm_dma_t *d)
|
||||
{
|
||||
DECLARE_WAITQUEUE(entry, current);
|
||||
drm_buf_t *last_buf = NULL;
|
||||
int retcode = 0;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
d->context = DRM_KERNEL_CONTEXT;
|
||||
|
||||
if ((retcode = drm_dma_enqueue(dev, d))) {
|
||||
return retcode;
|
||||
}
|
||||
|
||||
atomic_inc(&dev_priv->pending_bufs);
|
||||
i810_dma_schedule(dev, 1);
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int i810_dma(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;
|
||||
int retcode = 0;
|
||||
drm_dma_t d;
|
||||
|
||||
DRM_DEBUG("i810_dma start\n");
|
||||
copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT);
|
||||
DRM_DEBUG("%d %d: %d send, %d req\n",
|
||||
current->pid, d.context, d.send_count, d.request_count);
|
||||
|
||||
if (d.send_count < 0 || d.send_count > dma->buf_count) {
|
||||
DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n",
|
||||
current->pid, d.send_count, dma->buf_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (d.request_count < 0 || d.request_count > dma->buf_count) {
|
||||
DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
|
||||
current->pid, d.request_count, dma->buf_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (d.send_count) {
|
||||
retcode = i810_dma_send_buffers(dev, &d);
|
||||
}
|
||||
|
||||
d.granted_count = 0;
|
||||
|
||||
if (!retcode && d.request_count) {
|
||||
retcode = drm_dma_get_buffers(dev, &d);
|
||||
}
|
||||
|
||||
DRM_DEBUG("%d returning, granted = %d\n",
|
||||
current->pid, d.granted_count);
|
||||
copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT);
|
||||
|
||||
DRM_DEBUG("i810_dma end (granted)\n");
|
||||
return retcode;
|
||||
}
|
||||
#endif
|
||||
395
linux/i810_dma.c
395
linux/i810_dma.c
|
|
@ -25,6 +25,7 @@
|
|||
*
|
||||
* Authors: Rickard E. (Rik) Faith <faith@precisioninsight.com>
|
||||
* Jeff Hartmann <jhartmann@precisioninsight.com>
|
||||
* Keith Whitwell <keithw@precisioninsight.com>
|
||||
*
|
||||
* $XFree86$
|
||||
*
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
#include "drmP.h"
|
||||
#include "i810_drm_public.h"
|
||||
#include "i810_drv.h"
|
||||
#include "i810_dma.h"
|
||||
|
||||
#include <linux/interrupt.h> /* For task queue support */
|
||||
#include <linux/time.h> /* For do_gettimeofday */
|
||||
|
|
@ -49,24 +51,31 @@
|
|||
#define I810_READ16(reg) I810_DEREF16(reg)
|
||||
#define I810_WRITE16(reg,val) do { I810_DEREF16(reg) = val; } while (0)
|
||||
|
||||
#define RING_LOCALS() unsigned int outring, ringmask; volatile char *virt;
|
||||
#define BEGIN_LP_RING(n) \
|
||||
if (dev_priv->ring.space < n*4) i810_wait_ring(dev, n*4, 0); \
|
||||
dev_priv->ring.space -= n*4; \
|
||||
outring = dev_priv->ring.tail; \
|
||||
ringmask = dev_priv->ring.tail_mask; \
|
||||
virt = dev_priv->ring.virtual_start;
|
||||
#define RING_LOCALS unsigned int outring, ringmask; volatile char *virt;
|
||||
|
||||
#define ADVANCE_LP_RING() { \
|
||||
dev_priv->ring.tail = outring; \
|
||||
I810_WRITE(LP_RING + RING_TAIL, outring); \
|
||||
}
|
||||
|
||||
#define OUT_RING(n) { \
|
||||
*(volatile unsigned int *)(virt + outring) = n; \
|
||||
outring += 4; \
|
||||
outring &= ringmask; \
|
||||
}
|
||||
#define BEGIN_LP_RING(n) do { \
|
||||
if (I810_VERBOSE) \
|
||||
printk("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__); \
|
||||
if (dev_priv->ring.space < n*4) i810_wait_ring(dev, n*4, 0); \
|
||||
dev_priv->ring.space -= n*4; \
|
||||
outring = dev_priv->ring.tail; \
|
||||
ringmask = dev_priv->ring.tail_mask; \
|
||||
virt = dev_priv->ring.virtual_start; \
|
||||
} while (0)
|
||||
|
||||
#define ADVANCE_LP_RING() do { \
|
||||
if (I810_VERBOSE) printk("ADVANCE_LP_RING\n"); \
|
||||
dev_priv->ring.tail = outring; \
|
||||
I810_WRITE(LP_RING + RING_TAIL, outring); \
|
||||
} while(0)
|
||||
|
||||
#define OUT_RING(n) do { \
|
||||
if (I810_VERBOSE) printk(" OUT_RING %x\n", (int)(n)); \
|
||||
*(volatile unsigned int *)(virt + outring) = n; \
|
||||
outring += 4; \
|
||||
outring &= ringmask; \
|
||||
} while (0);
|
||||
|
||||
static unsigned long i810_alloc_page(drm_device_t *dev)
|
||||
{
|
||||
|
|
@ -101,28 +110,28 @@ static int i810_alloc_kernel_queue(drm_device_t *dev)
|
|||
down(&dev->struct_sem);
|
||||
|
||||
if(dev->queue_count != 0) {
|
||||
/* Reseting the kernel context here is not
|
||||
* a race, since it can only happen when that
|
||||
* queue is empty.
|
||||
*/
|
||||
queue = dev->queuelist[DRM_KERNEL_CONTEXT];
|
||||
printk("Kernel queue already allocated\n");
|
||||
/* Reseting the kernel context here is not
|
||||
* a race, since it can only happen when that
|
||||
* queue is empty.
|
||||
*/
|
||||
queue = dev->queuelist[DRM_KERNEL_CONTEXT];
|
||||
printk("Kernel queue already allocated\n");
|
||||
} else {
|
||||
queue = drm_alloc(sizeof(*queue), DRM_MEM_QUEUES);
|
||||
if(!queue) {
|
||||
up(&dev->struct_sem);
|
||||
printk("out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
++dev->queue_count;
|
||||
dev->queuelist = drm_alloc(sizeof(*dev->queuelist),
|
||||
DRM_MEM_QUEUES);
|
||||
if(!dev->queuelist) {
|
||||
up(&dev->struct_sem);
|
||||
drm_free(queue, sizeof(*queue), DRM_MEM_QUEUES);
|
||||
printk("out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
queue = drm_alloc(sizeof(*queue), DRM_MEM_QUEUES);
|
||||
if(!queue) {
|
||||
up(&dev->struct_sem);
|
||||
printk("out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
++dev->queue_count;
|
||||
dev->queuelist = drm_alloc(sizeof(*dev->queuelist),
|
||||
DRM_MEM_QUEUES);
|
||||
if(!dev->queuelist) {
|
||||
up(&dev->struct_sem);
|
||||
drm_free(queue, sizeof(*queue), DRM_MEM_QUEUES);
|
||||
printk("out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
memset(queue, 0, sizeof(*queue));
|
||||
|
|
@ -154,7 +163,7 @@ static int i810_alloc_kernel_queue(drm_device_t *dev)
|
|||
|
||||
static int i810_dma_cleanup(drm_device_t *dev)
|
||||
{
|
||||
DRM_DEBUG("i810_dma_cleanup\n");
|
||||
printk("i810_dma_cleanup\n");
|
||||
|
||||
if(dev->dev_private) {
|
||||
drm_i810_private_t *dev_priv =
|
||||
|
|
@ -178,8 +187,7 @@ static int i810_dma_cleanup(drm_device_t *dev)
|
|||
|
||||
static int __gettimeinmillis(void)
|
||||
{
|
||||
struct timeval timep;
|
||||
|
||||
struct timeval timep;
|
||||
do_gettimeofday(&timep);
|
||||
return(timep.tv_sec * 1000) + (timep.tv_usec / 1000);
|
||||
}
|
||||
|
|
@ -187,14 +195,14 @@ static int __gettimeinmillis(void)
|
|||
static int i810_wait_ring(drm_device_t *dev, int n, int timeout_millis)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
drm_i810_ring_buffer *ring = &(dev_priv->ring);
|
||||
drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
|
||||
int iters = 0;
|
||||
int startTime = 0;
|
||||
int curTime = 0;
|
||||
|
||||
if (timeout_millis == 0) timeout_millis = 3000;
|
||||
|
||||
DRM_DEBUG( "i810_wait_ring %d\n", n);
|
||||
printk( "i810_wait_ring %d\n", n);
|
||||
|
||||
while (ring->space < n) {
|
||||
int i;
|
||||
|
|
@ -211,8 +219,9 @@ static int i810_wait_ring(drm_device_t *dev, int n, int timeout_millis)
|
|||
} else if (curTime - startTime > timeout_millis) {
|
||||
DRM_ERROR("space: %d wanted %d\n", ring->space, n);
|
||||
DRM_ERROR("lockup\n");
|
||||
schedule(); /* JEFF - what to do here ??? */
|
||||
}
|
||||
|
||||
|
||||
for (i = 0 ; i < 2000 ; i++) ;
|
||||
}
|
||||
|
||||
|
|
@ -222,9 +231,9 @@ static int i810_wait_ring(drm_device_t *dev, int n, int timeout_millis)
|
|||
static void i810_kernel_lost_context(drm_device_t *dev)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
drm_i810_ring_buffer *ring = &(dev_priv->ring);
|
||||
drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
|
||||
|
||||
DRM_DEBUG("i810_kernel_lost_context, old ring (%x,%x)\n",
|
||||
printk("i810_kernel_lost_context, old ring (%x,%x)\n",
|
||||
ring->head, ring->tail);
|
||||
|
||||
ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
|
||||
|
|
@ -232,49 +241,26 @@ static void i810_kernel_lost_context(drm_device_t *dev)
|
|||
ring->space = ring->head - (ring->tail+8);
|
||||
if (ring->space < 0) ring->space += ring->Size;
|
||||
|
||||
DRM_DEBUG("new ring (%x,%x)\n", ring->head, ring->tail);
|
||||
printk("new ring (%x,%x)\n", ring->head, ring->tail);
|
||||
}
|
||||
|
||||
static inline void i810_ring_write_status(drm_device_t *dev)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
RING_LOCALS();
|
||||
RING_LOCALS;
|
||||
|
||||
i810_kernel_lost_context(dev);
|
||||
dev_priv->counter++;
|
||||
#if 1
|
||||
BEGIN_LP_RING(8);
|
||||
#else
|
||||
BEGIN_LP_RING(16);
|
||||
#endif
|
||||
|
||||
BEGIN_LP_RING(6);
|
||||
OUT_RING(CMD_REPORT_HEAD);
|
||||
OUT_RING(0);
|
||||
#if 1
|
||||
OUT_RING(CMD_STORE_DWORD_IDX);
|
||||
OUT_RING(5 * sizeof(unsigned long));
|
||||
OUT_RING(dev_priv->counter);
|
||||
OUT_RING(0);
|
||||
|
||||
#endif
|
||||
/* Add a breakpoint interrupt at the end */
|
||||
#if 1
|
||||
OUT_RING(0);
|
||||
OUT_RING(GFX_OP_BREAKPOINT_INTERRUPT);
|
||||
#endif
|
||||
/* Add a blit here just to see if my commands work */
|
||||
#if 0
|
||||
OUT_RING(0x02000000);
|
||||
OUT_RING(0);
|
||||
OUT_RING(0x50c00004);
|
||||
OUT_RING(0xcc0800);
|
||||
OUT_RING(0x1900320);
|
||||
OUT_RING(0);
|
||||
OUT_RING(0x800);
|
||||
OUT_RING(0xb80000);
|
||||
OUT_RING(0x02000000);
|
||||
OUT_RING(0);
|
||||
#endif
|
||||
OUT_RING(0);
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
/* Wait for ring to complete */
|
||||
i810_wait_ring(dev, dev_priv->ring.Size - 8, 0);
|
||||
}
|
||||
|
|
@ -284,35 +270,42 @@ static inline void i810_print_status_page(drm_device_t *dev)
|
|||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
u32 *temp = (u32 *)dev_priv->hw_status_page;
|
||||
|
||||
DRM_DEBUG( "hw_status: Interrupt Status : %lx\n", temp[0]);
|
||||
DRM_DEBUG( "hw_status: LpRing Head ptr : %lx\n", temp[1]);
|
||||
DRM_DEBUG( "hw_status: IRing Head ptr : %lx\n", temp[2]);
|
||||
DRM_DEBUG( "hw_status: Reserved : %lx\n", temp[3]);
|
||||
DRM_DEBUG( "hw_status: Driver Counter : %d\n", temp[5]);
|
||||
printk( "hw_status: Interrupt Status : %x\n", temp[0]);
|
||||
printk( "hw_status: LpRing Head ptr : %x\n", temp[1]);
|
||||
printk( "hw_status: IRing Head ptr : %x\n", temp[2]);
|
||||
printk( "hw_status: Reserved : %x\n", temp[3]);
|
||||
printk( "hw_status: Driver Counter : %d\n", temp[5]);
|
||||
}
|
||||
|
||||
static int i810_dma_initialize(drm_device_t *dev,
|
||||
drm_i810_private_t *dev_priv,
|
||||
drm_i810_init_t *init)
|
||||
{
|
||||
DRM_DEBUG( "i810_dma_init\n");
|
||||
drm_map_t *sarea_map;
|
||||
|
||||
printk( "i810_dma_init\n");
|
||||
dev->dev_private = (void *) dev_priv;
|
||||
memset(dev_priv, 0, sizeof(drm_i810_private_t));
|
||||
if((init->ring_map_idx >= dev->map_count) ||
|
||||
(init->buffer_map_idx >= dev->map_count)) {
|
||||
|
||||
if (init->ring_map_idx >= dev->map_count ||
|
||||
init->buffer_map_idx >= dev->map_count) {
|
||||
i810_dma_cleanup(dev);
|
||||
DRM_ERROR("ring_map or buffer_map are invalid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if(i810_alloc_kernel_queue(dev) != DRM_KERNEL_CONTEXT) {
|
||||
i810_dma_cleanup(dev);
|
||||
DRM_ERROR("Kernel context queue not present\n");
|
||||
return -ENOMEM;
|
||||
if (i810_alloc_kernel_queue(dev) != DRM_KERNEL_CONTEXT) {
|
||||
i810_dma_cleanup(dev);
|
||||
DRM_ERROR("Kernel context queue not present\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dev_priv->ring_map_idx = init->ring_map_idx;
|
||||
dev_priv->buffer_map_idx = init->buffer_map_idx;
|
||||
sarea_map = dev->maplist[0];
|
||||
dev_priv->sarea_priv = (drm_i810_sarea_t *)
|
||||
((u8 *)sarea_map->handle +
|
||||
init->sarea_priv_offset);
|
||||
|
||||
atomic_set(&dev_priv->pending_bufs, 0);
|
||||
atomic_set(&dev_priv->dispatch_lock, 0);
|
||||
|
|
@ -326,7 +319,7 @@ static int i810_dma_initialize(drm_device_t *dev,
|
|||
init->ring_size);
|
||||
dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
|
||||
|
||||
if(dev_priv->ring.virtual_start == NULL) {
|
||||
if (dev_priv->ring.virtual_start == NULL) {
|
||||
i810_dma_cleanup(dev);
|
||||
DRM_ERROR("can not ioremap virtual address for"
|
||||
" ring buffer\n");
|
||||
|
|
@ -337,20 +330,20 @@ static int i810_dma_initialize(drm_device_t *dev,
|
|||
dev_priv->hw_status_page = i810_alloc_page(dev);
|
||||
memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE);
|
||||
if(dev_priv->hw_status_page == 0UL) {
|
||||
i810_dma_cleanup(dev);
|
||||
DRM_ERROR("Can not allocate hardware status page\n");
|
||||
return -ENOMEM;
|
||||
i810_dma_cleanup(dev);
|
||||
DRM_ERROR("Can not allocate hardware status page\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page);
|
||||
printk("hw status page @ %lx\n", dev_priv->hw_status_page);
|
||||
|
||||
I810_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page));
|
||||
DRM_DEBUG("Enabled hardware status page\n");
|
||||
printk("Enabled hardware status page\n");
|
||||
#if 0
|
||||
DRM_DEBUG("Doing first ring buffer write\n");
|
||||
printk("Doing first ring buffer write\n");
|
||||
i810_ring_write_status(dev);
|
||||
DRM_DEBUG("First ring write succeeded\n");
|
||||
printk("First ring write succeeded\n");
|
||||
i810_print_status_page(dev);
|
||||
DRM_DEBUG("Status page dump succeeded\n");
|
||||
printk("Status page dump succeeded\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -385,48 +378,106 @@ int i810_dma_init(struct inode *inode, struct file *filp,
|
|||
return retcode;
|
||||
}
|
||||
|
||||
static inline void i810_dma_dispatch(drm_device_t *dev, unsigned long address,
|
||||
unsigned long length)
|
||||
static void i810_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
unsigned long address = (unsigned long)buf->bus_address;
|
||||
unsigned long start = address - dev->agp->base;
|
||||
RING_LOCALS();
|
||||
int length = buf->used;
|
||||
RING_LOCALS;
|
||||
|
||||
dev_priv->counter++;
|
||||
DRM_DEBUG( "dispatch counter : %d\n", dev_priv->counter);
|
||||
DRM_DEBUG( "i810_dma_dispatch\n");
|
||||
DRM_DEBUG( "start : %lx\n", start);
|
||||
DRM_DEBUG( "length : %d\n", length);
|
||||
DRM_DEBUG( "start + length - 4 : %d\n", start + length - 4);
|
||||
printk( "dispatch counter : %ld\n", dev_priv->counter);
|
||||
printk( "i810_dma_dispatch\n");
|
||||
printk( "start : 0x%lx\n", start);
|
||||
printk( "length : 0x%x\n", length);
|
||||
printk( "start + length - 4 : 0x%lx\n", start + length - 4);
|
||||
i810_kernel_lost_context(dev);
|
||||
|
||||
|
||||
BEGIN_LP_RING(8);
|
||||
OUT_RING(CMD_OP_BATCH_BUFFER);
|
||||
OUT_RING(start | BB1_PROTECTED);
|
||||
OUT_RING((start + length) - 4);
|
||||
OUT_RING(CMD_STORE_DWORD_IDX);
|
||||
OUT_RING(5 * sizeof(unsigned long));
|
||||
OUT_RING(dev_priv->counter);
|
||||
/* Add a breakpoint interrupt at the end */
|
||||
OUT_RING(CMD_REPORT_HEAD);
|
||||
OUT_RING(GFX_OP_BREAKPOINT_INTERRUPT);
|
||||
OUT_RING( CMD_OP_BATCH_BUFFER );
|
||||
OUT_RING( start | BB1_PROTECTED );
|
||||
OUT_RING( start + length - 4 );
|
||||
OUT_RING( CMD_STORE_DWORD_IDX );
|
||||
OUT_RING( 20 );
|
||||
OUT_RING( dev_priv->counter );
|
||||
OUT_RING( CMD_REPORT_HEAD );
|
||||
OUT_RING( GFX_OP_BREAKPOINT_INTERRUPT );
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
/* Wait for ring to flush */
|
||||
#if 0
|
||||
i810_wait_ring(dev, dev_priv->ring.Size - 8, 0);
|
||||
i810_ring_write_status(dev);
|
||||
DRM_DEBUG("ring write succeeded\n");
|
||||
i810_print_status_page(dev);
|
||||
DRM_DEBUG("Status page dump succeeded\n");
|
||||
#endif
|
||||
i810_print_status_page(dev);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void i810_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
|
||||
drm_buf_t *real_buf = dev->dma->buflist[ buf_priv->vertex_real_idx ];
|
||||
unsigned long address = (unsigned long)real_buf->bus_address;
|
||||
unsigned long start = address - dev->agp->base;
|
||||
xf86drmClipRectRec *box = buf_priv->boxes;
|
||||
int length = buf->used;
|
||||
int i = 0;
|
||||
RING_LOCALS;
|
||||
|
||||
if (I810_VERBOSE)
|
||||
printk("dispatch vertex addr 0x%lx, length 0x%x nbox %d\n",
|
||||
address, length, buf_priv->nbox);
|
||||
|
||||
dev_priv->counter++;
|
||||
printk( "dispatch counter : %ld\n", dev_priv->counter);
|
||||
printk( "i810_dma_dispatch\n");
|
||||
printk( "start : %lx\n", start);
|
||||
printk( "length : %d\n", length);
|
||||
printk( "start + length - 4 : %ld\n", start + length - 4);
|
||||
i810_kernel_lost_context(dev);
|
||||
|
||||
if (!buf_priv->vertex_discard) {
|
||||
do {
|
||||
if (i < buf_priv->nbox) {
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR |
|
||||
SC_ENABLE );
|
||||
OUT_RING( GFX_OP_SCISSOR_INFO );
|
||||
OUT_RING( box[i].x1 | (box[i].y1 << 16) );
|
||||
OUT_RING( box[i].x2 | (box[i].y2 << 16) );
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING( CMD_OP_BATCH_BUFFER );
|
||||
OUT_RING( start | BB1_PROTECTED );
|
||||
OUT_RING( start + length - 4 );
|
||||
OUT_RING( 0 );
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
} while (++i < buf_priv->nbox);
|
||||
}
|
||||
|
||||
BEGIN_LP_RING( 6 );
|
||||
OUT_RING( CMD_STORE_DWORD_IDX );
|
||||
OUT_RING( 20 );
|
||||
OUT_RING( dev_priv->counter );
|
||||
OUT_RING( CMD_REPORT_HEAD );
|
||||
OUT_RING( GFX_OP_BREAKPOINT_INTERRUPT );
|
||||
OUT_RING( 0 );
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static inline void i810_dma_quiescent(drm_device_t *dev)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
|
||||
|
||||
DRM_DEBUG( "i810_dma_quiescent\n");
|
||||
printk( "i810_dma_quiescent\n");
|
||||
while(1) {
|
||||
atomic_inc(&dev_priv->dispatch_lock);
|
||||
if(atomic_read(&dev_priv->dispatch_lock) == 1) {
|
||||
|
|
@ -441,13 +492,13 @@ static inline void i810_dma_quiescent(drm_device_t *dev)
|
|||
static inline void i810_dma_ready(drm_device_t *dev)
|
||||
{
|
||||
i810_dma_quiescent(dev);
|
||||
DRM_DEBUG( "i810_dma_ready\n");
|
||||
printk( "i810_dma_ready\n");
|
||||
}
|
||||
|
||||
static inline int i810_dma_is_ready(drm_device_t *dev)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
|
||||
DRM_DEBUG( "i810_dma_is_ready\n");
|
||||
printk( "i810_dma_is_ready\n");
|
||||
atomic_inc(&dev_priv->dispatch_lock);
|
||||
if(atomic_read(&dev_priv->dispatch_lock) == 1) {
|
||||
/* We got the lock */
|
||||
|
|
@ -480,7 +531,7 @@ static void i810_dma_service(int irq, void *device, struct pt_regs *regs)
|
|||
u16 temp;
|
||||
|
||||
atomic_inc(&dev->total_irq);
|
||||
DRM_DEBUG("Interrupt Handler\n");
|
||||
printk("Interrupt Handler\n");
|
||||
i810_print_status_page(dev);
|
||||
temp = I810_READ16(I810REG_INT_IDENTITY_R);
|
||||
temp = temp & ~(0x6000);
|
||||
|
|
@ -511,8 +562,8 @@ static int i810_do_dma(drm_device_t *dev, int locked)
|
|||
int retcode = 0;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
|
||||
unsigned long address;
|
||||
unsigned long length;
|
||||
drm_i810_buf_priv_t *buf_priv;
|
||||
|
||||
|
||||
printk("i810_do_dma\n");
|
||||
if (test_and_set_bit(0, &dev->dma_flag)) {
|
||||
|
|
@ -570,12 +621,23 @@ static int i810_do_dma(drm_device_t *dev, int locked)
|
|||
buf->pending = 1;
|
||||
buf->waiting = 0;
|
||||
buf->list = DRM_LIST_PEND;
|
||||
address = buf->bus_address;
|
||||
length = buf->used;
|
||||
|
||||
printk("dispatch!\n");
|
||||
i810_dma_dispatch(dev, address, length);
|
||||
|
||||
buf_priv = buf->dev_private;
|
||||
if (I810_VERBOSE) printk("i810_do_dma - type %d\n", buf_priv->dma_type);
|
||||
|
||||
switch (buf_priv->dma_type) {
|
||||
case I810_DMA_GENERAL:
|
||||
i810_dma_dispatch_general( dev, buf );
|
||||
break;
|
||||
case I810_DMA_VERTEX:
|
||||
i810_dma_dispatch_vertex( dev, buf );
|
||||
break;
|
||||
default:
|
||||
printk("bad buffer type %x in dispatch\n", buf_priv->dma_type);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
atomic_dec(&dev_priv->pending_bufs);
|
||||
|
||||
if(dma->this_buffer) {
|
||||
|
|
@ -685,67 +747,6 @@ again:
|
|||
return retcode;
|
||||
}
|
||||
|
||||
static int i810_dma_send_buffers(drm_device_t *dev, drm_dma_t *d)
|
||||
{
|
||||
DECLARE_WAITQUEUE(entry, current);
|
||||
drm_buf_t *last_buf = NULL;
|
||||
int retcode = 0;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
d->context = DRM_KERNEL_CONTEXT;
|
||||
|
||||
if ((retcode = drm_dma_enqueue(dev, d))) {
|
||||
return retcode;
|
||||
}
|
||||
|
||||
atomic_inc(&dev_priv->pending_bufs);
|
||||
i810_dma_schedule(dev, 1);
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int i810_dma(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;
|
||||
int retcode = 0;
|
||||
drm_dma_t d;
|
||||
|
||||
DRM_DEBUG("i810_dma start\n");
|
||||
copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT);
|
||||
DRM_DEBUG("%d %d: %d send, %d req\n",
|
||||
current->pid, d.context, d.send_count, d.request_count);
|
||||
|
||||
if (d.send_count < 0 || d.send_count > dma->buf_count) {
|
||||
DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n",
|
||||
current->pid, d.send_count, dma->buf_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (d.request_count < 0 || d.request_count > dma->buf_count) {
|
||||
DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
|
||||
current->pid, d.request_count, dma->buf_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (d.send_count) {
|
||||
retcode = i810_dma_send_buffers(dev, &d);
|
||||
}
|
||||
|
||||
d.granted_count = 0;
|
||||
|
||||
if (!retcode && d.request_count) {
|
||||
retcode = drm_dma_get_buffers(dev, &d);
|
||||
}
|
||||
|
||||
DRM_DEBUG("%d returning, granted = %d\n",
|
||||
current->pid, d.granted_count);
|
||||
copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT);
|
||||
|
||||
DRM_DEBUG("i810_dma end (granted)\n");
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int i810_irq_install(drm_device_t *dev, int irq)
|
||||
{
|
||||
|
|
@ -762,8 +763,8 @@ int i810_irq_install(drm_device_t *dev, int irq)
|
|||
dev->irq = irq;
|
||||
up(&dev->struct_sem);
|
||||
|
||||
DRM_DEBUG( "Interrupt Install : %d\n", irq);
|
||||
DRM_DEBUG("%d\n", irq);
|
||||
printk( "Interrupt Install : %d\n", irq);
|
||||
printk("%d\n", irq);
|
||||
|
||||
dev->context_flag = 0;
|
||||
dev->interrupt_flag = 0;
|
||||
|
|
@ -821,10 +822,10 @@ int i810_irq_uninstall(drm_device_t *dev)
|
|||
|
||||
if (!irq) return -EINVAL;
|
||||
|
||||
DRM_DEBUG( "Interrupt UnInstall: %d\n", irq);
|
||||
printk( "Interrupt UnInstall: %d\n", irq);
|
||||
|
||||
|
||||
DRM_DEBUG("%d\n", irq);
|
||||
printk("%d\n", irq);
|
||||
|
||||
temp = I810_READ16(I810REG_INT_IDENTITY_R);
|
||||
temp = temp & ~(0x6000);
|
||||
|
|
@ -849,7 +850,7 @@ int i810_control(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
drm_control_t ctl;
|
||||
int retcode;
|
||||
|
||||
DRM_DEBUG( "i810_control\n");
|
||||
printk( "i810_control\n");
|
||||
|
||||
copy_from_user_ret(&ctl, (drm_control_t *)arg, sizeof(ctl), -EFAULT);
|
||||
|
||||
|
|
|
|||
113
linux/i810_dma.h
Normal file
113
linux/i810_dma.h
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/* i810_dma.h -- DMA support for the i810 -*- linux-c -*-
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Keith Whitwell <keithw@precisioninsight.com>
|
||||
*
|
||||
* $XFree86$
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef I810_DMA_H
|
||||
#define I810_DMA_H
|
||||
|
||||
#include "i810_drm_public.h"
|
||||
|
||||
|
||||
/* Copy the outstanding cliprects for every I810_DMA_VERTEX buffer.
|
||||
* This can be fixed by emitting directly to the ringbuffer in the
|
||||
* 'vertex_dma' ioctl.
|
||||
*/
|
||||
typedef struct {
|
||||
int dma_type;
|
||||
int vertex_real_idx;
|
||||
int vertex_discard;
|
||||
unsigned int nbox;
|
||||
xf86drmClipRectRec boxes[I810_NR_SAREA_CLIPRECTS];
|
||||
} drm_i810_buf_priv_t;
|
||||
|
||||
|
||||
#define I810_DMA_GENERAL 0
|
||||
#define I810_DMA_VERTEX 1
|
||||
#define I810_DMA_DISCARD 2 /* not used */
|
||||
|
||||
#define I810_VERBOSE 1
|
||||
|
||||
|
||||
int i810_dma_vertex(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
int i810_dma_general(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
|
||||
#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
|
||||
#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
|
||||
#define CMD_REPORT_HEAD (7<<23)
|
||||
#define CMD_STORE_DWORD_IDX ((0x21<<23) | 0x1)
|
||||
#define CMD_OP_BATCH_BUFFER ((0x0<<29)|(0x30<<23)|0x1)
|
||||
|
||||
|
||||
#define BB1_START_ADDR_MASK (~0x7)
|
||||
#define BB1_PROTECTED (1<<0)
|
||||
#define BB1_UNPROTECTED (0<<0)
|
||||
#define BB2_END_ADDR_MASK (~0x7)
|
||||
|
||||
#define I810REG_HWSTAM 0x02098
|
||||
#define I810REG_INT_IDENTITY_R 0x020a4
|
||||
#define I810REG_INT_MASK_R 0x020a8
|
||||
#define I810REG_INT_ENABLE_R 0x020a0
|
||||
|
||||
#define LP_RING 0x2030
|
||||
#define HP_RING 0x2040
|
||||
#define RING_TAIL 0x00
|
||||
#define TAIL_ADDR 0x000FFFF8
|
||||
#define RING_HEAD 0x04
|
||||
#define HEAD_WRAP_COUNT 0xFFE00000
|
||||
#define HEAD_WRAP_ONE 0x00200000
|
||||
#define HEAD_ADDR 0x001FFFFC
|
||||
#define RING_START 0x08
|
||||
#define START_ADDR 0x00FFFFF8
|
||||
#define RING_LEN 0x0C
|
||||
#define RING_NR_PAGES 0x000FF000
|
||||
#define RING_REPORT_MASK 0x00000006
|
||||
#define RING_REPORT_64K 0x00000002
|
||||
#define RING_REPORT_128K 0x00000004
|
||||
#define RING_NO_REPORT 0x00000000
|
||||
#define RING_VALID_MASK 0x00000001
|
||||
#define RING_VALID 0x00000001
|
||||
#define RING_INVALID 0x00000000
|
||||
|
||||
#define GFX_OP_SCISSOR ((0x3<<29)|(0x1c<<24)|(0x10<<19))
|
||||
#define SC_UPDATE_SCISSOR (0x1<<1)
|
||||
#define SC_ENABLE_MASK (0x1<<0)
|
||||
#define SC_ENABLE (0x1<<0)
|
||||
|
||||
#define GFX_OP_SCISSOR_INFO ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
|
||||
#define SCI_YMIN_MASK (0xffff<<16)
|
||||
#define SCI_XMIN_MASK (0xffff<<0)
|
||||
#define SCI_YMAX_MASK (0xffff<<16)
|
||||
#define SCI_XMAX_MASK (0xffff<<0)
|
||||
|
||||
#endif
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Jeff Hartmann <jhartmann@precisioninsight.com>
|
||||
* Keith Whitwell <keithw@precisioninsight.com>
|
||||
*
|
||||
* $XFree86$
|
||||
*/
|
||||
|
|
@ -38,11 +39,95 @@ typedef struct drm_i810_init {
|
|||
} func;
|
||||
int ring_map_idx;
|
||||
int buffer_map_idx;
|
||||
int sarea_priv_offset;
|
||||
unsigned long ring_start;
|
||||
unsigned long ring_end;
|
||||
unsigned long ring_size;
|
||||
|
||||
} drm_i810_init_t;
|
||||
|
||||
typedef struct _xf86drmClipRectRec {
|
||||
unsigned short x1;
|
||||
unsigned short y1;
|
||||
unsigned short x2;
|
||||
unsigned short y2;
|
||||
} xf86drmClipRectRec;
|
||||
|
||||
|
||||
#define I810_DMA_BUF_ORDER 16
|
||||
#define I810_DMA_BUF_SZ (1<<I810_DMA_BUF_ORDER)
|
||||
#define I810_DMA_BUF_NR 63
|
||||
|
||||
#define I810_NR_SAREA_CLIPRECTS 2
|
||||
|
||||
|
||||
/* Each region is a minimum of 32k, and there are at most 128 of them.
|
||||
*/
|
||||
#define I810_NR_TEX_REGIONS 128
|
||||
#define I810_LOG_MIN_TEX_REGION_SIZE 18
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
unsigned char next, prev; /* indices to form a circular LRU */
|
||||
unsigned char in_use; /* owned by a client, or free? */
|
||||
int age; /* tracked by clients to update local LRU's */
|
||||
} i810TexRegion;
|
||||
|
||||
typedef struct {
|
||||
unsigned int nbox;
|
||||
xf86drmClipRectRec boxes[I810_NR_SAREA_CLIPRECTS];
|
||||
|
||||
/* Maintain an LRU of contiguous regions of texture space. If
|
||||
* you think you own a region of texture memory, and it has an age
|
||||
* different to the one you set, then you are mistaken and it has
|
||||
* been stolen by another client. If texAge hasn't changed, there
|
||||
* is no need to walk the list.
|
||||
*
|
||||
* These regions can be used as a proxy for the fine-grained texture
|
||||
* information of other clients - by maintaining them in the same
|
||||
* lru which is used to age their own textures, clients have an
|
||||
* approximate lru for the whole of global texture space, and can
|
||||
* make informed decisions as to which areas to kick out. There is
|
||||
* no need to choose whether to kick out your own texture or someone
|
||||
* else's - simply eject them all in LRU order.
|
||||
*/
|
||||
i810TexRegion texList[I810_NR_TEX_REGIONS+1]; /* Last elt is sentinal */
|
||||
int texAge; /* Current age counter */
|
||||
|
||||
|
||||
int lastDispatch;
|
||||
int lastGetBuffer; /* dodgy - not needed if dma uploads used */
|
||||
int ctxOwner; /* last context to upload state */
|
||||
|
||||
} drm_i810_sarea_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int idx;
|
||||
int used;
|
||||
} drm_i810_general_t;
|
||||
|
||||
|
||||
/* These may be placeholders if we have more cliprects than
|
||||
* I810_NR_SAREA_CLIPRECTS. In that case, idx != real_idx; idx is the
|
||||
* number of a placeholder buffer, real_idx is the real buffer to be
|
||||
* rendered multiple times.
|
||||
*
|
||||
* This is a hack to work around the fact that the drm considers
|
||||
* buffers to be only in a single state (ie on a single queue).
|
||||
*/
|
||||
typedef struct {
|
||||
int idx; /* buffer to queue and free on completion */
|
||||
int real_idx; /* buffer to execute */
|
||||
int real_used; /* buf->used in for real buffer */
|
||||
int discard; /* don't execute the commands */
|
||||
} drm_i810_vertex_t;
|
||||
|
||||
|
||||
|
||||
#define DRM_IOCTL_I810_INIT DRM_IOW( 0x40, drm_i810_init_t)
|
||||
#define DRM_IOCTL_I810_VERTEX DRM_IOW( 0x41, drm_i810_vertex_t)
|
||||
#define DRM_IOCTL_I810_DMA DRM_IOW( 0x42, drm_i810_general_t)
|
||||
|
||||
#endif /* _I810_DRM_H_ */
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@
|
|||
#define EXPORT_SYMTAB
|
||||
#include "drmP.h"
|
||||
#include "i810_drv.h"
|
||||
#include "i810_dma.h"
|
||||
|
||||
|
||||
EXPORT_SYMBOL(i810_init);
|
||||
EXPORT_SYMBOL(i810_cleanup);
|
||||
|
||||
|
|
@ -105,6 +108,8 @@ static drm_ioctl_desc_t i810_ioctls[] = {
|
|||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_I810_INIT)] = { i810_dma_init, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_I810_VERTEX)] = { i810_dma_vertex, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_I810_DMA)] = { i810_dma_general, 1, 1 },
|
||||
};
|
||||
|
||||
#define I810_IOCTL_COUNT DRM_ARRAY_SIZE(i810_ioctls)
|
||||
|
|
|
|||
|
|
@ -34,25 +34,30 @@
|
|||
#include "i810_drm_public.h"
|
||||
|
||||
typedef struct _drm_i810_ring_buffer{
|
||||
int tail_mask;
|
||||
unsigned long Start;
|
||||
unsigned long End;
|
||||
unsigned long Size;
|
||||
u8 *virtual_start;
|
||||
int head;
|
||||
int tail;
|
||||
int space;
|
||||
} drm_i810_ring_buffer;
|
||||
int tail_mask;
|
||||
unsigned long Start;
|
||||
unsigned long End;
|
||||
unsigned long Size;
|
||||
u8 *virtual_start;
|
||||
int head;
|
||||
int tail;
|
||||
int space;
|
||||
} drm_i810_ring_buffer_t;
|
||||
|
||||
typedef struct drm_i810_private {
|
||||
int ring_map_idx;
|
||||
int buffer_map_idx;
|
||||
drm_i810_ring_buffer ring;
|
||||
|
||||
drm_i810_ring_buffer_t ring;
|
||||
drm_i810_sarea_t *sarea_priv;
|
||||
|
||||
unsigned long hw_status_page;
|
||||
unsigned long counter;
|
||||
|
||||
atomic_t dispatch_lock;
|
||||
atomic_t pending_bufs;
|
||||
atomic_t in_flush;
|
||||
|
||||
} drm_i810_private_t;
|
||||
|
||||
/* i810_drv.c */
|
||||
|
|
@ -115,41 +120,5 @@ extern int i810_context_switch(drm_device_t *dev, int old, int new);
|
|||
extern int i810_context_switch_complete(drm_device_t *dev, int new);
|
||||
|
||||
|
||||
#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
|
||||
#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
|
||||
#define CMD_REPORT_HEAD (7<<23)
|
||||
#define CMD_STORE_DWORD_IDX ((0x21<<23) | 0x1)
|
||||
#define CMD_OP_BATCH_BUFFER ((0x0<<29)|(0x30<<23)|0x1)
|
||||
|
||||
|
||||
#define BB1_START_ADDR_MASK (~0x7)
|
||||
#define BB1_PROTECTED (1<<0)
|
||||
#define BB1_UNPROTECTED (0<<0)
|
||||
#define BB2_END_ADDR_MASK (~0x7)
|
||||
|
||||
#define I810REG_HWSTAM 0x02098
|
||||
#define I810REG_INT_IDENTITY_R 0x020a4
|
||||
#define I810REG_INT_MASK_R 0x020a8
|
||||
#define I810REG_INT_ENABLE_R 0x020a0
|
||||
|
||||
#define LP_RING 0x2030
|
||||
#define HP_RING 0x2040
|
||||
#define RING_TAIL 0x00
|
||||
#define TAIL_ADDR 0x000FFFF8
|
||||
#define RING_HEAD 0x04
|
||||
#define HEAD_WRAP_COUNT 0xFFE00000
|
||||
#define HEAD_WRAP_ONE 0x00200000
|
||||
#define HEAD_ADDR 0x001FFFFC
|
||||
#define RING_START 0x08
|
||||
#define START_ADDR 0x00FFFFF8
|
||||
#define RING_LEN 0x0C
|
||||
#define RING_NR_PAGES 0x000FF000
|
||||
#define RING_REPORT_MASK 0x00000006
|
||||
#define RING_REPORT_64K 0x00000002
|
||||
#define RING_REPORT_128K 0x00000004
|
||||
#define RING_NO_REPORT 0x00000000
|
||||
#define RING_VALID_MASK 0x00000001
|
||||
#define RING_VALID 0x00000001
|
||||
#define RING_INVALID 0x00000000
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue