diff options
Diffstat (limited to 'shared-core')
| -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 | 54 | ||||
| -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 | 8 | ||||
| -rw-r--r-- | shared-core/nouveau_state.c | 13 | ||||
| -rw-r--r-- | shared-core/nv40_graph.c | 1 | 
9 files changed, 213 insertions, 152 deletions
| 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..f6908492 100644 --- a/shared-core/nouveau_irq.c +++ b/shared-core/nouveau_irq.c @@ -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); @@ -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..95de558b 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 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..082849d9 100644 --- a/shared-core/nv40_graph.c +++ b/shared-core/nv40_graph.c @@ -926,6 +926,7 @@ nv40_graph_init(drm_device_t *dev)  	/* No idea what this is for.. */  	dev_priv->fb_obj = nouveau_dma_object_create(dev, +			NV_CLASS_DMA_IN_MEMORY,  			0, nouveau_mem_fb_amount(dev),  			NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM);  	pg0220_inst = nouveau_chip_instance_get(dev, | 
