diff options
Diffstat (limited to 'shared-core')
-rw-r--r-- | shared-core/drm.h | 14 | ||||
-rw-r--r-- | shared-core/drm_pciids.txt | 1 | ||||
-rw-r--r-- | shared-core/nouveau_drm.h | 29 | ||||
-rw-r--r-- | shared-core/nouveau_drv.h | 13 | ||||
-rw-r--r-- | shared-core/nouveau_fifo.c | 9 | ||||
-rw-r--r-- | shared-core/nouveau_irq.c | 64 | ||||
-rw-r--r-- | shared-core/nouveau_mem.c | 4 | ||||
-rw-r--r-- | shared-core/nouveau_object.c | 234 | ||||
-rw-r--r-- | shared-core/nouveau_reg.h | 10 | ||||
-rw-r--r-- | shared-core/nouveau_state.c | 13 | ||||
-rw-r--r-- | shared-core/nv40_graph.c | 8 | ||||
-rw-r--r-- | shared-core/r128_cce.c | 1 | ||||
-rw-r--r-- | shared-core/r128_drv.h | 2 | ||||
-rw-r--r-- | shared-core/radeon_cp.c | 6 | ||||
-rw-r--r-- | shared-core/radeon_drm.h | 1 | ||||
-rw-r--r-- | shared-core/radeon_drv.h | 4 | ||||
-rw-r--r-- | shared-core/radeon_state.c | 6 |
17 files changed, 242 insertions, 177 deletions
diff --git a/shared-core/drm.h b/shared-core/drm.h index 3a5d6346..bcb3eedf 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -679,7 +679,7 @@ typedef struct drm_set_version { typedef struct drm_fence_arg { unsigned handle; - int class; + int class; unsigned type; unsigned flags; unsigned signaled; @@ -808,7 +808,7 @@ typedef struct drm_bo_arg_request { drm_bo_type_t type; unsigned arg_handle; drm_u64_t buffer_start; - unsigned page_alignment; + unsigned page_alignment; unsigned expand_pad[4]; /*Future expansion */ enum { drm_bo_create, @@ -839,11 +839,11 @@ typedef struct drm_bo_arg_reply { drm_u64_t size; drm_u64_t offset; drm_u64_t arg_handle; - unsigned mask; - drm_u64_t buffer_start; - unsigned fence_flags; - unsigned rep_flags; - unsigned page_alignment; + unsigned mask; + drm_u64_t buffer_start; + unsigned fence_flags; + unsigned rep_flags; + unsigned page_alignment; unsigned expand_pad[4]; /*Future expansion */ }drm_bo_arg_reply_t; diff --git a/shared-core/drm_pciids.txt b/shared-core/drm_pciids.txt index 0fc9775b..a1bc907b 100644 --- a/shared-core/drm_pciids.txt +++ b/shared-core/drm_pciids.txt @@ -222,6 +222,7 @@ 0x1106 0x3344 0 "VIA CN700 / VM800 / P4M800Pro" 0x1106 0x3343 0 "VIA P4M890" 0x1106 0x3230 VIA_DX9_0 "VIA K8M890" +0x1106 0x3157 VIA_PRO_GROUP_A "VIA CX700" [i810] 0x8086 0x7121 0 "Intel i810 GMCH" diff --git a/shared-core/nouveau_drm.h b/shared-core/nouveau_drm.h index 0f11c43a..8a1964ed 100644 --- a/shared-core/nouveau_drm.h +++ b/shared-core/nouveau_drm.h @@ -25,6 +25,8 @@ #ifndef __NOUVEAU_DRM_H__ #define __NOUVEAU_DRM_H__ +#define NOUVEAU_DRM_HEADER_PATCHLEVEL 4 + typedef struct drm_nouveau_fifo_alloc { int channel; uint32_t put_base; @@ -37,24 +39,18 @@ typedef struct drm_nouveau_fifo_alloc { } drm_nouveau_fifo_alloc_t; -#define NV_DMA_CONTEXT_FLAGS_PATCH_ROP_AND 0x1 -#define NV_DMA_CONTEXT_FLAGS_PATCH_SRCCOPY 0x2 -#define NV_DMA_CONTEXT_FLAGS_CLIP_ENABLE 0x4 -#define NV_DMA_CONTEXT_FLAGS_MONO 0x8 - typedef struct drm_nouveau_object_init { uint32_t handle; - int class; - uint32_t flags; - /* these are object handles */ - uint32_t dma0; - uint32_t dma1; - uint32_t dma_notifier; + int class; } drm_nouveau_object_init_t; +#define NOUVEAU_MEM_ACCESS_RO 1 +#define NOUVEAU_MEM_ACCESS_WO 2 +#define NOUVEAU_MEM_ACCESS_RW 3 typedef struct drm_nouveau_dma_object_init { uint32_t handle; + int class; int access; int target; uint32_t offset; @@ -80,8 +76,8 @@ typedef struct drm_nouveau_mem_alloc { drm_nouveau_mem_alloc_t; typedef struct drm_nouveau_mem_free { - int flags; uint64_t region_offset; + int flags; } drm_nouveau_mem_free_t; @@ -91,9 +87,10 @@ drm_nouveau_mem_free_t; #define NOUVEAU_GETPARAM_BUS_TYPE 5 #define NOUVEAU_GETPARAM_FB_PHYSICAL 6 #define NOUVEAU_GETPARAM_AGP_PHYSICAL 7 +#define NOUVEAU_GETPARAM_FB_SIZE 8 +#define NOUVEAU_GETPARAM_AGP_SIZE 9 typedef struct drm_nouveau_getparam { - unsigned int param; - unsigned int dummy; + uint64_t param; uint64_t value; } drm_nouveau_getparam_t; @@ -101,8 +98,8 @@ drm_nouveau_getparam_t; #define NOUVEAU_SETPARAM_CMDBUF_LOCATION 1 #define NOUVEAU_SETPARAM_CMDBUF_SIZE 2 typedef struct drm_nouveau_setparam { - unsigned int param; - unsigned int value; + uint64_t param; + uint64_t value; } drm_nouveau_setparam_t; diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 63721650..c3d19bb0 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -34,7 +34,7 @@ #define DRIVER_MAJOR 0 #define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 3 +#define DRIVER_PATCHLEVEL 4 #define NOUVEAU_FAMILY 0x0000FFFF #define NOUVEAU_FLAGS 0xFFFF0000 @@ -70,9 +70,6 @@ struct nouveau_object int engine; }; -#define NV_DMA_TARGET_VIDMEM 0 -#define NV_DMA_TARGET_PCI 2 -#define NV_DMA_TARGET_AGP 3 struct nouveau_fifo { int used; @@ -134,7 +131,9 @@ typedef struct drm_nouveau_private { /* base physical adresses */ uint64_t fb_phys; + uint64_t fb_available_size; uint64_t agp_phys; + uint64_t agp_available_size; /* the mtrr covering the FB */ int fb_mtrr; @@ -192,8 +191,10 @@ extern void nouveau_fifo_free(drm_device_t *dev, int channel); /* nouveau_object.c */ extern void nouveau_object_cleanup(drm_device_t *dev, DRMFILE filp); -extern struct nouveau_object *nouveau_dma_object_create(drm_device_t *dev, - uint32_t offset, uint32_t size, int access, uint32_t target); +extern struct nouveau_object * +nouveau_dma_object_create(drm_device_t *dev, int class, + uint32_t offset, uint32_t size, + int access, int target); extern int nouveau_ioctl_object_init(DRM_IOCTL_ARGS); extern int nouveau_ioctl_dma_object_init(DRM_IOCTL_ARGS); extern uint32_t nouveau_chip_instance_get(drm_device_t *dev, struct mem_block *mem); diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index fd5455bf..6f75a05b 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -239,11 +239,12 @@ nouveau_fifo_cmdbuf_alloc(struct drm_device *dev, int channel) } if (cb->flags & NOUVEAU_MEM_AGP) { - cb_dma = nouveau_dma_object_create(dev, - cb->start, cb->size, + cb_dma = nouveau_dma_object_create(dev, NV_CLASS_DMA_IN_MEMORY, + cb->start - dev_priv->agp_phys, + cb->size, NV_DMA_ACCESS_RO, NV_DMA_TARGET_AGP); } else if (dev_priv->card_type != NV_04) { - cb_dma = nouveau_dma_object_create(dev, + cb_dma = nouveau_dma_object_create(dev, NV_CLASS_DMA_IN_MEMORY, cb->start - drm_get_resource_start(dev, 1), cb->size, NV_DMA_ACCESS_RO, NV_DMA_TARGET_VIDMEM); @@ -252,7 +253,7 @@ nouveau_fifo_cmdbuf_alloc(struct drm_device *dev, int channel) * exact reason for existing :) PCI access to cmdbuf in * VRAM. */ - cb_dma = nouveau_dma_object_create(dev, + cb_dma = nouveau_dma_object_create(dev, NV_CLASS_DMA_IN_MEMORY, cb->start, cb->size, NV_DMA_ACCESS_RO, NV_DMA_TARGET_PCI); } diff --git a/shared-core/nouveau_irq.c b/shared-core/nouveau_irq.c index 51d4bae1..32b33070 100644 --- a/shared-core/nouveau_irq.c +++ b/shared-core/nouveau_irq.c @@ -44,7 +44,7 @@ void nouveau_irq_preinstall(drm_device_t *dev) /* Disable/Clear PFIFO interrupts */ NV_WRITE(NV03_PFIFO_INTR_EN_0, 0); - NV_WRITE(NV03_PMC_INTR_0, 0xFFFFFFFF); + NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF); /* Disable/Clear PGRAPH interrupts */ if (dev_priv->card_type<NV_40) NV_WRITE(NV03_PGRAPH_INTR_EN, 0); @@ -78,7 +78,7 @@ void nouveau_irq_postinstall(drm_device_t *dev) NV_PFIFO_INTR_SEMAPHORE | NV_PFIFO_INTR_ACQUIRE_TIMEOUT ); - NV_WRITE(NV03_PMC_INTR_0, 0xFFFFFFFF); + NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF); /* Enable PGRAPH interrupts */ if (dev_priv->card_type<NV_40) @@ -136,7 +136,7 @@ static void nouveau_fifo_irq_handler(drm_device_t *dev) uint32_t status, chmode, chstat, channel; drm_nouveau_private_t *dev_priv = dev->dev_private; - status = NV_READ(NV03_PMC_INTR_0); + status = NV_READ(NV03_PFIFO_INTR_0); if (!status) return; chmode = NV_READ(NV04_PFIFO_MODE); @@ -166,14 +166,14 @@ static void nouveau_fifo_irq_handler(drm_device_t *dev) ); status &= ~NV_PFIFO_INTR_CACHE_ERROR; - NV_WRITE(NV03_PMC_INTR_0, NV_PFIFO_INTR_CACHE_ERROR); + NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR); } if (status & NV_PFIFO_INTR_DMA_PUSHER) { DRM_INFO("NV: PFIFO DMA pusher interrupt\n"); status &= ~NV_PFIFO_INTR_DMA_PUSHER; - NV_WRITE(NV03_PMC_INTR_0, NV_PFIFO_INTR_DMA_PUSHER); + NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_DMA_PUSHER); NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000); if (NV_READ(NV04_PFIFO_CACHE1_DMA_PUT)!=NV_READ(NV04_PFIFO_CACHE1_DMA_GET)) @@ -186,7 +186,7 @@ static void nouveau_fifo_irq_handler(drm_device_t *dev) if (status) { DRM_INFO("NV: unknown PFIFO interrupt. status=0x%08x\n", status); - NV_WRITE(NV03_PMC_INTR_0, status); + NV_WRITE(NV03_PFIFO_INTR_0, status); } NV_WRITE(NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING); @@ -239,6 +239,30 @@ static void nouveau_nv04_context_switch(drm_device_t *dev) } #endif +static void +nouveau_graph_dump_trap_info(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + uint32_t address; + uint32_t channel; + uint32_t method, subc, data; + + address = NV_READ(0x400704); + data = NV_READ(0x400708); + channel = (address >> 20) & 0x1F; + subc = (address >> 16) & 0x7; + method = address & 0x1FFC; + + DRM_ERROR("NV: nSource: 0x%08x, nStatus: 0x%08x\n", + NV_READ(0x400108), NV_READ(0x400104)); + DRM_ERROR("NV: Channel %d/%d (class 0x%04x) -" + "Method 0x%04x, Data 0x%08x\n", + channel, subc, + NV_READ(0x400160+subc*4) & 0xFFFF, + method, data + ); +} + static void nouveau_pgraph_irq_handler(drm_device_t *dev) { uint32_t status; @@ -256,9 +280,15 @@ static void nouveau_pgraph_irq_handler(drm_device_t *dev) nsource = NV_READ(0x00400108); DRM_DEBUG("nsource:0x%08x\tnstatus:0x%08x\n", nsource, nstatus); - instance = NV_READ(0x00400158); - notify = NV_READ(0x00400150) >> 16; - DRM_DEBUG("instance:0x%08x\tnotify:0x%08x\n", nsource, nstatus); + /* if this wasn't NOTIFICATION_PENDING, dump extra trap info */ + if (nsource & ~(1<<0)) { + nouveau_graph_dump_trap_info(dev); + } else { + instance = NV_READ(0x00400158); + notify = NV_READ(0x00400150) >> 16; + DRM_DEBUG("instance:0x%08x\tnotify:0x%08x\n", + nsource, nstatus); + } status &= ~NV_PGRAPH_INTR_NOTIFY; NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY); @@ -289,9 +319,6 @@ static void nouveau_pgraph_irq_handler(drm_device_t *dev) if (status & NV_PGRAPH_INTR_ERROR) { uint32_t nsource, nstatus, instance; - uint32_t address; - uint32_t channel; - uint32_t method, subc, data; DRM_ERROR("NV: PGRAPH error interrupt\n"); @@ -302,18 +329,7 @@ static void nouveau_pgraph_irq_handler(drm_device_t *dev) instance = NV_READ(0x00400158); DRM_ERROR("instance:0x%08x\n", instance); - address = NV_READ(0x400704); - data = NV_READ(0x400708); - channel = (address >> 20) & 0x1F; - subc = (address >> 16) & 0x7; - method = address & 0x1FFC; - DRM_DEBUG("NV: 0x400704 = 0x%08x\n", address); - DRM_ERROR("NV: Channel %d/%d (class 0x%04x) -" - "Method 0x%04x, Data 0x%08x\n", - channel, subc, - NV_READ(0x400160+subc*4) & 0xFFFF, - method, data - ); + nouveau_graph_dump_trap_info(dev); status &= ~NV_PGRAPH_INTR_ERROR; NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_ERROR); diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c index 3b1f443c..f62d8615 100644 --- a/shared-core/nouveau_mem.c +++ b/shared-core/nouveau_mem.c @@ -335,7 +335,8 @@ int nouveau_mem_init(struct drm_device *dev) if (init_heap(&dev_priv->agp_heap, info.aperture_base, info.aperture_size)) goto no_agp; - dev_priv->agp_phys=info.aperture_base; + dev_priv->agp_phys = info.aperture_base; + dev_priv->agp_available_size = info.aperture_size; } no_agp: @@ -346,6 +347,7 @@ no_agp: * We don't want to allocate this... */ if (dev_priv->card_type >= NV_40) fb_size -= dev_priv->ramin_size; + dev_priv->fb_available_size = fb_size; DRM_DEBUG("Available VRAM: %dKiB\n", fb_size>>10); if (fb_size>256*1024*1024) { diff --git a/shared-core/nouveau_object.c b/shared-core/nouveau_object.c index c11b05eb..b3c4b0e0 100644 --- a/shared-core/nouveau_object.c +++ b/shared-core/nouveau_object.c @@ -97,9 +97,6 @@ nouveau_object_handle_find(drm_device_t *dev, int fifo_num, uint32_t handle) struct nouveau_fifo *fifo = &dev_priv->fifos[fifo_num]; struct nouveau_object *obj = fifo->objs; - if (!handle) - return NULL; - DRM_DEBUG("Looking for handle 0x%08x\n", handle); while (obj) { if (obj->handle == handle) @@ -166,7 +163,7 @@ static int nouveau_hash_table_insert(drm_device_t* dev, int fifo, o_ofs = ofs = nouveau_handle_hash(dev, obj->handle, fifo); - while (NV_READ(ht_base + ofs)) { + while (NV_READ(ht_base + ofs) || NV_READ(ht_base + ofs + 4)) { ofs += 8; if (ofs == ht_end) ofs = ht_base; if (ofs == o_ofs) { @@ -284,17 +281,40 @@ static void nouveau_object_instance_free(drm_device_t *dev, The method below creates a DMA object in instance RAM and returns a handle to it that can be used to set up context objects. */ -struct nouveau_object *nouveau_dma_object_create(drm_device_t* dev, - uint32_t offset, uint32_t size, - int access, uint32_t target) + +struct nouveau_object * +nouveau_dma_object_create(drm_device_t* dev, int class, + uint32_t offset, uint32_t size, + int access, int target) { drm_nouveau_private_t *dev_priv=dev->dev_private; struct nouveau_object *obj; uint32_t frame, adjust; + uint32_t pte_flags = 0; DRM_DEBUG("offset:0x%08x, size:0x%08x, target:%d, access:%d\n", offset, size, target, access); + switch (target) { + case NV_DMA_TARGET_AGP: + offset += dev_priv->agp_phys; + break; + default: + break; + } + + switch (access) { + case NV_DMA_ACCESS_RO: + break; + case NV_DMA_ACCESS_WO: + case NV_DMA_ACCESS_RW: + pte_flags |= (1 << 1); + break; + default: + DRM_ERROR("invalid access mode=%d\n", access); + return NULL; + } + frame = offset & ~0x00000FFF; adjust = offset & 0x00000FFF; @@ -305,21 +325,16 @@ struct nouveau_object *nouveau_dma_object_create(drm_device_t* dev, } obj->engine = 0; - obj->class = 0; + obj->class = class; INSTANCE_WR(obj->instance, 0, ((1<<12) | (1<<13) | (adjust << 20) | (access << 14) | (target << 16) | - 0x3D /* DMA_IN_MEMORY */)); + class)); INSTANCE_WR(obj->instance, 1, size-1); - INSTANCE_WR(obj->instance, 2, - frame | ((access != NV_DMA_ACCESS_RO) ? (1<<1) : 0)); - /* I don't actually know what this is, the DMA objects I see - * in renouveau dumps usually have this as the same as +8 - */ - INSTANCE_WR(obj->instance, 3, - frame | ((access != NV_DMA_ACCESS_RO) ? (1<<1) : 0)); + INSTANCE_WR(obj->instance, 2, frame | pte_flags); + INSTANCE_WR(obj->instance, 3, frame | pte_flags); return obj; } @@ -376,55 +391,13 @@ struct nouveau_object *nouveau_dma_object_create(drm_device_t* dev, entry[5]: set to 0? */ -static struct nouveau_object *nouveau_context_object_create(drm_device_t* dev, - int class, uint32_t flags, - struct nouveau_object *dma0, - struct nouveau_object *dma1, - struct nouveau_object *dma_notifier) +static struct nouveau_object * +nouveau_context_object_create(drm_device_t* dev, int class) { drm_nouveau_private_t *dev_priv=dev->dev_private; struct nouveau_object *obj; - uint32_t d0, d1, dn; - uint32_t flags0,flags1,flags2; - flags0=0;flags1=0;flags2=0; - - if (dev_priv->card_type >= NV_40) { - if (flags & NV_DMA_CONTEXT_FLAGS_PATCH_ROP_AND) - flags0 |= 0x02080000; - else if (flags & NV_DMA_CONTEXT_FLAGS_PATCH_SRCCOPY) - flags0 |= 0x02080000; - if (flags & NV_DMA_CONTEXT_FLAGS_CLIP_ENABLE) - flags0 |= 0x00020000; -#ifdef __BIG_ENDIAN - if (flags & NV_DMA_CONTEXT_FLAGS_MONO) - flags1 |= 0x01000000; - flags2 |= 0x01000000; -#else - if (flags & NV_DMA_CONTEXT_FLAGS_MONO) - flags1 |= 0x02000000; -#endif - } else { - if (flags & NV_DMA_CONTEXT_FLAGS_PATCH_ROP_AND) - flags0 |= 0x01008000; - else if (flags & NV_DMA_CONTEXT_FLAGS_PATCH_SRCCOPY) - flags0 |= 0x01018000; - if (flags & NV_DMA_CONTEXT_FLAGS_CLIP_ENABLE) - flags0 |= 0x00002000; -#ifdef __BIG_ENDIAN - flags0 |= 0x00080000; - if (flags & NV_DMA_CONTEXT_FLAGS_MONO) - flags1 |= 0x00000001; -#else - if (flags & NV_DMA_CONTEXT_FLAGS_MONO) - flags1 |= 0x00000002; -#endif - } - DRM_DEBUG("class=%x, dma0=%08x, dma1=%08x, dman=%08x\n", - class, - dma0 ? dma0->handle : 0, - dma1 ? dma1->handle : 0, - dma_notifier ? dma_notifier->handle : 0); + DRM_DEBUG("class=%x\n", class); obj = nouveau_instance_alloc(dev); if (!obj) { @@ -435,25 +408,37 @@ static struct nouveau_object *nouveau_context_object_create(drm_device_t* dev, obj->engine = 1; obj->class = class; - d0 = dma0 ? nouveau_chip_instance_get(dev, dma0->instance) : 0; - d1 = dma1 ? nouveau_chip_instance_get(dev, dma1->instance) : 0; - dn = dma_notifier ? - nouveau_chip_instance_get(dev, dma_notifier->instance) : 0; - - if (dev_priv->card_type >= NV_40) { - INSTANCE_WR(obj->instance, 0, class | flags0); - INSTANCE_WR(obj->instance, 1, dn | flags1); - INSTANCE_WR(obj->instance, 2, d0 | flags2); - INSTANCE_WR(obj->instance, 3, d1); - INSTANCE_WR(obj->instance, 4, 0x00000000); - INSTANCE_WR(obj->instance, 5, 0x00000000); - INSTANCE_WR(obj->instance, 6, 0x00000000); - INSTANCE_WR(obj->instance, 7, 0x00000000); - } else { - INSTANCE_WR(obj->instance, 0, class | flags0); - INSTANCE_WR(obj->instance, 1, (dn << 16) | flags1); - INSTANCE_WR(obj->instance, 2, d0 | (d1 << 16)); - INSTANCE_WR(obj->instance, 3, 0); + switch (class) { + case NV_CLASS_NULL: + INSTANCE_WR(obj->instance, 0, 0x00001030); + INSTANCE_WR(obj->instance, 1, 0xFFFFFFFF); + INSTANCE_WR(obj->instance, 2, 0x00000000); + INSTANCE_WR(obj->instance, 2, 0x00000000); + break; + default: + if (dev_priv->card_type >= NV_40) { + INSTANCE_WR(obj->instance, 0, obj->class); + INSTANCE_WR(obj->instance, 1, 0x00000000); +#ifdef __BIG_ENDIAN + INSTANCE_WR(obj->instance, 2, 0x01000000); +#else + INSTANCE_WR(obj->instance, 2, 0x00000000); +#endif + INSTANCE_WR(obj->instance, 3, 0x00000000); + INSTANCE_WR(obj->instance, 4, 0x00000000); + INSTANCE_WR(obj->instance, 5, 0x00000000); + INSTANCE_WR(obj->instance, 6, 0x00000000); + INSTANCE_WR(obj->instance, 7, 0x00000000); + } else { +#ifdef __BIG_ENDIAN + INSTANCE_WR(obj->instance, 0, obj->class | 0x00080000); +#else + INSTANCE_WR(obj->instance, 0, obj->class); +#endif + INSTANCE_WR(obj->instance, 1, 0x00000000); + INSTANCE_WR(obj->instance, 2, 0x00000000); + INSTANCE_WR(obj->instance, 3, 0x00000000); + } } return obj; @@ -488,7 +473,7 @@ int nouveau_ioctl_object_init(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_nouveau_object_init_t init; - struct nouveau_object *obj, *dma0, *dma1, *dman; + struct nouveau_object *obj; int fifo; fifo = nouveau_fifo_id_get(dev, filp); @@ -506,30 +491,11 @@ int nouveau_ioctl_object_init(DRM_IOCTL_ARGS) return DRM_ERR(EINVAL); } - dma0 = nouveau_object_handle_find(dev, fifo, init.dma0); - if (init.dma0 && !dma0) { - DRM_ERROR("context dma0 - invalid handle 0x%08x\n", init.dma0); - return DRM_ERR(EINVAL); - } - dma1 = nouveau_object_handle_find(dev, fifo, init.dma1); - if (init.dma1 && !dma1) { - DRM_ERROR("context dma1 - invalid handle 0x%08x\n", init.dma0); - return DRM_ERR(EINVAL); - } - dman = nouveau_object_handle_find(dev, fifo, init.dma_notifier); - if (init.dma_notifier && !dman) { - DRM_ERROR("context dman - invalid handle 0x%08x\n", - init.dma_notifier); - return DRM_ERR(EINVAL); - } - - obj = nouveau_context_object_create(dev, init.class, init.flags, - dma0, dma1, dman); + obj = nouveau_context_object_create(dev, init.class); if (!obj) return DRM_ERR(ENOMEM); obj->handle = init.handle; - if (nouveau_hash_table_insert(dev, fifo, obj)) { nouveau_object_free(dev, fifo, obj); return DRM_ERR(ENOMEM); @@ -540,6 +506,64 @@ int nouveau_ioctl_object_init(DRM_IOCTL_ARGS) return 0; } +static int +nouveau_dma_object_check_access(drm_device_t *dev, + drm_nouveau_dma_object_init_t *init) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + uint64_t limit; + + /* Check for known DMA object classes */ + switch (init->class) { + case NV_CLASS_DMA_IN_MEMORY: + case NV_CLASS_DMA_FROM_MEMORY: + case NV_CLASS_DMA_TO_MEMORY: + break; + default: + DRM_ERROR("invalid class = 0x%x\n", init->class); + return DRM_ERR(EPERM); + } + + /* Check access mode, and translate to NV_DMA_ACCESS_* */ + switch (init->access) { + case NOUVEAU_MEM_ACCESS_RO: + init->access = NV_DMA_ACCESS_RO; + break; + case NOUVEAU_MEM_ACCESS_WO: + init->access = NV_DMA_ACCESS_WO; + break; + case NOUVEAU_MEM_ACCESS_RW: + init->access = NV_DMA_ACCESS_RW; + break; + default: + DRM_ERROR("invalid access mode = %d\n", init->access); + return DRM_ERR(EPERM); + } + + /* Check that request is within the allowed limits of "target" */ + switch (init->target) { + case NOUVEAU_MEM_FB: + limit = dev_priv->fb_available_size; + init->target = NV_DMA_TARGET_VIDMEM; + break; + case NOUVEAU_MEM_AGP: + limit = dev_priv->agp_available_size; + init->target = NV_DMA_TARGET_AGP; + break; + default: + DRM_ERROR("invalid target = 0x%x\n", init->target); + return DRM_ERR(EPERM); + } + + if ((init->offset > limit) || (init->offset + init->size) > limit) { + DRM_ERROR("access out of allowed range (%d,0x%08x,0x%08x)\n", + init->target, init->offset, init->size); + return DRM_ERR(EPERM); + } + + return 0; +} + int nouveau_ioctl_dma_object_init(DRM_IOCTL_ARGS) { DRM_DEVICE; @@ -554,14 +578,18 @@ int nouveau_ioctl_dma_object_init(DRM_IOCTL_ARGS) DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_dma_object_init_t __user *) data, sizeof(init)); + if (nouveau_dma_object_check_access(dev, &init)) + return DRM_ERR(EPERM); + if (nouveau_object_handle_find(dev, fifo, init.handle)) { DRM_ERROR("Channel %d: handle 0x%08x already exists\n", fifo, init.handle); return DRM_ERR(EINVAL); } - obj = nouveau_dma_object_create(dev, init.offset, init.size, - init.access, init.target); + obj = nouveau_dma_object_create(dev, init.class, + init.offset, init.size, + init.access, init.target); if (!obj) return DRM_ERR(ENOMEM); diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h index 966600cf..e7ab3804 100644 --- a/shared-core/nouveau_reg.h +++ b/shared-core/nouveau_reg.h @@ -32,12 +32,20 @@ # define NV40_RAMHT_CONTEXT_ENGINE_SHIFT 20 # define NV40_RAMHT_CONTEXT_INSTANCE_SHIFT 0 +/* DMA object defines */ #define NV_DMA_ACCESS_RW 0 #define NV_DMA_ACCESS_RO 1 #define NV_DMA_ACCESS_WO 2 #define NV_DMA_TARGET_VIDMEM 0 +#define NV_DMA_TARGET_PCI 2 #define NV_DMA_TARGET_AGP 3 +/* Some object classes we care about in the drm */ +#define NV_CLASS_DMA_FROM_MEMORY 0x00000002 +#define NV_CLASS_DMA_TO_MEMORY 0x00000003 +#define NV_CLASS_NULL 0x00000030 +#define NV_CLASS_DMA_IN_MEMORY 0x0000003D + #define NV03_FIFO_SIZE 0x8000UL #define NV_MAX_FIFO_NUMBER 32 #define NV03_FIFO_REGS_SIZE 0x10000 @@ -88,8 +96,6 @@ #define NV10_PGRAPH_CTX_CACHE4 0x004001C0 #define NV04_PGRAPH_CTX_CACHE4 0x004001E0 #define NV10_PGRAPH_CTX_CACHE5 0x004001E0 -#define NV40_PGRAPH_UNK220 0x00400220 -# define NV40_PGRAPH_UNK220_FB_INSTANCE 0xFFFFFFFF #define NV03_PGRAPH_ABS_X_RAM 0x00400400 #define NV03_PGRAPH_ABS_Y_RAM 0x00400480 #define NV03_PGRAPH_X_MISC 0x00400500 diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index f1f272e7..e1fc6330 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -181,8 +181,14 @@ int nouveau_ioctl_getparam(DRM_IOCTL_ARGS) case NOUVEAU_GETPARAM_AGP_PHYSICAL: getparam.value=dev_priv->agp_phys; break; + case NOUVEAU_GETPARAM_FB_SIZE: + getparam.value=dev_priv->fb_available_size; + break; + case NOUVEAU_GETPARAM_AGP_SIZE: + getparam.value=dev_priv->agp_available_size; + break; default: - DRM_ERROR("unknown parameter %d\n", getparam.param); + DRM_ERROR("unknown parameter %lld\n", getparam.param); return DRM_ERR(EINVAL); } @@ -207,7 +213,8 @@ int nouveau_ioctl_setparam(DRM_IOCTL_ARGS) case NOUVEAU_MEM_FB: break; default: - DRM_ERROR("invalid CMDBUF_LOCATION value=%d\n", setparam.value); + DRM_ERROR("invalid CMDBUF_LOCATION value=%lld\n", + setparam.value); return DRM_ERR(EINVAL); } dev_priv->config.cmdbuf.location = setparam.value; @@ -216,7 +223,7 @@ int nouveau_ioctl_setparam(DRM_IOCTL_ARGS) dev_priv->config.cmdbuf.size = setparam.value; break; default: - DRM_ERROR("unknown parameter %d\n", setparam.param); + DRM_ERROR("unknown parameter %lld\n", setparam.param); return DRM_ERR(EINVAL); } diff --git a/shared-core/nv40_graph.c b/shared-core/nv40_graph.c index 659767f2..5e0d8d77 100644 --- a/shared-core/nv40_graph.c +++ b/shared-core/nv40_graph.c @@ -924,14 +924,6 @@ nv40_graph_init(drm_device_t *dev) /* No context present currently */ NV_WRITE(0x40032C, 0x00000000); - /* No idea what this is for.. */ - dev_priv->fb_obj = nouveau_dma_object_create(dev, - 0, nouveau_mem_fb_amount(dev), - NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM); - pg0220_inst = nouveau_chip_instance_get(dev, - dev_priv->fb_obj->instance); - NV_WRITE(NV40_PGRAPH_UNK220, pg0220_inst); - return 0; } diff --git a/shared-core/r128_cce.c b/shared-core/r128_cce.c index f9a9eb32..62859d5a 100644 --- a/shared-core/r128_cce.c +++ b/shared-core/r128_cce.c @@ -560,6 +560,7 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init) if (dev_priv->is_pci) { #endif dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; + dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE; dev_priv->gart_info.addr = NULL; dev_priv->gart_info.bus_addr = 0; dev_priv->gart_info.is_pcie = 0; diff --git a/shared-core/r128_drv.h b/shared-core/r128_drv.h index f1efb49d..90868356 100644 --- a/shared-core/r128_drv.h +++ b/shared-core/r128_drv.h @@ -383,6 +383,8 @@ extern long r128_compat_ioctl(struct file *filp, unsigned int cmd, #define R128_PERFORMANCE_BOXES 0 +#define R128_PCIGART_TABLE_SIZE 32768 + #define R128_READ(reg) DRM_READ32( dev_priv->mmio, (reg) ) #define R128_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) ) #define R128_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) ) diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 0fa6535d..e02796e7 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -1623,13 +1623,13 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) #endif { /* if we have an offset set from userspace */ - if (dev_priv->pcigart_offset) { + if (dev_priv->pcigart_offset_set) { dev_priv->gart_info.bus_addr = dev_priv->pcigart_offset + dev_priv->fb_location; dev_priv->gart_info.mapping.offset = dev_priv->gart_info.bus_addr; dev_priv->gart_info.mapping.size = - RADEON_PCIGART_TABLE_SIZE; + dev_priv->gart_info.table_size; drm_core_ioremap(&dev_priv->gart_info.mapping, dev); dev_priv->gart_info.addr = @@ -2230,6 +2230,8 @@ int radeon_driver_firstopen(struct drm_device *dev) drm_local_map_t *map; drm_radeon_private_t *dev_priv = dev->dev_private; + dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; + ret = drm_addmap(dev, drm_get_resource_start(dev, 2), drm_get_resource_len(dev, 2), _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio); diff --git a/shared-core/radeon_drm.h b/shared-core/radeon_drm.h index f5edbc19..e96e7851 100644 --- a/shared-core/radeon_drm.h +++ b/shared-core/radeon_drm.h @@ -708,6 +708,7 @@ typedef struct drm_radeon_setparam { #define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ #define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ +#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 /* PCI GART Table Size */ /* 1.14: Clients can allocate/free a surface */ diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 5c426fe0..3e56af30 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -95,10 +95,11 @@ * 1.24- Add general-purpose packet for manipulating scratch registers (r300) * 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL, * new packet type) + * 1.26- Add support for variable size PCI(E) gart aperture */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 25 +#define DRIVER_MINOR 26 #define DRIVER_PATCHLEVEL 0 /* @@ -282,6 +283,7 @@ typedef struct drm_radeon_private { struct radeon_virt_surface virt_surfaces[2*RADEON_MAX_SURFACES]; unsigned long pcigart_offset; + unsigned int pcigart_offset_set; drm_ati_pcigart_info gart_info; u32 scratch_ages[5]; diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 40b7d6ce..b95549d8 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -3196,10 +3196,16 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS) break; case RADEON_SETPARAM_PCIGART_LOCATION: dev_priv->pcigart_offset = sp.value; + dev_priv->pcigart_offset_set = 1; break; case RADEON_SETPARAM_NEW_MEMMAP: dev_priv->new_memmap = sp.value; break; + case RADEON_SETPARAM_PCIGART_TABLE_SIZE: + dev_priv->gart_info.table_size = sp.value; + if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE) + dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; + break; default: DRM_DEBUG("Invalid parameter %d\n", sp.param); return DRM_ERR(EINVAL); |