diff options
| -rw-r--r-- | shared-core/nouveau_drv.h | 17 | ||||
| -rw-r--r-- | shared-core/nouveau_fifo.c | 280 | ||||
| -rw-r--r-- | shared-core/nouveau_object.c | 42 | ||||
| -rw-r--r-- | shared-core/nouveau_reg.h | 15 | ||||
| -rw-r--r-- | shared-core/nouveau_state.c | 19 | 
5 files changed, 239 insertions, 134 deletions
| diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index f579026a..03c7bd12 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -71,16 +71,14 @@ struct nouveau_fifo  	drm_local_map_t *map;  	/* mapping of the regs controling the fifo */  	drm_local_map_t *regs; +	/* dma object for the command buffer itself */ +	struct nouveau_object *cmdbuf_obj;  	/* objects belonging to this fifo */  	struct nouveau_object *objs;  };  struct nouveau_object_store  { -	int ht_bits; -	int ht_size; -	int ht_base; -  	uint32_t *inst_bmap;  	uint32_t first_instance;  	int      num_instance; @@ -112,18 +110,24 @@ typedef struct drm_nouveau_private {  	drm_local_map_t *mmio;  	drm_local_map_t *fb; +	//TODO: Remove me, I'm bogus :)  	int      cur_fifo;  	struct nouveau_object *fb_obj; -	struct nouveau_object *cmdbuf_obj;  	int               cmdbuf_ch_size;  	struct mem_block* cmdbuf_alloc; +	int fifo_alloc_count;  	struct nouveau_fifo fifos[NV_MAX_FIFO_NUMBER];  	struct nouveau_object_store objs;  	/* RAMFC and RAMRO offsets */ +	uint32_t ramht_offset; +	uint32_t ramht_size; +	uint32_t ramht_bits;  	uint32_t ramfc_offset; +	uint32_t ramfc_size;  	uint32_t ramro_offset; +	uint32_t ramro_size;  	struct mem_block *agp_heap;  	struct mem_block *fb_heap; @@ -153,12 +157,13 @@ extern int               nouveau_mem_init(struct drm_device *dev);  extern void              nouveau_mem_close(struct drm_device *dev);  /* nouveau_fifo.c */ +extern int  nouveau_fifo_init(drm_device_t *dev);  extern int  nouveau_fifo_number(drm_device_t *dev);  extern void nouveau_fifo_cleanup(drm_device_t *dev, DRMFILE filp);  extern int  nouveau_fifo_id_get(drm_device_t *dev, DRMFILE filp);  /* nouveau_object.c */ -extern void nouveau_hash_table_init(drm_device_t *dev); +extern int  nouveau_object_init(drm_device_t *dev);  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); diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index cf389647..c662165b 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -53,63 +53,111 @@ int nouveau_fifo_number(drm_device_t* dev)   * voir nv_driver.c : NVPreInit    */ -static void nouveau_fifo_init(drm_device_t* dev) +static int nouveau_fifo_instmem_configure(drm_device_t *dev)  {  	drm_nouveau_private_t *dev_priv = dev->dev_private; -	 -	/* Init PFIFO - This is an exact copy of what's done in the Xorg ddx so far. -	 *              We should be able to figure out what's happening from the -	 *              resources available.. -	 */ +	int i; -	if (dev->irq_enabled) -		nouveau_irq_postinstall(dev); +	/* Clear RAMIN */ +	for (i=0x00710000; i<0x00800000; i++) +		NV_WRITE(i, 0x00000000); -	if (dev_priv->card_type >= NV_40) -		NV_WRITE(NV_PGRAPH_NV40_UNK220, dev_priv->fb_obj->instance >> 4); +	/* FIFO hash table (RAMHT) +	 *   use 4k hash table at RAMIN+0x10000 +	 *   TODO: extend the hash table +	 */ +	dev_priv->ramht_offset = 0x10000; +	dev_priv->ramht_bits   = 9; +	dev_priv->ramht_size   = (1 << dev_priv->ramht_bits); +	NV_WRITE(NV_PFIFO_RAMHT, +			(0x03 << 24) /* search 128 */ |  +			((dev_priv->ramht_bits - 9) << 16) | +			(dev_priv->ramht_offset >> 8) +			); +	DRM_DEBUG("RAMHT offset=0x%x, size=%d\n", +			dev_priv->ramht_offset, +			dev_priv->ramht_size); + +	/* FIFO runout table (RAMRO) - 512k at 0x11200 */ +	dev_priv->ramro_offset = 0x11200; +	dev_priv->ramro_size   = 512; +	NV_WRITE(NV_PFIFO_RAMRO, dev_priv->ramro_offset>>8); +	DRM_DEBUG("RAMRO offset=0x%x, size=%d\n", +			dev_priv->ramro_offset, +			dev_priv->ramro_size); + +	/* FIFO context table (RAMFC) +	 *   NV40  : Not sure exactly how to position RAMFC on some cards, +	 *           0x30002 seems to position it at RAMIN+0x20000 on these +	 *           cards.  RAMFC is 4kb (32 fifos, 128byte entries). +	 *   Others: Position RAMFC at RAMIN+0x11400 +	 */ +	if (dev_priv->card_type >= NV_40) { +		dev_priv->ramfc_offset = 0x20000; +		dev_priv->ramfc_size   = nouveau_fifo_number(dev) * 128; +		NV_WRITE(NV40_PFIFO_RAMFC, 0x30002); +	} else if (dev_priv->card_type >= NV_10) { +		dev_priv->ramfc_offset = 0x11400; +		dev_priv->ramfc_size   = nouveau_fifo_number(dev) * 64; +		NV_WRITE(NV_PFIFO_RAMFC, dev_priv->ramfc_offset>>8); +	} else { +		dev_priv->ramfc_offset = 0x11400; +		dev_priv->ramfc_size   = nouveau_fifo_number(dev) * 32; +		NV_WRITE(NV_PFIFO_RAMFC, dev_priv->ramfc_offset>>8); +	} +	DRM_DEBUG("RAMFC offset=0x%x, size=%d\n", +			dev_priv->ramfc_offset, +			dev_priv->ramfc_size); + +	return 0; +} -	DRM_DEBUG("%s: setting FIFO %d active\n", __func__, dev_priv->cur_fifo); +int nouveau_fifo_init(drm_device_t *dev) +{ +	drm_nouveau_private_t *dev_priv = dev->dev_private; +	int ret; -	// FIXME remove all the stuff that's done in nouveau_fifo_alloc  	NV_WRITE(NV_PFIFO_CACHES, 0x00000000); + +	ret = nouveau_fifo_instmem_configure(dev); +	if (ret) { +		DRM_ERROR("Failed to configure instance memory\n"); +		return ret; +	} + +	/* FIXME remove all the stuff that's done in nouveau_fifo_alloc */ + +	DRM_DEBUG("Setting defaults for remaining PFIFO regs\n"); + +	/* All channels into PIO mode */  	NV_WRITE(NV_PFIFO_MODE, 0x00000000);  	NV_WRITE(NV_PFIFO_CACH1_PSH0, 0x00000000);  	NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000000); -	if (dev_priv->card_type >= NV_40) -		NV_WRITE(NV_PFIFO_CACH1_PSH1, 0x00010000|dev_priv->cur_fifo); -	else -		NV_WRITE(NV_PFIFO_CACH1_PSH1, 0x00000100|dev_priv->cur_fifo); -	NV_WRITE(NV_PFIFO_CACH1_DMAP, dev_priv->cur_fifo * dev_priv->cmdbuf_ch_size); -	NV_WRITE(NV_PFIFO_CACH1_DMAG, dev_priv->cur_fifo * dev_priv->cmdbuf_ch_size); -	NV_WRITE(NV_PFIFO_CACH1_DMAI, dev_priv->cmdbuf_obj->instance >> 4); +	/* Channel 0 active, PIO mode */ +	NV_WRITE(NV_PFIFO_CACH1_PSH1, 0x00000000); +	/* PUT and GET to 0 */ +	NV_WRITE(NV_PFIFO_CACH1_DMAP, 0x00000000); +	NV_WRITE(NV_PFIFO_CACH1_DMAP, 0x00000000); +	/* No cmdbuf object */ +	NV_WRITE(NV_PFIFO_CACH1_DMAI, 0x00000000);  	NV_WRITE(NV_PFIFO_CACH0_PSH0, 0x00000000);  	NV_WRITE(NV_PFIFO_CACH0_PUL0, 0x00000000); -	NV_WRITE(NV_PFIFO_SIZE , 0x0000FFFF); +	NV_WRITE(NV_PFIFO_SIZE, 0x0000FFFF);  	NV_WRITE(NV_PFIFO_CACH1_HASH, 0x0000FFFF); -	NV_WRITE(NV_PFIFO_RAMHT, -			(0x03 << 24) /* search 128 */ |  -			((dev_priv->objs.ht_bits - 9) << 16) | -			(dev_priv->objs.ht_base >> 8) -			); -	/* RAMFC needs to be at RAMIN+0x20000 on NV40, I currently don't know -	 * how to move it.. -	 */ -	dev_priv->ramfc_offset=0x20000; -	if (dev_priv->card_type < NV_40) -		NV_WRITE(NV_PFIFO_RAMFC, dev_priv->ramfc_offset>>8); /* RAMIN+0x11000 0.5k */ -	else -		NV_WRITE(0x2220, 0x30002); -	dev_priv->ramro_offset=0x11200; -	NV_WRITE(NV_PFIFO_RAMRO, dev_priv->ramro_offset>>8); /* RAMIN+0x11200 0.5k */  	NV_WRITE(NV_PFIFO_CACH0_PUL1, 0x00000001);  	NV_WRITE(NV_PFIFO_CACH1_DMAC, 0x00000000);  	NV_WRITE(NV_PFIFO_CACH1_DMAS, 0x00000000);  	NV_WRITE(NV_PFIFO_CACH1_ENG, 0x00000000);  #ifdef __BIG_ENDIAN -		NV_WRITE(NV_PFIFO_CACH1_DMAF, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES|NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES|NV_PFIFO_CACH1_DMAF_MAX_REQS_4|NV_PFIFO_CACH1_BIG_ENDIAN); +	NV_WRITE(NV_PFIFO_CACH1_DMAF, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES | +				      NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | +				      NV_PFIFO_CACH1_DMAF_MAX_REQS_4 | +				      NV_PFIFO_CACH1_BIG_ENDIAN);  #else -		NV_WRITE(NV_PFIFO_CACH1_DMAF, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES|NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES|NV_PFIFO_CACH1_DMAF_MAX_REQS_4); +	NV_WRITE(NV_PFIFO_CACH1_DMAF, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES | +				      NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES |  +				      NV_PFIFO_CACH1_DMAF_MAX_REQS_4);  #endif  	NV_WRITE(NV_PFIFO_CACH1_DMAPSH, 0x00000001);  	NV_WRITE(NV_PFIFO_CACH1_PSH0, 0x00000001); @@ -126,11 +174,7 @@ static void nouveau_fifo_init(drm_device_t* dev)  	NV_WRITE(NV_PFIFO_DMA_TIMESLICE, 0x001fffff);  	NV_WRITE(NV_PFIFO_CACHES, 0x00000001); -	DRM_DEBUG("%s: CACHE1 GET/PUT readback %d/%d\n", __func__, -			NV_READ(NV_PFIFO_CACH1_DMAG), -			NV_READ(NV_PFIFO_CACH1_DMAP)); - -	DRM_INFO("%s: OK\n", __func__); +	return 0;  }  static int nouveau_dma_init(struct drm_device *dev) @@ -140,14 +184,6 @@ static int nouveau_dma_init(struct drm_device *dev)  	struct mem_block *cb;  	int cb_min_size = nouveau_fifo_number(dev) * max(NV03_FIFO_SIZE,PAGE_SIZE); -	/* XXX this should be done earlier on init */ -	nouveau_hash_table_init(dev); - -	if (dev_priv->card_type >= NV_40) -		dev_priv->fb_obj = nouveau_dma_object_create(dev, -				0, nouveau_mem_fb_amount(dev), -				NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM); -  	/* Defaults for unconfigured values */  	if (!config->cmdbuf.location)  		config->cmdbuf.location = NOUVEAU_MEM_FB; @@ -168,17 +204,9 @@ static int nouveau_dma_init(struct drm_device *dev)  		return DRM_ERR(ENOMEM);  	} -	if (config->cmdbuf.location == NOUVEAU_MEM_AGP) -		dev_priv->cmdbuf_obj = nouveau_dma_object_create(dev, -				cb->start, cb->size, NV_DMA_ACCESS_RO, NV_DMA_TARGET_AGP); -	else -		dev_priv->cmdbuf_obj = nouveau_dma_object_create(dev, -				cb->start - drm_get_resource_start(dev, 1), -				cb->size, NV_DMA_ACCESS_RO, NV_DMA_TARGET_VIDMEM);  	dev_priv->cmdbuf_ch_size = (uint32_t)cb->size / nouveau_fifo_number(dev);  	dev_priv->cmdbuf_alloc = cb; -	nouveau_fifo_init(dev);  	DRM_INFO("DMA command buffer is %dKiB at 0x%08x(%s)\n",  			(uint32_t)cb->size>>10, (uint32_t)cb->start,  			config->cmdbuf.location == NOUVEAU_MEM_FB ? "VRAM" : "AGP"); @@ -191,23 +219,11 @@ static void nouveau_context_init(drm_device_t *dev,  				 drm_nouveau_fifo_alloc_t *init)  {  	drm_nouveau_private_t *dev_priv = dev->dev_private; -	uint32_t ctx_addr,ctx_size; +	struct nouveau_object *cb_obj; +	uint32_t ctx_addr, ctx_size = 32;  	int i; -	switch(dev_priv->card_type) -	{ -		case NV_03: -		case NV_04: -		case NV_05: -			ctx_size=32; -			break; -		case NV_10: -		case NV_20: -		case NV_30: -		default: -			ctx_size=64; -			break; -	} +	cb_obj = dev_priv->fifos[init->channel].cmdbuf_obj;  	ctx_addr=NV_RAMIN+dev_priv->ramfc_offset+init->channel*ctx_size;  	// clear the fifo context @@ -216,36 +232,83 @@ static void nouveau_context_init(drm_device_t *dev,  	NV_WRITE(ctx_addr,init->put_base);  	NV_WRITE(ctx_addr+4,init->put_base); -	if (dev_priv->card_type <= NV_05) -	{ -		// that's what is done in nvosdk, but that part of the code is buggy so... -		NV_WRITE(ctx_addr+8,dev_priv->cmdbuf_obj->instance >> 4); +	// that's what is done in nvosdk, but that part of the code is buggy so... +	NV_WRITE(ctx_addr+8, cb_obj->instance >> 4);  #ifdef __BIG_ENDIAN -		NV_WRITE(ctx_addr+16,NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES|NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES|NV_PFIFO_CACH1_DMAF_MAX_REQS_4|NV_PFIFO_CACH1_BIG_ENDIAN); +	NV_WRITE(ctx_addr+16,NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES|NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES|NV_PFIFO_CACH1_DMAF_MAX_REQS_4|NV_PFIFO_CACH1_BIG_ENDIAN);  #else -		NV_WRITE(ctx_addr+16,NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES|NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES|NV_PFIFO_CACH1_DMAF_MAX_REQS_4); +	NV_WRITE(ctx_addr+16,NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES|NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES|NV_PFIFO_CACH1_DMAF_MAX_REQS_4);  #endif -	} -	else -	{ -		NV_WRITE(ctx_addr+12,dev_priv->cmdbuf_obj->instance >> 4/*DMA INST/DMA COUNT*/); +} + +#define RAMFC_WR(offset, val) NV_WRITE(fifoctx + NV10_RAMFC_##offset, (val)) +static void nouveau_nv10_context_init(drm_device_t *dev, +				      drm_nouveau_fifo_alloc_t *init) +{ +	drm_nouveau_private_t *dev_priv = dev->dev_private; +	struct nouveau_object *cb_obj; +	uint32_t fifoctx; +	int i; + +	cb_obj  = dev_priv->fifos[init->channel].cmdbuf_obj; +	fifoctx = NV_RAMIN + dev_priv->ramfc_offset + init->channel*64; +	for (i=0;i<64;i+=4) +		NV_WRITE(fifoctx + i, 0); + +	/* Fill entries that are seen filled in dumps of nvidia driver just +	 * after channel's is put into DMA mode +	 */ +	RAMFC_WR(DMA_PUT       , init->put_base); +	RAMFC_WR(DMA_GET       , init->put_base); +	RAMFC_WR(DMA_INSTANCE  , cb_obj->instance >> 4);  #ifdef __BIG_ENDIAN -		NV_WRITE(ctx_addr+20,NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES|NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES|NV_PFIFO_CACH1_DMAF_MAX_REQS_4|NV_PFIFO_CACH1_BIG_ENDIAN); +		RAMFC_WR(DMA_FETCH, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES |  +				    NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | +				    NV_PFIFO_CACH1_DMAF_MAX_REQS_4     | +				    NV_PFIFO_CACH1_BIG_ENDIAN);  #else -		NV_WRITE(ctx_addr+20,NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES|NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES|NV_PFIFO_CACH1_DMAF_MAX_REQS_4); +		RAMFC_WR(DMA_FETCH, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES |  +				    NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | +				    NV_PFIFO_CACH1_DMAF_MAX_REQS_4);  #endif -	} +	RAMFC_WR(DMA_SUBROUTINE, init->put_base); +} +static void nouveau_nv10_context_save(drm_device_t *dev) +{ +	drm_nouveau_private_t *dev_priv = dev->dev_private; +	uint32_t fifoctx; +	int channel; + +	channel = NV_READ(NV_PFIFO_CACH1_PSH1) & (nouveau_fifo_number(dev)-1); +	fifoctx = NV_RAMIN + dev_priv->ramfc_offset + channel*64; + +	RAMFC_WR(DMA_PUT          , NV_READ(NV_PFIFO_CACH1_DMAP)); +	RAMFC_WR(DMA_GET          , NV_READ(NV_PFIFO_CACH1_DMAG)); +	RAMFC_WR(REF_CNT          , NV_READ(NV_PFIFO_CACH1_REF_CNT)); +	RAMFC_WR(DMA_INSTANCE     , NV_READ(NV_PFIFO_CACH1_DMAI)); +	RAMFC_WR(DMA_STATE        , NV_READ(NV_PFIFO_CACH1_DMAS)); +	RAMFC_WR(DMA_FETCH        , NV_READ(NV_PFIFO_CACH1_DMAF)); +	RAMFC_WR(ENGINE           , NV_READ(NV_PFIFO_CACH1_ENG)); +	RAMFC_WR(PULL1_ENGINE     , NV_READ(NV_PFIFO_CACH1_PUL1)); +	RAMFC_WR(ACQUIRE_VALUE    , NV_READ(NV_PFIFO_CACH1_ACQUIRE_VALUE)); +	RAMFC_WR(ACQUIRE_TIMESTAMP, NV_READ(NV_PFIFO_CACH1_ACQUIRE_TIMESTAMP)); +	RAMFC_WR(ACQUIRE_TIMEOUT  , NV_READ(NV_PFIFO_CACH1_ACQUIRE_TIMEOUT)); +	RAMFC_WR(SEMAPHORE        , NV_READ(NV_PFIFO_CACH1_SEMAPHORE)); +	RAMFC_WR(DMA_SUBROUTINE   , NV_READ(NV_PFIFO_CACH1_DMAG));  } +#undef RAMFC_WR  #define RAMFC_WR(offset, val) NV_WRITE(fifoctx + NV40_RAMFC_##offset, (val))  static void nouveau_nv40_context_init(drm_device_t *dev,  				      drm_nouveau_fifo_alloc_t *init)  {  	drm_nouveau_private_t *dev_priv = dev->dev_private; +	struct nouveau_object *cb_obj;  	uint32_t fifoctx;  	int i; +	cb_obj  = dev_priv->fifos[init->channel].cmdbuf_obj;  	fifoctx = NV_RAMIN + dev_priv->ramfc_offset + init->channel*128;  	for (i=0;i<128;i+=4)  		NV_WRITE(fifoctx + i, 0); @@ -255,7 +318,7 @@ static void nouveau_nv40_context_init(drm_device_t *dev,  	 */  	RAMFC_WR(DMA_PUT       , init->put_base);  	RAMFC_WR(DMA_GET       , init->put_base); -	RAMFC_WR(DMA_INSTANCE  , dev_priv->cmdbuf_obj->instance >> 4); +	RAMFC_WR(DMA_INSTANCE  , cb_obj->instance >> 4);  	RAMFC_WR(DMA_FETCH     , 0x30086078);  	RAMFC_WR(DMA_SUBROUTINE, init->put_base);  	RAMFC_WR(GRCTX_INSTANCE, 0); /* XXX */ @@ -297,6 +360,7 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init,  	int i;  	int ret;  	drm_nouveau_private_t *dev_priv = dev->dev_private; +	struct nouveau_object *cb_obj;  	/* Init cmdbuf on first FIFO init, this is delayed until now to  	 * give the ddx a chance to configure the cmdbuf with SETPARAM @@ -324,6 +388,23 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init,  	if (i==nouveau_fifo_number(dev))  		return DRM_ERR(EINVAL); +	/* allocate a dma object for the command buffer */ +	if (dev_priv->cmdbuf_alloc->flags & NOUVEAU_MEM_AGP) { +		cb_obj = nouveau_dma_object_create(dev, +				dev_priv->cmdbuf_alloc->start, +				dev_priv->cmdbuf_alloc->size, +				NV_DMA_ACCESS_RO, +				NV_DMA_TARGET_AGP); +	} else { +		cb_obj = nouveau_dma_object_create(dev, +				dev_priv->cmdbuf_alloc->start - +					drm_get_resource_start(dev, 1), +				dev_priv->cmdbuf_alloc->size, +				NV_DMA_ACCESS_RO, +				NV_DMA_TARGET_VIDMEM); +	} +	dev_priv->fifos[i].cmdbuf_obj = cb_obj; +  	/* that fifo is used */  	dev_priv->fifos[i].used=1;  	dev_priv->fifos[i].filp=filp; @@ -340,16 +421,20 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init,  	NV_WRITE(NV_PFIFO_CACH1_PSH0, 0x00000000);  	NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000000); -	if (dev_priv->card_type < NV_40) +	/* Save current channel's state to it's RAMFC entry. +	 * +	 * Then, construct inital RAMFC for new channel, I'm not entirely +	 * sure this is needed if we activate the channel immediately. +	 * My understanding is that the GPU will fill RAMFC itself when +	 * it switches away from the channel +	 */ +	if (dev_priv->card_type < NV_10) {  		nouveau_context_init(dev, init); -	else { -		/* Save current channel's state to it's RAMFC entry */ +	} else if (dev_priv->card_type < NV_40) { +		nouveau_nv10_context_save(dev); +		nouveau_nv10_context_init(dev, init); +	} else {  		nouveau_nv40_context_save(dev); -		/* Construct inital RAMFC for new channel, I'm not entirely -		 * sure this is needed if we activate the channel immediately. -		 * My understanding is that the GPU will fill RAMFC itself -		 * when it switches away from the channel -		 */  		nouveau_nv40_context_init(dev, init);  	} @@ -368,7 +453,7 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init,  	NV_WRITE(NV_PFIFO_CACH1_DMAP, init->put_base);  	NV_WRITE(NV_PFIFO_CACH1_DMAG, init->put_base); -	NV_WRITE(NV_PFIFO_CACH1_DMAI, dev_priv->cmdbuf_obj->instance >> 4); +	NV_WRITE(NV_PFIFO_CACH1_DMAI, cb_obj->instance >> 4);  	NV_WRITE(NV_PFIFO_SIZE , 0x0000FFFF);  	NV_WRITE(NV_PFIFO_CACH1_HASH, 0x0000FFFF); @@ -409,6 +494,7 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init,  	/* FIFO has no objects yet */  	dev_priv->fifos[init->channel].objs = NULL; +	dev_priv->fifo_alloc_count++;  	DRM_INFO("%s: initialised FIFO %d\n", __func__, init->channel);  	return 0; @@ -438,6 +524,8 @@ void nouveau_fifo_free(drm_device_t* dev,int n)  	/* reenable the fifo caches */  	NV_WRITE(NV_PFIFO_CACHES, 0x00000001); + +	dev_priv->fifo_alloc_count--;  }  /* cleanups all the fifos from filp */ diff --git a/shared-core/nouveau_object.c b/shared-core/nouveau_object.c index 935297fa..abd8bec5 100644 --- a/shared-core/nouveau_object.c +++ b/shared-core/nouveau_object.c @@ -132,15 +132,14 @@ static uint32_t nouveau_handle_hash(drm_device_t* dev, uint32_t handle,  				    int fifo)  {  	drm_nouveau_private_t *dev_priv=dev->dev_private; -	struct nouveau_object_store *objs=&dev_priv->objs;  	uint32_t hash = 0;  	int i; -	for (i=32;i>0;i-=objs->ht_bits) { -		hash ^= (handle & ((1 << objs->ht_bits) - 1)); -		handle >>= objs->ht_bits; +	for (i=32;i>0;i-=dev_priv->ramht_bits) { +		hash ^= (handle & ((1 << dev_priv->ramht_bits) - 1)); +		handle >>= dev_priv->ramht_bits;  	} -	hash ^= fifo << (objs->ht_bits - 4); +	hash ^= fifo << (dev_priv->ramht_bits - 4);  	return hash << 3;  } @@ -148,9 +147,8 @@ static int nouveau_hash_table_insert(drm_device_t* dev, int fifo,  				     struct nouveau_object *obj)  {  	drm_nouveau_private_t *dev_priv=dev->dev_private; -	struct nouveau_object_store *objs=&dev_priv->objs; -	int ht_base = NV_RAMIN + objs->ht_base; -	int ht_end  = ht_base + objs->ht_size; +	int ht_base = NV_RAMIN + dev_priv->ramht_offset; +	int ht_end  = ht_base + dev_priv->ramht_size;  	int o_ofs, ofs;  	o_ofs = ofs = nouveau_handle_hash(dev, obj->handle, fifo); @@ -277,38 +275,18 @@ static void nouveau_object_instance_free(drm_device_t *dev,  	objs->free_instance++;  } -/* Where is the hash table located: - -   Base address and size can be calculated from this register: - -   ht_base = 0x1000 *  GetBitField (pNv->PFIFO[0x0210/4],8:4); -   ht_size = 0x1000 << GetBitField (pNv->PFIFO[0x0210/4],17:16); - -   and the hash table will be located between address PRAMIN + ht_base and -   PRAMIN + ht_base + ht_size.	Each hash table entry has two longwords. -*/ -void nouveau_hash_table_init(drm_device_t* dev) +int nouveau_object_init(drm_device_t* dev)  {  	drm_nouveau_private_t *dev_priv=dev->dev_private; -	int i; - -	dev_priv->objs.ht_bits = 9; -	dev_priv->objs.ht_base = 0x10000; -	dev_priv->objs.ht_size = (1 << dev_priv->objs.ht_bits); -	dev_priv->objs.first_instance = 0x13000; +	dev_priv->objs.first_instance = +		dev_priv->ramfc_offset +dev_priv->ramfc_size;  	dev_priv->objs.free_instance  = 1024; /*FIXME*/  	dev_priv->objs.num_instance   = 1024; /*FIXME*/  	dev_priv->objs.inst_bmap = drm_calloc  	    (1, dev_priv->objs.num_instance/32, DRM_MEM_DRIVER); -	/* clear all of RAMIN -	 * NOTE: except the bottom 0x10000 bytes, the binary driver doesn't -	 *       like this and will die either sometime during init, or during -	 *       shutdown - leaving the screen in an unusable state... -	 */ -	for (i=0x00710000; i<0x00800000; i+=4) -		NV_WRITE(i, 0x00000000); +	return 0;  }  /* diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h index 868a0678..fe42f986 100644 --- a/shared-core/nouveau_reg.h +++ b/shared-core/nouveau_reg.h @@ -85,6 +85,7 @@  #define NV_PFIFO_RAMHT                                     0x00002210  #define NV_PFIFO_RAMFC                                     0x00002214  #define NV_PFIFO_RAMRO                                     0x00002218 +#define NV40_PFIFO_RAMFC                                   0x00002220  #define NV_PFIFO_CACHES                                    0x00002500  #define NV_PFIFO_MODE                                      0x00002504  #define NV_PFIFO_DMA                                       0x00002508 @@ -192,6 +193,20 @@  #define NV03_FIFO_CMD_REWIND                               (NV03_FIFO_CMD_JUMP | (0 & NV03_FIFO_CMD_JUMP_OFFSET_MASK))  /* RAMFC offsets */ +#define NV10_RAMFC_DMA_PUT                                       0x00 +#define NV10_RAMFC_DMA_GET                                       0x04 +#define NV10_RAMFC_REF_CNT                                       0x08 +#define NV10_RAMFC_DMA_INSTANCE                                  0x0C +#define NV10_RAMFC_DMA_STATE                                     0x10 +#define NV10_RAMFC_DMA_FETCH                                     0x14 +#define NV10_RAMFC_ENGINE                                        0x18 +#define NV10_RAMFC_PULL1_ENGINE                                  0x1C +#define NV10_RAMFC_ACQUIRE_VALUE                                 0x20 +#define NV10_RAMFC_ACQUIRE_TIMESTAMP                             0x24 +#define NV10_RAMFC_ACQUIRE_TIMEOUT                               0x28 +#define NV10_RAMFC_SEMAPHORE                                     0x2C +#define NV10_RAMFC_DMA_SUBROUTINE                                0x30 +  #define NV40_RAMFC_DMA_PUT                                       0x00  #define NV40_RAMFC_DMA_GET                                       0x04  #define NV40_RAMFC_REF_CNT                                       0x08 diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index 1901f08c..b05442fb 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -64,6 +64,25 @@ int nouveau_firstopen(struct drm_device *dev)  	DRM_INFO("%lld MB of video ram detected\n",nouveau_mem_fb_amount(dev)>>20); +	/* Clear RAMIN +	 * Determine locations for RAMHT/FC/RO +	 * Initialise PFIFO +	 */ +	ret = nouveau_fifo_init(dev); +	if (ret) return ret; +	/* Initialise instance memory allocation */ +	ret = nouveau_object_init(dev); +	if (ret) return ret; + +	/* FIXME: doesn't belong here, and have no idea what it's for.. */ +	if (dev_priv->card_type >= NV_40) { +		dev_priv->fb_obj = nouveau_dma_object_create(dev, +				0, nouveau_mem_fb_amount(dev), +				NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM); + +		NV_WRITE(NV_PGRAPH_NV40_UNK220, dev_priv->fb_obj->instance >> 4); +	} +  	return 0;  } | 
