From fef9b30a2b437c0103c33443566604027529b91d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 27 Aug 2006 08:55:02 +1000 Subject: initial import of nouveau code from nouveau CVS --- shared-core/nouveau_fifo.c | 270 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 shared-core/nouveau_fifo.c (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c new file mode 100644 index 00000000..18ad7c5f --- /dev/null +++ b/shared-core/nouveau_fifo.c @@ -0,0 +1,270 @@ +/* + * Copyright 2005-2006 Stephane Marchesin + * 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. + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + + +/* returns the number of hw fifos */ +int nouveau_fifo_number(drm_device_t* dev) +{ + drm_nouveau_private_t *dev_priv=dev->dev_private; + switch(dev_priv->card_type) + { + case NV_03: + return 8; + case NV_04: + case NV_05: + return 16; + default: + return 32; + } +} + +/* setup the fifo enable register */ +static void nouveau_fifo_enable(drm_device_t* dev) +{ + int i; + unsigned enable_val=0; + drm_nouveau_private_t *dev_priv = dev->dev_private; + + for(i=31;i>=0;i--) + { + enable_val<<=1; + if (dev_priv->fifos[i].used) + enable_val|=1; + } + DRM_DEBUG("enable_val=0x%08x\n", enable_val); + NV_WRITE(NV03_FIFO_ENABLE,enable_val); +} + +/*********************************** + * functions doing the actual work + ***********************************/ + +/* voir nv_xaa.c : NVResetGraphics + * mémoire mappée par nv_driver.c : NVMapMem + * voir nv_driver.c : NVPreInit + */ + +/* initializes a fifo */ +static int nouveau_fifo_init(drm_device_t* dev,drm_nouveau_fifo_init_t* init, DRMFILE filp) +{ + int i; + int ret; + drm_nouveau_private_t *dev_priv = dev->dev_private; + + /* + * Alright, here is the full story + * Nvidia cards have multiple hw fifo contexts (praise them for that, + * no complicated crash-prone context switches) + * X always uses context 0 (0x00800000) + * We allocate a new context for each app and let it write to it directly + * (woo, full userspace command submission !) + * When there are no more contexts, you lost + */ + for(i=0;ififos[i].used==0) + { + dev_priv->fifos[i].used=1; + break; + } + + /* no more fifos. you lost. */ + if (i==nouveau_fifo_number(dev)) + return DRM_ERR(EINVAL); + + /* that fifo is used */ + dev_priv->fifos[i].used=1; + dev_priv->fifos[i].filp=filp; + + /* enable the fifo */ + nouveau_fifo_enable(dev); + + /* make the fifo available to user space */ + init->channel = i; + init->put_base = i*dev_priv->cmdbuf_ch_size; + + NV_WRITE(NV03_FIFO_REGS_DMAPUT(i), init->put_base); + NV_WRITE(NV03_FIFO_REGS_DMAGET(i), init->put_base); + + /* first, the fifo control regs */ + init->ctrl = dev_priv->mmio->offset + NV03_FIFO_REGS(i); + init->ctrl_size = NV03_FIFO_REGS_SIZE; + ret = drm_addmap(dev, init->ctrl, init->ctrl_size, _DRM_REGISTERS, + 0, &dev_priv->fifos[i].regs); + if (ret != 0) + return ret; + + /* then, the fifo itself */ + init->cmdbuf = dev_priv->cmdbuf_base; + init->cmdbuf += init->channel * dev_priv->cmdbuf_ch_size; + init->cmdbuf_size = dev_priv->cmdbuf_ch_size; + ret = drm_addmap(dev, init->cmdbuf, init->cmdbuf_size, _DRM_REGISTERS, + 0, &dev_priv->fifos[i].map); + if (ret != 0) + return ret; + + /* FIFO has no objects yet */ + dev_priv->fifos[i].objs = NULL; + + DRM_DEBUG("%s: initialised FIFO %d\n", __func__, i); + dev_priv->cur_fifo = i; + return 0; +} +static void nouveau_pfifo_init(drm_device_t* dev); + +/* cleanups all the fifos from filp */ +void nouveau_fifo_cleanup(drm_device_t * dev, DRMFILE filp) +{ + int i; + drm_nouveau_private_t *dev_priv = dev->dev_private; + + DRM_DEBUG("clearing FIFO enables from filp\n"); + for(i=0;ififos[i].filp==filp) + dev_priv->fifos[i].used=0; + + if (dev_priv->cur_fifo == i) { + DRM_DEBUG("%s: cur_fifo is no longer owned.\n", __func__); + for (i=0;ififos[i].used) break; + if (i==nouveau_fifo_number(dev)) + i=0; + DRM_DEBUG("%s: new cur_fifo is %d\n", __func__, i); + dev_priv->cur_fifo = i; + } + + nouveau_pfifo_init(dev); +// nouveau_fifo_enable(dev); +} + +int nouveau_fifo_id_get(drm_device_t* dev, DRMFILE filp) +{ + drm_nouveau_private_t *dev_priv=dev->dev_private; + int i; + + for(i=0;ififos[i].filp == filp) + return i; + return -1; +} + +static void nouveau_pfifo_init(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.. + */ + + if (dev->irq_enabled) + nouveau_irq_postinstall(dev); + + if (dev_priv->card_type >= NV_40) + NV_WRITE(NV_PGRAPH_NV40_UNK220, dev_priv->fb_obj->instance >> 4); + + DRM_DEBUG("%s: setting FIFO %d active\n", __func__, dev_priv->cur_fifo); + + NV_WRITE(NV_PFIFO_CACHES, 0x00000000); + nouveau_fifo_enable(dev); + + 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); + NV_WRITE(NV_PFIFO_CACH0_PSH0, 0x00000000); + NV_WRITE(NV_PFIFO_CACH0_PUL0, 0x00000000); + NV_WRITE(NV_PFIFO_SIZE , 0x0000FFFF); + NV_WRITE(NV_PFIFO_CACH1_HASH, 0x0000FFFF); + NV_WRITE(NV_PFIFO_CACH0_PUL1, 0x00000001); + NV_WRITE(NV_PFIFO_CACH1_DMAC, 0x00000000); + NV_WRITE(NV_PFIFO_CACH1_ENG, 0x00000000); +#ifdef __BIG_ENDIAN + NV_WRITE(NV_PFIFO_CACH1_DMAF, 0x800F0078); +#else + NV_WRITE(NV_PFIFO_CACH1_DMAF, 0x000F0078); +#endif + NV_WRITE(NV_PFIFO_CACH1_DMAS, 0x00000001); + NV_WRITE(NV_PFIFO_CACH1_PSH0, 0x00000001); + NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001); + NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000001); + + 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)); +} + +/*********************************** + * ioctls wrapping the functions + ***********************************/ + +static int nouveau_ioctl_fifo_init(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_nouveau_fifo_init_t init; + int res; + DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_fifo_init_t __user *) data, sizeof(init)); + + res=nouveau_fifo_init(dev,&init,filp); + if (!res) + DRM_COPY_TO_USER_IOCTL((drm_nouveau_fifo_init_t __user *)data, init, sizeof(init)); + + return res; +} + +static int nouveau_ioctl_fifo_reinit(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + + nouveau_pfifo_init(dev); + return 0; +} + +/*********************************** + * finally, the ioctl table + ***********************************/ + +drm_ioctl_desc_t nouveau_ioctls[] = { + [DRM_IOCTL_NR(DRM_NOUVEAU_FIFO_INIT)] = {nouveau_ioctl_fifo_init, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_NOUVEAU_PFIFO_REINIT)] = {nouveau_ioctl_fifo_reinit, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_NOUVEAU_OBJECT_INIT)] = {nouveau_ioctl_object_init, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_NOUVEAU_DMA_OBJECT_INIT)] = {nouveau_ioctl_dma_object_init, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_NOUVEAU_MEM_ALLOC)] = {nouveau_ioctl_mem_alloc, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_NOUVEAU_MEM_FREE)] = {nouveau_ioctl_mem_free, DRM_AUTH}, +}; + +int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls); + + -- cgit v1.2.3 From 24dddc27549f2b8cf837305ee84dd1ca97df98e7 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 30 Aug 2006 16:55:02 +1000 Subject: Add stub {get,set}param ioctls. --- shared-core/nouveau_fifo.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 18ad7c5f..c0d54b33 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -263,6 +263,8 @@ drm_ioctl_desc_t nouveau_ioctls[] = { [DRM_IOCTL_NR(DRM_NOUVEAU_DMA_OBJECT_INIT)] = {nouveau_ioctl_dma_object_init, DRM_AUTH}, [DRM_IOCTL_NR(DRM_NOUVEAU_MEM_ALLOC)] = {nouveau_ioctl_mem_alloc, DRM_AUTH}, [DRM_IOCTL_NR(DRM_NOUVEAU_MEM_FREE)] = {nouveau_ioctl_mem_free, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_NOUVEAU_GETPARAM)] = {nouveau_ioctl_getparam, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_NOUVEAU_SETPARAM)] = {nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, }; int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls); -- cgit v1.2.3 From b119966ae65c9ee74096cf0b246bf7703cb58ec4 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 3 Sep 2006 06:36:06 +1000 Subject: Allow cmdbuf location(AGP,VRAM) and size to be configured. --- shared-core/nouveau_fifo.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index c0d54b33..67ee6c71 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -77,6 +77,15 @@ static int nouveau_fifo_init(drm_device_t* dev,drm_nouveau_fifo_init_t* init, DR int ret; drm_nouveau_private_t *dev_priv = dev->dev_private; + /* Init cmdbuf on first FIFO init, this is delayed until now to + * give the ddx a chance to configure the cmdbuf with SETPARAM + */ + if (!dev_priv->cmdbuf_alloc) { + ret = nouveau_dma_init(dev); + if (ret) + return ret; + } + /* * Alright, here is the full story * Nvidia cards have multiple hw fifo contexts (praise them for that, @@ -120,7 +129,7 @@ static int nouveau_fifo_init(drm_device_t* dev,drm_nouveau_fifo_init_t* init, DR return ret; /* then, the fifo itself */ - init->cmdbuf = dev_priv->cmdbuf_base; + init->cmdbuf = dev_priv->cmdbuf_alloc->start; init->cmdbuf += init->channel * dev_priv->cmdbuf_ch_size; init->cmdbuf_size = dev_priv->cmdbuf_ch_size; ret = drm_addmap(dev, init->cmdbuf, init->cmdbuf_size, _DRM_REGISTERS, @@ -157,8 +166,9 @@ void nouveau_fifo_cleanup(drm_device_t * dev, DRMFILE filp) DRM_DEBUG("%s: new cur_fifo is %d\n", __func__, i); dev_priv->cur_fifo = i; } - - nouveau_pfifo_init(dev); + + if (dev_priv->cmdbuf_alloc) + nouveau_pfifo_init(dev); // nouveau_fifo_enable(dev); } -- cgit v1.2.3 From 0ef29768ca909421539c3d8f65bb8e94912fa597 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 7 Sep 2006 23:59:19 +1000 Subject: Fix second start of X server without module reload beforehand, and a couple of other fixes. - Mark the correct RAMIN slots as free (oops) - Remove a VRAM alloc that shouldn't have been there (oops) - Move HT init out of firstopen() and into dma_init() - Setup PFIFO_RAM{HT,FC,RO} in pfifo_init() --- shared-core/nouveau_fifo.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 67ee6c71..ca7ddef6 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -216,6 +216,13 @@ static void nouveau_pfifo_init(drm_device_t* dev) NV_WRITE(NV_PFIFO_CACH0_PUL0, 0x00000000); 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) + ); + NV_WRITE(NV_PFIFO_RAMFC, 0x00000110); /* RAMIN+0x11000 0.5k */ + NV_WRITE(NV_PFIFO_RAMRO, 0x00000112); /* RAMIN+0x11200 0.5k */ NV_WRITE(NV_PFIFO_CACH0_PUL1, 0x00000001); NV_WRITE(NV_PFIFO_CACH1_DMAC, 0x00000000); NV_WRITE(NV_PFIFO_CACH1_ENG, 0x00000000); -- cgit v1.2.3 From dd473411f889cc16af255437d2a61c616bcee695 Mon Sep 17 00:00:00 2001 From: Stephane Marchesin Date: Wed, 11 Oct 2006 00:28:15 +0200 Subject: Context switching work. Added preliminary support for context switches (triggers the interrupts, but hangs after the switch ; something's not quite right yet). Removed the PFIFO_REINIT ioctl. I hope it's that a good idea... Requires the upcoming commit to the DDX. --- shared-core/nouveau_fifo.c | 308 +++++++++++++++++++++++++++++---------------- 1 file changed, 198 insertions(+), 110 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index ca7ddef6..de23f96d 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -44,23 +44,6 @@ int nouveau_fifo_number(drm_device_t* dev) } } -/* setup the fifo enable register */ -static void nouveau_fifo_enable(drm_device_t* dev) -{ - int i; - unsigned enable_val=0; - drm_nouveau_private_t *dev_priv = dev->dev_private; - - for(i=31;i>=0;i--) - { - enable_val<<=1; - if (dev_priv->fifos[i].used) - enable_val|=1; - } - DRM_DEBUG("enable_val=0x%08x\n", enable_val); - NV_WRITE(NV03_FIFO_ENABLE,enable_val); -} - /*********************************** * functions doing the actual work ***********************************/ @@ -70,12 +53,141 @@ static void nouveau_fifo_enable(drm_device_t* dev) * voir nv_driver.c : NVPreInit */ -/* initializes a fifo */ -static int nouveau_fifo_init(drm_device_t* dev,drm_nouveau_fifo_init_t* init, DRMFILE filp) +static void nouveau_fifo_init(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.. + */ + + if (dev->irq_enabled) + nouveau_irq_postinstall(dev); + + if (dev_priv->card_type >= NV_40) + NV_WRITE(NV_PGRAPH_NV40_UNK220, dev_priv->fb_obj->instance >> 4); + + DRM_DEBUG("%s: setting FIFO %d active\n", __func__, dev_priv->cur_fifo); + + NV_WRITE(NV_PFIFO_CACHES, 0x00000000); + 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); + NV_WRITE(NV_PFIFO_CACH0_PSH0, 0x00000000); + NV_WRITE(NV_PFIFO_CACH0_PUL0, 0x00000000); + 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) + ); + dev_priv->ramfc_offset=0x11000; + dev_priv->ramro_offset=0x11200; + NV_WRITE(NV_PFIFO_RAMFC, dev_priv->ramfc_offset>>8); /* RAMIN+0x11000 0.5k */ + 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); +#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); +#endif + NV_WRITE(NV_PFIFO_CACH1_DMAPSH, 0x00000001); + NV_WRITE(NV_PFIFO_CACH1_PSH0, 0x00000001); + NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001); + NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000001); + + NV_WRITE(NV_PGRAPH_CTX_USER, 0x0); + NV_WRITE(NV_PGRAPH_CTX_SWITCH1, 0x19); + NV_WRITE(NV_PFIFO_DELAY_0, 0xff /* retrycount*/ ); + if (dev_priv->card_type >= NV_40) + NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x00002001); + else + NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x10110000); + + 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__); +} + +static int nouveau_dma_init(struct drm_device *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_config *config = &dev_priv->config; + struct mem_block *cb; + int cb_min_size = nouveau_fifo_number(dev) * NV03_FIFO_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; + if (!config->cmdbuf.size || config->cmdbuf.size < cb_min_size) + config->cmdbuf.size = cb_min_size; + + cb = nouveau_mem_alloc(dev, 0, config->cmdbuf.size, + config->cmdbuf.location, (DRMFILE)-2); + /* Try defaults if that didn't succeed */ + if (!cb) { + config->cmdbuf.location = NOUVEAU_MEM_FB; + config->cmdbuf.size = cb_min_size; + cb = nouveau_mem_alloc(dev, 0, config->cmdbuf.size, + config->cmdbuf.location, (DRMFILE)-2); + } + if (!cb) { + DRM_ERROR("Couldn't allocate DMA command buffer.\n"); + 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"); + DRM_INFO("FIFO size is %dKiB\n", dev_priv->cmdbuf_ch_size>>10); + + return 0; +} + +/* allocates and initializes a fifo for user space consumption */ +static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, DRMFILE filp) { int i; int ret; drm_nouveau_private_t *dev_priv = dev->dev_private; + uint32_t ctx_addr; /* Init cmdbuf on first FIFO init, this is delayed until now to * give the ddx a chance to configure the cmdbuf with SETPARAM @@ -90,18 +202,15 @@ static int nouveau_fifo_init(drm_device_t* dev,drm_nouveau_fifo_init_t* init, DR * Alright, here is the full story * Nvidia cards have multiple hw fifo contexts (praise them for that, * no complicated crash-prone context switches) - * X always uses context 0 (0x00800000) * We allocate a new context for each app and let it write to it directly * (woo, full userspace command submission !) * When there are no more contexts, you lost */ for(i=0;ififos[i].used==0) - { - dev_priv->fifos[i].used=1; break; - } + DRM_INFO("Allocating FIFO number %d\n", i); /* no more fifos. you lost. */ if (i==nouveau_fifo_number(dev)) return DRM_ERR(EINVAL); @@ -110,16 +219,49 @@ static int nouveau_fifo_init(drm_device_t* dev,drm_nouveau_fifo_init_t* init, DR dev_priv->fifos[i].used=1; dev_priv->fifos[i].filp=filp; - /* enable the fifo */ - nouveau_fifo_enable(dev); + nouveau_wait_for_idle(dev); + + /* disable the fifo caches */ + NV_WRITE(NV_PFIFO_CACHES, 0x00000000); + + // FIXME i*32 is true on nv04, what is it on >=nv10 ? + ctx_addr=NV_RAMIN+dev_priv->ramfc_offset+i*32; + + // clear the first 2 RAMFC entries + // FIXME try to fill GET/PUT and see what that changes + NV_WRITE(ctx_addr,0x0); + NV_WRITE(ctx_addr+4,0x0); + + // FIXME that's what is done in nvosdk, but that part of the code is buggy so... + // RAMFC + 8 = instoffset + NV_WRITE(ctx_addr+8,dev_priv->cmdbuf_obj->instance >> 4); + + // RAMFC + 16 = defaultFetch + 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); + + /* enable the fifo dma operation */ + NV_WRITE(NV_PFIFO_MODE,NV_READ(NV_PFIFO_MODE)|(1<cur_fifo=i; + 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); - /* make the fifo available to user space */ init->channel = i; init->put_base = i*dev_priv->cmdbuf_ch_size; NV_WRITE(NV03_FIFO_REGS_DMAPUT(i), init->put_base); NV_WRITE(NV03_FIFO_REGS_DMAGET(i), init->put_base); + NV_WRITE(NV_PFIFO_CACH1_DMAP, init->put_base); + NV_WRITE(NV_PFIFO_CACH1_DMAG, init->put_base); + /* reenable the fifo caches */ + NV_WRITE(NV_PFIFO_CACHES, 0x00000001); + + /* make the fifo available to user space */ /* first, the fifo control regs */ init->ctrl = dev_priv->mmio->offset + NV03_FIFO_REGS(i); init->ctrl_size = NV03_FIFO_REGS_SIZE; @@ -140,14 +282,29 @@ static int nouveau_fifo_init(drm_device_t* dev,drm_nouveau_fifo_init_t* init, DR /* FIFO has no objects yet */ dev_priv->fifos[i].objs = NULL; - DRM_DEBUG("%s: initialised FIFO %d\n", __func__, i); - dev_priv->cur_fifo = i; + DRM_INFO("%s: initialised FIFO %d\n", __func__, i); return 0; } -static void nouveau_pfifo_init(drm_device_t* dev); + +/* stops a fifo */ +void nouveau_fifo_free(drm_device_t* dev,int n) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + dev_priv->fifos[n].used=0; + DRM_DEBUG("%s: freeing fifo %d\n", __func__, n); + + /* disable the fifo caches */ + NV_WRITE(NV_PFIFO_CACHES, 0x00000000); + + NV_WRITE(NV_PFIFO_MODE,NV_READ(NV_PFIFO_MODE)&~(1<dev_private; @@ -155,9 +312,10 @@ void nouveau_fifo_cleanup(drm_device_t * dev, DRMFILE filp) DRM_DEBUG("clearing FIFO enables from filp\n"); for(i=0;ififos[i].filp==filp) - dev_priv->fifos[i].used=0; + nouveau_fifo_free(dev,i); - if (dev_priv->cur_fifo == i) { + /* check we still point at an active channel */ + if (dev_priv->fifos[dev_priv->cur_fifo].used == 0) { DRM_DEBUG("%s: cur_fifo is no longer owned.\n", __func__); for (i=0;ififos[i].used) break; @@ -167,9 +325,8 @@ void nouveau_fifo_cleanup(drm_device_t * dev, DRMFILE filp) dev_priv->cur_fifo = i; } - if (dev_priv->cmdbuf_alloc) - nouveau_pfifo_init(dev); -// nouveau_fifo_enable(dev); +/* if (dev_priv->cmdbuf_alloc) + nouveau_fifo_init(dev);*/ } int nouveau_fifo_id_get(drm_device_t* dev, DRMFILE filp) @@ -183,99 +340,30 @@ int nouveau_fifo_id_get(drm_device_t* dev, DRMFILE filp) return -1; } -static void nouveau_pfifo_init(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.. - */ - - if (dev->irq_enabled) - nouveau_irq_postinstall(dev); - - if (dev_priv->card_type >= NV_40) - NV_WRITE(NV_PGRAPH_NV40_UNK220, dev_priv->fb_obj->instance >> 4); - - DRM_DEBUG("%s: setting FIFO %d active\n", __func__, dev_priv->cur_fifo); - - NV_WRITE(NV_PFIFO_CACHES, 0x00000000); - nouveau_fifo_enable(dev); - - 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); - NV_WRITE(NV_PFIFO_CACH0_PSH0, 0x00000000); - NV_WRITE(NV_PFIFO_CACH0_PUL0, 0x00000000); - 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) - ); - NV_WRITE(NV_PFIFO_RAMFC, 0x00000110); /* RAMIN+0x11000 0.5k */ - NV_WRITE(NV_PFIFO_RAMRO, 0x00000112); /* RAMIN+0x11200 0.5k */ - NV_WRITE(NV_PFIFO_CACH0_PUL1, 0x00000001); - NV_WRITE(NV_PFIFO_CACH1_DMAC, 0x00000000); - NV_WRITE(NV_PFIFO_CACH1_ENG, 0x00000000); -#ifdef __BIG_ENDIAN - NV_WRITE(NV_PFIFO_CACH1_DMAF, 0x800F0078); -#else - NV_WRITE(NV_PFIFO_CACH1_DMAF, 0x000F0078); -#endif - NV_WRITE(NV_PFIFO_CACH1_DMAS, 0x00000001); - NV_WRITE(NV_PFIFO_CACH1_PSH0, 0x00000001); - NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001); - NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000001); - - 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)); -} - /*********************************** * ioctls wrapping the functions ***********************************/ -static int nouveau_ioctl_fifo_init(DRM_IOCTL_ARGS) +static int nouveau_ioctl_fifo_alloc(DRM_IOCTL_ARGS) { DRM_DEVICE; - drm_nouveau_fifo_init_t init; + drm_nouveau_fifo_alloc_t init; int res; - DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_fifo_init_t __user *) data, sizeof(init)); + DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_fifo_alloc_t __user *) data, sizeof(init)); - res=nouveau_fifo_init(dev,&init,filp); + res=nouveau_fifo_alloc(dev,&init,filp); if (!res) - DRM_COPY_TO_USER_IOCTL((drm_nouveau_fifo_init_t __user *)data, init, sizeof(init)); + DRM_COPY_TO_USER_IOCTL((drm_nouveau_fifo_alloc_t __user *)data, init, sizeof(init)); return res; } -static int nouveau_ioctl_fifo_reinit(DRM_IOCTL_ARGS) -{ - DRM_DEVICE; - - nouveau_pfifo_init(dev); - return 0; -} - /*********************************** * finally, the ioctl table ***********************************/ drm_ioctl_desc_t nouveau_ioctls[] = { - [DRM_IOCTL_NR(DRM_NOUVEAU_FIFO_INIT)] = {nouveau_ioctl_fifo_init, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_NOUVEAU_PFIFO_REINIT)] = {nouveau_ioctl_fifo_reinit, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_NOUVEAU_FIFO_ALLOC)] = {nouveau_ioctl_fifo_alloc, DRM_AUTH}, [DRM_IOCTL_NR(DRM_NOUVEAU_OBJECT_INIT)] = {nouveau_ioctl_object_init, DRM_AUTH}, [DRM_IOCTL_NR(DRM_NOUVEAU_DMA_OBJECT_INIT)] = {nouveau_ioctl_dma_object_init, DRM_AUTH}, [DRM_IOCTL_NR(DRM_NOUVEAU_MEM_ALLOC)] = {nouveau_ioctl_mem_alloc, DRM_AUTH}, -- cgit v1.2.3 From a749d9d5b49ea0e402848bd6024e5c44826e784f Mon Sep 17 00:00:00 2001 From: Stephane Marchesin Date: Thu, 12 Oct 2006 01:08:15 +0200 Subject: More work on the context switch code. Still doesn't work. I'm mostly convinced it's an initialization issue. --- shared-core/nouveau_fifo.c | 70 ++++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 27 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index de23f96d..da9a8630 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -110,7 +110,6 @@ static void nouveau_fifo_init(drm_device_t* dev) NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000001); NV_WRITE(NV_PGRAPH_CTX_USER, 0x0); - NV_WRITE(NV_PGRAPH_CTX_SWITCH1, 0x19); NV_WRITE(NV_PFIFO_DELAY_0, 0xff /* retrycount*/ ); if (dev_priv->card_type >= NV_40) NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x00002001); @@ -187,7 +186,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; - uint32_t ctx_addr; + uint32_t ctx_addr,ctx_size; /* Init cmdbuf on first FIFO init, this is delayed until now to * give the ddx a chance to configure the cmdbuf with SETPARAM @@ -219,54 +218,71 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, dev_priv->fifos[i].used=1; dev_priv->fifos[i].filp=filp; + init->channel = i; + init->put_base = i*dev_priv->cmdbuf_ch_size; + dev_priv->cur_fifo = init->channel; + nouveau_wait_for_idle(dev); /* disable the fifo caches */ NV_WRITE(NV_PFIFO_CACHES, 0x00000000); - // FIXME i*32 is true on nv04, what is it on >=nv10 ? - ctx_addr=NV_RAMIN+dev_priv->ramfc_offset+i*32; - - // clear the first 2 RAMFC entries - // FIXME try to fill GET/PUT and see what that changes - NV_WRITE(ctx_addr,0x0); - NV_WRITE(ctx_addr+4,0x0); + if (dev_priv->card_type <= NV_04) + ctx_size=32; + else + ctx_size=128; - // FIXME that's what is done in nvosdk, but that part of the code is buggy so... - // RAMFC + 8 = instoffset - NV_WRITE(ctx_addr+8,dev_priv->cmdbuf_obj->instance >> 4); + ctx_addr=NV_RAMIN+dev_priv->ramfc_offset+init->channel*ctx_size; + // clear the fifo context + for(i=0;iput_base); + NV_WRITE(ctx_addr+4,init->put_base); + if (dev_priv->card_type <= NV_04) + { + // 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); +#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); +#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); +#endif + } + else + { + NV_WRITE(ctx_addr+12,dev_priv->cmdbuf_obj->instance >> 4/*DMA INST/DMA COUNT*/); +#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); +#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); +#endif + } /* enable the fifo dma operation */ - NV_WRITE(NV_PFIFO_MODE,NV_READ(NV_PFIFO_MODE)|(1<channel)); // FIXME check if we need to refill the time quota with something like NV_WRITE(0x204C, 0x0003FFFF); - dev_priv->cur_fifo=i; 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); - init->channel = i; - init->put_base = i*dev_priv->cmdbuf_ch_size; - - NV_WRITE(NV03_FIFO_REGS_DMAPUT(i), init->put_base); - NV_WRITE(NV03_FIFO_REGS_DMAGET(i), init->put_base); NV_WRITE(NV_PFIFO_CACH1_DMAP, init->put_base); NV_WRITE(NV_PFIFO_CACH1_DMAG, init->put_base); + NV_WRITE(NV03_FIFO_REGS_DMAPUT(init->channel), init->put_base); + NV_WRITE(NV03_FIFO_REGS_DMAGET(init->channel), init->put_base); /* reenable the fifo caches */ NV_WRITE(NV_PFIFO_CACHES, 0x00000001); /* make the fifo available to user space */ /* first, the fifo control regs */ - init->ctrl = dev_priv->mmio->offset + NV03_FIFO_REGS(i); + init->ctrl = dev_priv->mmio->offset + NV03_FIFO_REGS(init->channel); init->ctrl_size = NV03_FIFO_REGS_SIZE; ret = drm_addmap(dev, init->ctrl, init->ctrl_size, _DRM_REGISTERS, - 0, &dev_priv->fifos[i].regs); + 0, &dev_priv->fifos[init->channel].regs); if (ret != 0) return ret; @@ -275,14 +291,14 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, init->cmdbuf += init->channel * dev_priv->cmdbuf_ch_size; init->cmdbuf_size = dev_priv->cmdbuf_ch_size; ret = drm_addmap(dev, init->cmdbuf, init->cmdbuf_size, _DRM_REGISTERS, - 0, &dev_priv->fifos[i].map); + 0, &dev_priv->fifos[init->channel].map); if (ret != 0) return ret; /* FIFO has no objects yet */ - dev_priv->fifos[i].objs = NULL; + dev_priv->fifos[init->channel].objs = NULL; - DRM_INFO("%s: initialised FIFO %d\n", __func__, i); + DRM_INFO("%s: initialised FIFO %d\n", __func__, init->channel); return 0; } @@ -291,7 +307,7 @@ void nouveau_fifo_free(drm_device_t* dev,int n) { drm_nouveau_private_t *dev_priv = dev->dev_private; dev_priv->fifos[n].used=0; - DRM_DEBUG("%s: freeing fifo %d\n", __func__, n); + DRM_INFO("%s: freeing fifo %d\n", __func__, n); /* disable the fifo caches */ NV_WRITE(NV_PFIFO_CACHES, 0x00000000); -- cgit v1.2.3 From 7ef44b2b8dd1745f5b228e6161ebd989844c3088 Mon Sep 17 00:00:00 2001 From: Stephane Marchesin Date: Thu, 12 Oct 2006 17:31:49 +0200 Subject: Still more work on the context switching code. --- shared-core/nouveau_fifo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index da9a8630..1761bbec 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -227,7 +227,7 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, /* disable the fifo caches */ NV_WRITE(NV_PFIFO_CACHES, 0x00000000); - if (dev_priv->card_type <= NV_04) + if (dev_priv->card_type <= NV_05) ctx_size=32; else ctx_size=128; @@ -239,7 +239,7 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, NV_WRITE(ctx_addr,init->put_base); NV_WRITE(ctx_addr+4,init->put_base); - if (dev_priv->card_type <= NV_04) + 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); -- cgit v1.2.3 From 4988074794531939ec0cb0ad183633b59e9ccff4 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sat, 14 Oct 2006 06:57:49 +1100 Subject: Fix some randomness in activating a second channel on NV40 (odd GET/PUT vals). Ch 1 GET now advances, but no ctx_switch. --- shared-core/nouveau_fifo.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 1761bbec..bd924f5f 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -259,6 +259,10 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, #endif } + /* disable the pusher ? */ + NV_WRITE(NV_PFIFO_CACH1_DMAPSH, 0); + NV_WRITE(NV_PFIFO_CACH1_PSH0, 0); + /* enable the fifo dma operation */ NV_WRITE(NV_PFIFO_MODE,NV_READ(NV_PFIFO_MODE)|(1<channel)); @@ -274,6 +278,10 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, NV_WRITE(NV03_FIFO_REGS_DMAPUT(init->channel), init->put_base); NV_WRITE(NV03_FIFO_REGS_DMAGET(init->channel), init->put_base); + /* reenable the pusher ? */ + NV_WRITE(NV_PFIFO_CACH1_PSH0, 1); + NV_WRITE(NV_PFIFO_CACH1_DMAPSH, 1); + /* reenable the fifo caches */ NV_WRITE(NV_PFIFO_CACHES, 0x00000001); -- cgit v1.2.3 From b509abe413f74bd08f6415dec8147bd07e78a84b Mon Sep 17 00:00:00 2001 From: Stephane Marchesin Date: Fri, 13 Oct 2006 22:35:22 +0200 Subject: Fix the fifo context size on nv10, nv20 and nv30. --- shared-core/nouveau_fifo.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index bd924f5f..9615e084 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -227,10 +227,22 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, /* disable the fifo caches */ NV_WRITE(NV_PFIFO_CACHES, 0x00000000); - if (dev_priv->card_type <= NV_05) - ctx_size=32; - else - ctx_size=128; + 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: + ctx_size=64; + case NV_40: + case G_70: + default: + ctx_size=128; + } ctx_addr=NV_RAMIN+dev_priv->ramfc_offset+init->channel*ctx_size; // clear the fifo context -- cgit v1.2.3 From 3a0cd7c7e221f625585675490f626de8677a9dc7 Mon Sep 17 00:00:00 2001 From: Stephane Marchesin Date: Sat, 14 Oct 2006 01:21:31 +0200 Subject: Add the missing breaks. --- shared-core/nouveau_fifo.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 9615e084..6de6a615 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -238,10 +238,12 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, case NV_20: case NV_30: ctx_size=64; + break; case NV_40: case G_70: default: ctx_size=128; + break; } ctx_addr=NV_RAMIN+dev_priv->ramfc_offset+init->channel*ctx_size; -- cgit v1.2.3 From 2c5b91aecf3d21684ffca758c034cd9a8ed2155d Mon Sep 17 00:00:00 2001 From: Stephane Marchesin Date: Sat, 14 Oct 2006 16:36:11 +0200 Subject: Again more work on context switches. They work, sometimes. And when they do they seem to screw up the PGRAPH state. --- shared-core/nouveau_fifo.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 6de6a615..5b8cabd8 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -70,6 +70,7 @@ static void nouveau_fifo_init(drm_device_t* dev) DRM_DEBUG("%s: setting FIFO %d active\n", __func__, dev_priv->cur_fifo); + // FIXME remove all the stuff that's done in nouveau_fifo_alloc NV_WRITE(NV_PFIFO_CACHES, 0x00000000); NV_WRITE(NV_PFIFO_MODE, 0x00000000); @@ -226,6 +227,9 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, /* disable the fifo caches */ NV_WRITE(NV_PFIFO_CACHES, 0x00000000); + NV_WRITE(NV_PFIFO_CACH1_DMAPSH, NV_READ(NV_PFIFO_CACH1_DMAPSH)&(~0x1)); + NV_WRITE(NV_PFIFO_CACH1_PSH0, 0x00000000); + NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000000); switch(dev_priv->card_type) { @@ -273,10 +277,6 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, #endif } - /* disable the pusher ? */ - NV_WRITE(NV_PFIFO_CACH1_DMAPSH, 0); - NV_WRITE(NV_PFIFO_CACH1_PSH0, 0); - /* enable the fifo dma operation */ NV_WRITE(NV_PFIFO_MODE,NV_READ(NV_PFIFO_MODE)|(1<channel)); @@ -291,10 +291,23 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, NV_WRITE(NV_PFIFO_CACH1_DMAG, init->put_base); NV_WRITE(NV03_FIFO_REGS_DMAPUT(init->channel), init->put_base); NV_WRITE(NV03_FIFO_REGS_DMAGET(init->channel), init->put_base); + NV_WRITE(NV_PFIFO_CACH1_DMAI, dev_priv->cmdbuf_obj->instance >> 4); + NV_WRITE(NV_PFIFO_SIZE , 0x0000FFFF); + NV_WRITE(NV_PFIFO_CACH1_HASH, 0x0000FFFF); - /* reenable the pusher ? */ - NV_WRITE(NV_PFIFO_CACH1_PSH0, 1); - NV_WRITE(NV_PFIFO_CACH1_DMAPSH, 1); + 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); +#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); +#endif + NV_WRITE(NV_PFIFO_CACH1_DMAPSH, 0x00000001); + NV_WRITE(NV_PFIFO_CACH1_PSH0, 0x00000001); + NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001); + NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000001); /* reenable the fifo caches */ NV_WRITE(NV_PFIFO_CACHES, 0x00000001); -- cgit v1.2.3 From 1943f39d8ce27c799f928bab172e521f4d540166 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 17 Oct 2006 06:37:40 +1100 Subject: Setup NV40 RAMFC (in wrong location.. but anyway), rearrange the RAMFC setup code a bit. --- shared-core/nouveau_fifo.c | 124 +++++++++++++++++++++++++++++---------------- 1 file changed, 79 insertions(+), 45 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 5b8cabd8..96c3c5e3 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -181,13 +181,88 @@ static int nouveau_dma_init(struct drm_device *dev) return 0; } +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; + 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; + } + + ctx_addr=NV_RAMIN+dev_priv->ramfc_offset+init->channel*ctx_size; + // clear the fifo context + for(i=0;iput_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); +#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); +#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); +#endif + } + else + { + NV_WRITE(ctx_addr+12,dev_priv->cmdbuf_obj->instance >> 4/*DMA INST/DMA COUNT*/); +#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); +#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); +#endif + } + +} + +static void nouveau_nv40_context_init(drm_device_t *dev, + drm_nouveau_fifo_alloc_t *init) +{ +#define RAMFC_WR(offset, val) NV_WRITE(fifoctx + NV40_RAMFC_##offset, (val)) + drm_nouveau_private_t *dev_priv = dev->dev_private; + uint32_t fifoctx; + int i; + + fifoctx = NV_RAMIN + dev_priv->ramfc_offset + init->channel*128; + for (i=0;i<128;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 , dev_priv->cmdbuf_obj->instance >> 4); + RAMFC_WR(DMA_FETCH , 0x30086078); + RAMFC_WR(DMA_SUBROUTINE, init->put_base); + RAMFC_WR(GRCTX_INSTANCE, 0); /* XXX */ + RAMFC_WR(DMA_TIMESLICE , 0x0001FFFF); +#undef RAMFC_WR +} + /* allocates and initializes a fifo for user space consumption */ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, DRMFILE filp) { int i; int ret; drm_nouveau_private_t *dev_priv = dev->dev_private; - uint32_t ctx_addr,ctx_size; /* Init cmdbuf on first FIFO init, this is delayed until now to * give the ddx a chance to configure the cmdbuf with SETPARAM @@ -231,51 +306,10 @@ 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); - 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: - ctx_size=64; - break; - case NV_40: - case G_70: - default: - ctx_size=128; - break; - } - - ctx_addr=NV_RAMIN+dev_priv->ramfc_offset+init->channel*ctx_size; - // clear the fifo context - for(i=0;iput_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); -#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); -#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); -#endif - } + if (dev_priv->card_type < NV_40) + nouveau_context_init(dev, init); else - { - NV_WRITE(ctx_addr+12,dev_priv->cmdbuf_obj->instance >> 4/*DMA INST/DMA COUNT*/); -#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); -#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); -#endif - } + nouveau_nv40_context_init(dev, init); /* enable the fifo dma operation */ NV_WRITE(NV_PFIFO_MODE,NV_READ(NV_PFIFO_MODE)|(1<channel)); -- cgit v1.2.3 From 98e718d48fcd166accf1af3c017c34e331ab09cb Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 17 Oct 2006 07:29:31 +1100 Subject: NV40: FIFO context switching now WorksForMe(tm) --- shared-core/nouveau_fifo.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 96c3c5e3..d015d420 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -92,9 +92,12 @@ static void nouveau_fifo_init(drm_device_t* dev) ((dev_priv->objs.ht_bits - 9) << 16) | (dev_priv->objs.ht_base >> 8) ); - dev_priv->ramfc_offset=0x11000; + dev_priv->ramfc_offset=0x12000; dev_priv->ramro_offset=0x11200; - NV_WRITE(NV_PFIFO_RAMFC, dev_priv->ramfc_offset>>8); /* RAMIN+0x11000 0.5k */ + 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); 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); @@ -314,6 +317,10 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, /* enable the fifo dma operation */ NV_WRITE(NV_PFIFO_MODE,NV_READ(NV_PFIFO_MODE)|(1<channel)); + NV_WRITE(NV03_FIFO_REGS_DMAPUT(init->channel), init->put_base); + NV_WRITE(NV03_FIFO_REGS_DMAGET(init->channel), init->put_base); + +if (init->channel == 0) { // FIXME check if we need to refill the time quota with something like NV_WRITE(0x204C, 0x0003FFFF); if (dev_priv->card_type >= NV_40) @@ -323,8 +330,6 @@ 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(NV03_FIFO_REGS_DMAPUT(init->channel), init->put_base); - NV_WRITE(NV03_FIFO_REGS_DMAGET(init->channel), init->put_base); NV_WRITE(NV_PFIFO_CACH1_DMAI, dev_priv->cmdbuf_obj->instance >> 4); NV_WRITE(NV_PFIFO_SIZE , 0x0000FFFF); NV_WRITE(NV_PFIFO_CACH1_HASH, 0x0000FFFF); @@ -338,6 +343,7 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, #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); #endif +} NV_WRITE(NV_PFIFO_CACH1_DMAPSH, 0x00000001); NV_WRITE(NV_PFIFO_CACH1_PSH0, 0x00000001); NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001); @@ -375,6 +381,8 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, void nouveau_fifo_free(drm_device_t* dev,int n) { drm_nouveau_private_t *dev_priv = dev->dev_private; + int i; + dev_priv->fifos[n].used=0; DRM_INFO("%s: freeing fifo %d\n", __func__, n); @@ -382,7 +390,14 @@ void nouveau_fifo_free(drm_device_t* dev,int n) NV_WRITE(NV_PFIFO_CACHES, 0x00000000); NV_WRITE(NV_PFIFO_MODE,NV_READ(NV_PFIFO_MODE)&~(1<ramfc_offset + n*128 + i)); + NV_WRITE(NV_RAMIN + dev_priv->ramfc_offset + n*128 + i, 0); + } /* reenable the fifo caches */ NV_WRITE(NV_PFIFO_CACHES, 0x00000001); -- cgit v1.2.3 From 4b43ee63f90c93701c9f1cdf7fefd1816b316d33 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 17 Oct 2006 12:33:49 +1100 Subject: NV40: *Now* fifo ctx switching works for me.. Ok, I lied before.. it was a fluke it worked and required magic to repeat it.. It actually helps to fill in RAMFC entries in the correct place. The code also clears RAMIN entirely instead of just the hash-table. --- shared-core/nouveau_fifo.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index d015d420..5a7b8638 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -92,12 +92,15 @@ static void nouveau_fifo_init(drm_device_t* dev) ((dev_priv->objs.ht_bits - 9) << 16) | (dev_priv->objs.ht_base >> 8) ); - dev_priv->ramfc_offset=0x12000; - dev_priv->ramro_offset=0x11200; + /* 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); -- cgit v1.2.3 From b5cf0d635c81d2c99510ce5e3f67f4aa593cd6d7 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 18 Oct 2006 02:37:19 +1100 Subject: Remove hack which delays activation of a additional channel. The previously active channel's state is saved to RAMFC before PFIFO gets clobbered. --- shared-core/nouveau_fifo.c | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 5a7b8638..5c328668 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -238,10 +238,10 @@ static void nouveau_context_init(drm_device_t *dev, } +#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) { -#define RAMFC_WR(offset, val) NV_WRITE(fifoctx + NV40_RAMFC_##offset, (val)) drm_nouveau_private_t *dev_priv = dev->dev_private; uint32_t fifoctx; int i; @@ -260,9 +260,37 @@ static void nouveau_nv40_context_init(drm_device_t *dev, RAMFC_WR(DMA_SUBROUTINE, init->put_base); RAMFC_WR(GRCTX_INSTANCE, 0); /* XXX */ RAMFC_WR(DMA_TIMESLICE , 0x0001FFFF); -#undef RAMFC_WR } +static void nouveau_nv40_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*128; + + 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_DCOUNT , NV_READ(NV_PFIFO_CACH1_DMA_DCOUNT)); + RAMFC_WR(DMA_STATE , NV_READ(NV_PFIFO_CACH1_DMAS)); + //fetch + 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)); + RAMFC_WR(GRCTX_INSTANCE , NV_READ(NV40_PFIFO_GRCTX_INSTANCE)); + RAMFC_WR(DMA_TIMESLICE , NV_READ(NV_PFIFO_DMA_TIMESLICE) & 0x1FFFF); + RAMFC_WR(UNK_40 , NV_READ(NV40_PFIFO_UNK32E4)); +} +#undef RAMFC_WR + /* allocates and initializes a fifo for user space consumption */ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, DRMFILE filp) { @@ -314,8 +342,16 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, if (dev_priv->card_type < NV_40) nouveau_context_init(dev, init); - else + else { + /* Save current channel's state to it's RAMFC entry */ + 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); + } /* enable the fifo dma operation */ NV_WRITE(NV_PFIFO_MODE,NV_READ(NV_PFIFO_MODE)|(1<channel)); @@ -323,7 +359,6 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, NV_WRITE(NV03_FIFO_REGS_DMAPUT(init->channel), init->put_base); NV_WRITE(NV03_FIFO_REGS_DMAGET(init->channel), init->put_base); -if (init->channel == 0) { // FIXME check if we need to refill the time quota with something like NV_WRITE(0x204C, 0x0003FFFF); if (dev_priv->card_type >= NV_40) @@ -346,7 +381,6 @@ if (init->channel == 0) { #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); #endif -} NV_WRITE(NV_PFIFO_CACH1_DMAPSH, 0x00000001); NV_WRITE(NV_PFIFO_CACH1_PSH0, 0x00000001); NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001); -- cgit v1.2.3 From 2dd3c039fdbe86db4043abcc69babf768edb3ab8 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 6 Nov 2006 11:42:15 +1100 Subject: fixup fifo size so it is page aligned --- shared-core/nouveau_fifo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 5c328668..cf389647 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -138,7 +138,7 @@ static int nouveau_dma_init(struct drm_device *dev) drm_nouveau_private_t *dev_priv = dev->dev_private; struct nouveau_config *config = &dev_priv->config; struct mem_block *cb; - int cb_min_size = nouveau_fifo_number(dev) * NV03_FIFO_SIZE; + 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); -- cgit v1.2.3 From 9ef4bbc66c1b055b4450ea9354945d784751cef7 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 14 Nov 2006 04:51:13 +1100 Subject: Hack around yet another "X restart borkage without nouveau.ko reload" problem. On X init, PFIFO and PGRAPH are reset to defaults. This causes the GPU to loose the configuration done by the drm. Perhaps a CARD_INIT ioctl a proper solution to having this problem again in the future.. --- shared-core/nouveau_fifo.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index cf389647..ef63f084 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -178,7 +178,6 @@ static int nouveau_dma_init(struct drm_device *dev) 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"); @@ -306,6 +305,9 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, if (ret) return ret; } + /* Initialise PFIFO regs */ + if (!dev_priv->fifo_alloc_count) + nouveau_fifo_init(dev); /* * Alright, here is the full story @@ -409,6 +411,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 +441,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 */ -- cgit v1.2.3 From 7002082944a69e1d11b0146b1176fd4293581dcd Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 14 Nov 2006 08:11:49 +1100 Subject: Restructure initialisation a bit. - Do important card init in firstopen - Give each channel it's own cmdbuf dma object - Move RAMHT config state to the same place as RAMRO/RAMFC - Make sure instance mem for objects is *after* RAM{FC,HT,RO} --- shared-core/nouveau_fifo.c | 177 +++++++++++++++++++++++++++++---------------- 1 file changed, 113 insertions(+), 64 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index ef63f084..d4e5b1dd 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,13 +204,6 @@ 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; @@ -190,6 +219,7 @@ static void nouveau_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 ctx_addr,ctx_size; int i; @@ -208,6 +238,8 @@ static void nouveau_context_init(drm_device_t *dev, 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 for(i=0;icard_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); + 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); #else @@ -227,7 +259,7 @@ static void nouveau_context_init(drm_device_t *dev, } else { - NV_WRITE(ctx_addr+12,dev_priv->cmdbuf_obj->instance >> 4/*DMA INST/DMA COUNT*/); + NV_WRITE(ctx_addr+12,cb_obj->instance >> 4/*DMA INST/DMA COUNT*/); #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); #else @@ -242,9 +274,11 @@ 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); @@ -254,7 +288,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 */ @@ -296,6 +330,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 @@ -305,9 +340,6 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, if (ret) return ret; } - /* Initialise PFIFO regs */ - if (!dev_priv->fifo_alloc_count) - nouveau_fifo_init(dev); /* * Alright, here is the full story @@ -326,6 +358,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; @@ -370,7 +419,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); -- cgit v1.2.3 From 2fd812f8ef8adb09fd8d17cab869f9fc8b047d75 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 14 Nov 2006 09:00:31 +1100 Subject: Completely untested NV10/20/30 FIFO context switching changes. --- shared-core/nouveau_fifo.c | 108 +++++++++++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 37 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index d4e5b1dd..c662165b 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -220,24 +220,9 @@ static void nouveau_context_init(drm_device_t *dev, { drm_nouveau_private_t *dev_priv = dev->dev_private; struct nouveau_object *cb_obj; - uint32_t ctx_addr,ctx_size; + 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; @@ -247,27 +232,72 @@ 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, cb_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,cb_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, @@ -391,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); } -- cgit v1.2.3 From 18bba3fa29187bb5122ed057989203dc05bc46aa Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 17 Nov 2006 08:05:23 +1100 Subject: Dump some useful info when a PGRAPH error occurs. The "channel" detect doesn't work on my nv40, but the rest seems to produce sane info. --- shared-core/nouveau_fifo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index c662165b..73c4e9f9 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -536,7 +536,7 @@ void nouveau_fifo_cleanup(drm_device_t* dev, DRMFILE filp) DRM_DEBUG("clearing FIFO enables from filp\n"); for(i=0;ififos[i].filp==filp) + if (dev_priv->fifos[i].used && dev_priv->fifos[i].filp==filp) nouveau_fifo_free(dev,i); /* check we still point at an active channel */ -- cgit v1.2.3 From e9194dd1b068666dd94e73d95dc3cd031a89a6b7 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sat, 18 Nov 2006 10:03:45 +1100 Subject: Check some return vals, fixes a couple of oopses. --- shared-core/nouveau_fifo.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 73c4e9f9..441bde40 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -403,6 +403,10 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, NV_DMA_ACCESS_RO, NV_DMA_TARGET_VIDMEM); } + if (!cb_obj) { + DRM_ERROR("unable to alloc object for command buffer\n"); + return DRM_ERR(EINVAL); + } dev_priv->fifos[i].cmdbuf_obj = cb_obj; /* that fifo is used */ -- cgit v1.2.3 From 9ac7a8b0b4c0431b605c3f8d0b4a696903010c51 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sat, 18 Nov 2006 10:09:29 +1100 Subject: Only return FIFO number if the FIFO is marked as in use.. --- shared-core/nouveau_fifo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 441bde40..b6fc613c 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -564,7 +564,7 @@ int nouveau_fifo_id_get(drm_device_t* dev, DRMFILE filp) int i; for(i=0;ififos[i].filp == filp) + if (dev_priv->fifos[i].used && dev_priv->fifos[i].filp == filp) return i; return -1; } -- cgit v1.2.3 From f48a7685bd7a241001cec89acd8cce6cdefa941e Mon Sep 17 00:00:00 2001 From: Matthieu Castet Date: Tue, 28 Nov 2006 21:32:03 +0100 Subject: For nv10, bit 16 of RAMFC need to be set for 64 bytes fifo context. When cleaning a fifo, we shouldn't assume everybody use nv40 ;) Fill DMA_SUBROUTINE fill correct value. --- shared-core/nouveau_fifo.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index b6fc613c..d67cdc3c 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -44,6 +44,19 @@ int nouveau_fifo_number(drm_device_t* dev) } } +/* returns the size of fifo context */ +static int nouveau_fifo_ctx_size(drm_device_t* dev) +{ + drm_nouveau_private_t *dev_priv=dev->dev_private; + + if (dev_priv->card_type >= NV_40) + return 128; + else if (dev_priv->card_type >= NV_10) + return 64; + else + return 32; +} + /*********************************** * functions doing the actual work ***********************************/ @@ -99,7 +112,8 @@ static int nouveau_fifo_instmem_configure(drm_device_t *dev) } 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); + NV_WRITE(NV_PFIFO_RAMFC, (dev_priv->ramfc_offset>>8) | + (1 << 16) /* 64 Bytes entry*/); } else { dev_priv->ramfc_offset = 0x11400; dev_priv->ramfc_size = nouveau_fifo_number(dev) * 32; @@ -271,7 +285,7 @@ static void nouveau_nv10_context_init(drm_device_t *dev, NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | NV_PFIFO_CACH1_DMAF_MAX_REQS_4); #endif - RAMFC_WR(DMA_SUBROUTINE, init->put_base); + RAMFC_WR(DMA_SUBROUTINE, 0); } static void nouveau_nv10_context_save(drm_device_t *dev) @@ -295,7 +309,7 @@ static void nouveau_nv10_context_save(drm_device_t *dev) 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)); + RAMFC_WR(DMA_SUBROUTINE , NV_READ(NV_PFIFO_CACH1_DMASR)); } #undef RAMFC_WR @@ -509,6 +523,7 @@ void nouveau_fifo_free(drm_device_t* dev,int n) { drm_nouveau_private_t *dev_priv = dev->dev_private; int i; + int ctx_size = nouveau_fifo_ctx_size(dev); dev_priv->fifos[n].used=0; DRM_INFO("%s: freeing fifo %d\n", __func__, n); @@ -520,10 +535,10 @@ void nouveau_fifo_free(drm_device_t* dev,int n) // FIXME XXX needs more code /* Clean RAMFC */ - for (i=0;i<128;i+=4) { + for (i=0;iramfc_offset + n*128 + i)); - NV_WRITE(NV_RAMIN + dev_priv->ramfc_offset + n*128 + i, 0); + dev_priv->ramfc_offset + n*ctx_size + i)); + NV_WRITE(NV_RAMIN + dev_priv->ramfc_offset + n*ctx_size + i, 0); } /* reenable the fifo caches */ -- cgit v1.2.3 From b1a9a769711d83af8ab4c7ba4eec52a05a351533 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 30 Nov 2006 08:35:42 +1100 Subject: Wrap access to objects in RAMIN. This will make it easier to support extra RAMIN in vram at a later point. --- shared-core/nouveau_fifo.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index d67cdc3c..9ff0563c 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -247,7 +247,7 @@ static void nouveau_context_init(drm_device_t *dev, NV_WRITE(ctx_addr,init->put_base); NV_WRITE(ctx_addr+4,init->put_base); // 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); + NV_WRITE(ctx_addr+8, nouveau_chip_instance_get(dev, cb_obj->instance)); #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); #else @@ -274,7 +274,8 @@ static void nouveau_nv10_context_init(drm_device_t *dev, */ RAMFC_WR(DMA_PUT , init->put_base); RAMFC_WR(DMA_GET , init->put_base); - RAMFC_WR(DMA_INSTANCE , cb_obj->instance >> 4); + RAMFC_WR(DMA_INSTANCE , nouveau_chip_instance_get(dev, + cb_obj->instance)); #ifdef __BIG_ENDIAN RAMFC_WR(DMA_FETCH, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES | NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | @@ -332,7 +333,8 @@ 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 , cb_obj->instance >> 4); + RAMFC_WR(DMA_INSTANCE , nouveau_chip_instance_get(dev, + cb_obj->instance)); RAMFC_WR(DMA_FETCH , 0x30086078); RAMFC_WR(DMA_SUBROUTINE, init->put_base); RAMFC_WR(GRCTX_INSTANCE, 0); /* XXX */ @@ -471,7 +473,8 @@ 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, cb_obj->instance >> 4); + NV_WRITE(NV_PFIFO_CACH1_DMAI, + nouveau_chip_instance_get(dev, cb_obj->instance)); NV_WRITE(NV_PFIFO_SIZE , 0x0000FFFF); NV_WRITE(NV_PFIFO_CACH1_HASH, 0x0000FFFF); -- cgit v1.2.3 From 80d75cf6950acf1a00a031ceb6511b26dcc9b056 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 30 Nov 2006 10:31:42 +1100 Subject: Use nouveau_mem.c to allocate RAMIN. --- shared-core/nouveau_fifo.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 9ff0563c..94762139 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -69,6 +69,7 @@ static int nouveau_fifo_ctx_size(drm_device_t* dev) static int nouveau_fifo_instmem_configure(drm_device_t *dev) { drm_nouveau_private_t *dev_priv = dev->dev_private; + uint32_t obj_base, obj_size; int i; /* Clear RAMIN */ @@ -123,6 +124,13 @@ static int nouveau_fifo_instmem_configure(drm_device_t *dev) dev_priv->ramfc_offset, dev_priv->ramfc_size); + obj_base = dev_priv->ramfc_offset + dev_priv->ramfc_size; + obj_size = (512*1024) - obj_base; /*XXX: probably wrong on some cards*/ + if (nouveau_instmem_init(dev, obj_base, obj_size)) + return 1; + DRM_DEBUG("RAMIN object space: offset=0x%08x, size=%dKiB\n", + obj_base, obj_size>>10); + return 0; } -- cgit v1.2.3 From 30acb90a6077798b1e0c4927273067500905d6d1 Mon Sep 17 00:00:00 2001 From: Stephane Marchesin Date: Sun, 3 Dec 2006 10:02:54 +0100 Subject: Merge the pciid work. Add getparams for AGP and FB physical adresses. Fix the MEM_ALLOC issue properly. Fix context switches for nv44. Change the DRM version to 0.0.1. --- shared-core/nouveau_fifo.c | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 94762139..67c790b4 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -106,19 +106,34 @@ static int nouveau_fifo_instmem_configure(drm_device_t *dev) * 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) | - (1 << 16) /* 64 Bytes entry*/); - } 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); + switch(dev_priv->card_type) + { + case NV_50: + case NV_40: + dev_priv->ramfc_offset = 0x20000; + dev_priv->ramfc_size = nouveau_fifo_number(dev) * nouveau_fifo_ctx_size(dev); + NV_WRITE(NV40_PFIFO_RAMFC, 0x30002); + break; + case NV_44: + dev_priv->ramfc_offset = 0x20000; + dev_priv->ramfc_size = nouveau_fifo_number(dev) * nouveau_fifo_ctx_size(dev); + NV_WRITE(NV40_PFIFO_RAMFC, ((nouveau_mem_fb_amount(dev)-512*1024+dev_priv->ramfc_offset)>>16) | + (2 << 16)); + break; + case NV_30: + case NV_20: + case NV_10: + dev_priv->ramfc_offset = 0x11400; + dev_priv->ramfc_size = nouveau_fifo_number(dev) * nouveau_fifo_ctx_size(dev); + NV_WRITE(NV_PFIFO_RAMFC, (dev_priv->ramfc_offset>>8) | + (1 << 16) /* 64 Bytes entry*/); + break; + case NV_04: + case NV_03: + dev_priv->ramfc_offset = 0x11400; + dev_priv->ramfc_size = nouveau_fifo_number(dev) * nouveau_fifo_ctx_size(dev); + NV_WRITE(NV_PFIFO_RAMFC, dev_priv->ramfc_offset>>8); + break; } DRM_DEBUG("RAMFC offset=0x%x, size=%d\n", dev_priv->ramfc_offset, -- cgit v1.2.3 From 1a40f3318c2660b83f64f7ed189d0f1692644ee4 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 12 Dec 2006 00:11:42 +1100 Subject: Port remaining NV4 RAMIN access from the ddx into the drm. Should fix lockups seen on NV4 cards. --- shared-core/nouveau_fifo.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 67c790b4..a611e438 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -434,13 +434,24 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, dev_priv->cmdbuf_alloc->size, NV_DMA_ACCESS_RO, NV_DMA_TARGET_AGP); - } else { + + } else if (dev_priv->card_type != NV_04) { 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); + } else { + /* NV04 cmdbuf hack, from original ddx.. not sure of it's + * exact reason for existing :) PCI access to cmdbuf in + * VRAM. + */ + cb_obj = nouveau_dma_object_create(dev, + dev_priv->cmdbuf_alloc->start, + dev_priv->cmdbuf_alloc->size, + NV_DMA_ACCESS_RO, + NV_DMA_TARGET_PCI); } if (!cb_obj) { DRM_ERROR("unable to alloc object for command buffer\n"); -- cgit v1.2.3 From b7586ab539e5f8d16b473543ab829d0a4441f87c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 21 Dec 2006 17:43:48 +1100 Subject: nouveau: save/restore endianness flag on FIFO switch This makes my G5 survive glxinfo and nouveau_demo - airlied --- shared-core/nouveau_fifo.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index a611e438..f52f39f9 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -358,7 +358,13 @@ static void nouveau_nv40_context_init(drm_device_t *dev, RAMFC_WR(DMA_GET , init->put_base); RAMFC_WR(DMA_INSTANCE , nouveau_chip_instance_get(dev, cb_obj->instance)); - RAMFC_WR(DMA_FETCH , 0x30086078); + RAMFC_WR(DMA_FETCH , NV_PFIFO_CACH1_DMAF_TRIG_128_BYTES | + NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | + NV_PFIFO_CACH1_DMAF_MAX_REQS_8 | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACH1_BIG_ENDIAN | +#endif + 0x30000000 /* no idea.. */); RAMFC_WR(DMA_SUBROUTINE, init->put_base); RAMFC_WR(GRCTX_INSTANCE, 0); /* XXX */ RAMFC_WR(DMA_TIMESLICE , 0x0001FFFF); @@ -379,7 +385,7 @@ static void nouveau_nv40_context_save(drm_device_t *dev) RAMFC_WR(DMA_INSTANCE , NV_READ(NV_PFIFO_CACH1_DMAI)); RAMFC_WR(DMA_DCOUNT , NV_READ(NV_PFIFO_CACH1_DMA_DCOUNT)); RAMFC_WR(DMA_STATE , NV_READ(NV_PFIFO_CACH1_DMAS)); - //fetch + 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)); -- cgit v1.2.3 From 9e019df75764a7ce79266ceb058307336ddf00ef Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 26 Dec 2006 23:30:26 +1100 Subject: nouveau: Alloc cmdbuf for each channel individually --- shared-core/nouveau_fifo.c | 107 ++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 65 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index f52f39f9..1014d8a6 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -214,12 +214,14 @@ int nouveau_fifo_init(drm_device_t *dev) return 0; } -static int nouveau_dma_init(struct drm_device *dev) +static int +nouveau_fifo_cmdbuf_alloc(struct drm_device *dev, int channel) { drm_nouveau_private_t *dev_priv = dev->dev_private; struct nouveau_config *config = &dev_priv->config; struct mem_block *cb; - int cb_min_size = nouveau_fifo_number(dev) * max(NV03_FIFO_SIZE,PAGE_SIZE); + struct nouveau_object *cb_dma = NULL; + int cb_min_size = max(NV03_FIFO_SIZE,PAGE_SIZE); /* Defaults for unconfigured values */ if (!config->cmdbuf.location) @@ -228,27 +230,40 @@ static int nouveau_dma_init(struct drm_device *dev) config->cmdbuf.size = cb_min_size; cb = nouveau_mem_alloc(dev, 0, config->cmdbuf.size, - config->cmdbuf.location, (DRMFILE)-2); - /* Try defaults if that didn't succeed */ - if (!cb) { - config->cmdbuf.location = NOUVEAU_MEM_FB; - config->cmdbuf.size = cb_min_size; - cb = nouveau_mem_alloc(dev, 0, config->cmdbuf.size, - config->cmdbuf.location, (DRMFILE)-2); - } + config->cmdbuf.location | NOUVEAU_MEM_MAPPED, + (DRMFILE)-2); if (!cb) { DRM_ERROR("Couldn't allocate DMA command buffer.\n"); return DRM_ERR(ENOMEM); } - dev_priv->cmdbuf_ch_size = (uint32_t)cb->size / nouveau_fifo_number(dev); - dev_priv->cmdbuf_alloc = cb; + if (cb->flags & NOUVEAU_MEM_AGP) { + cb_dma = nouveau_dma_object_create(dev, + cb->start, 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->start - drm_get_resource_start(dev, 1), + cb->size, + NV_DMA_ACCESS_RO, NV_DMA_TARGET_VIDMEM); + } else { + /* NV04 cmdbuf hack, from original ddx.. not sure of it's + * exact reason for existing :) PCI access to cmdbuf in + * VRAM. + */ + cb_dma = nouveau_dma_object_create(dev, + cb->start, cb->size, + NV_DMA_ACCESS_RO, NV_DMA_TARGET_PCI); + } - 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"); - DRM_INFO("FIFO size is %dKiB\n", dev_priv->cmdbuf_ch_size>>10); + if (!cb_dma) { + nouveau_mem_free(dev, cb); + DRM_ERROR("Failed to alloc DMA object for command buffer\n"); + return DRM_ERR(ENOMEM); + } + dev_priv->fifos[channel].cmdbuf_mem = cb; + dev_priv->fifos[channel].cmdbuf_obj = cb_dma; return 0; } @@ -407,15 +422,6 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, 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 - */ - if (!dev_priv->cmdbuf_alloc) { - ret = nouveau_dma_init(dev); - if (ret) - return ret; - } - /* * Alright, here is the full story * Nvidia cards have multiple hw fifo contexts (praise them for that, @@ -433,44 +439,17 @@ 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 if (dev_priv->card_type != NV_04) { - 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); - } else { - /* NV04 cmdbuf hack, from original ddx.. not sure of it's - * exact reason for existing :) PCI access to cmdbuf in - * VRAM. - */ - cb_obj = nouveau_dma_object_create(dev, - dev_priv->cmdbuf_alloc->start, - dev_priv->cmdbuf_alloc->size, - NV_DMA_ACCESS_RO, - NV_DMA_TARGET_PCI); - } - if (!cb_obj) { - DRM_ERROR("unable to alloc object for command buffer\n"); - return DRM_ERR(EINVAL); - } - dev_priv->fifos[i].cmdbuf_obj = cb_obj; + /* allocate a command buffer, and create a dma object for the gpu */ + ret = nouveau_fifo_cmdbuf_alloc(dev, i); + if (ret) return ret; + cb_obj = dev_priv->fifos[i].cmdbuf_obj; /* that fifo is used */ dev_priv->fifos[i].used=1; dev_priv->fifos[i].filp=filp; init->channel = i; - init->put_base = i*dev_priv->cmdbuf_ch_size; + init->put_base = 0; dev_priv->cur_fifo = init->channel; nouveau_wait_for_idle(dev); @@ -544,14 +523,9 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, if (ret != 0) return ret; - /* then, the fifo itself */ - init->cmdbuf = dev_priv->cmdbuf_alloc->start; - init->cmdbuf += init->channel * dev_priv->cmdbuf_ch_size; - init->cmdbuf_size = dev_priv->cmdbuf_ch_size; - ret = drm_addmap(dev, init->cmdbuf, init->cmdbuf_size, _DRM_REGISTERS, - 0, &dev_priv->fifos[init->channel].map); - if (ret != 0) - return ret; + /* pass back FIFO map info to the caller */ + init->cmdbuf = dev_priv->fifos[init->channel].cmdbuf_mem->start; + init->cmdbuf_size = dev_priv->fifos[init->channel].cmdbuf_mem->size; /* FIFO has no objects yet */ dev_priv->fifos[init->channel].objs = NULL; @@ -587,6 +561,9 @@ void nouveau_fifo_free(drm_device_t* dev,int n) /* reenable the fifo caches */ NV_WRITE(NV_PFIFO_CACHES, 0x00000001); + /* Deallocate command buffer, and dma object */ + nouveau_mem_free(dev, dev_priv->fifos[n].cmdbuf_mem); + dev_priv->fifo_alloc_count--; } -- cgit v1.2.3 From 2c3bc69ba2b60e4f89b93332fa8da758170b2285 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 2 Jan 2007 14:41:34 +1100 Subject: nouveau: Only clobber PFIFO if no channels are already alloc'd With this change the GPU is responsible for doing the channel switch itself. This is needed for the upcoming NV4x PGRAPH context work as we don't yet know enough to manually swap PGRAPH contexts. --- shared-core/nouveau_fifo.c | 76 +++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 31 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 1014d8a6..9cc579f9 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -414,6 +414,43 @@ static void nouveau_nv40_context_save(drm_device_t *dev) } #undef RAMFC_WR +/* This function should load values from RAMFC into PFIFO, but for now + * it just clobbers PFIFO with what nouveau_fifo_alloc used to setup + * unconditionally. + */ +static void +nouveau_fifo_context_restore(drm_device_t *dev, int channel) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[channel]; + uint32_t cb_inst; + + cb_inst = nouveau_chip_instance_get(dev, chan->cmdbuf_obj->instance); + + // FIXME check if we need to refill the time quota with something like NV_WRITE(0x204C, 0x0003FFFF); + + if (dev_priv->card_type >= NV_40) + NV_WRITE(NV_PFIFO_CACH1_PSH1, 0x00010000|channel); + else + NV_WRITE(NV_PFIFO_CACH1_PSH1, 0x00000100|channel); + + NV_WRITE(NV_PFIFO_CACH1_DMAP, 0 /*RAMFC_DMA_PUT*/); + NV_WRITE(NV_PFIFO_CACH1_DMAG, 0 /*RAMFC_DMA_GET*/); + NV_WRITE(NV_PFIFO_CACH1_DMAI, cb_inst); + NV_WRITE(NV_PFIFO_SIZE , 0x0000FFFF); + NV_WRITE(NV_PFIFO_CACH1_HASH, 0x0000FFFF); + + 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); +#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); +#endif +} + /* allocates and initializes a fifo for user space consumption */ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, DRMFILE filp) { @@ -460,52 +497,29 @@ 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); - /* 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 - */ + /* Construct inital RAMFC for new channel */ if (dev_priv->card_type < NV_10) { nouveau_context_init(dev, init); } 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); nouveau_nv40_context_init(dev, init); } /* enable the fifo dma operation */ NV_WRITE(NV_PFIFO_MODE,NV_READ(NV_PFIFO_MODE)|(1<channel)); + /* setup channel's default get/put values */ NV_WRITE(NV03_FIFO_REGS_DMAPUT(init->channel), init->put_base); NV_WRITE(NV03_FIFO_REGS_DMAGET(init->channel), init->put_base); - // FIXME check if we need to refill the time quota with something like NV_WRITE(0x204C, 0x0003FFFF); - - 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, init->put_base); - NV_WRITE(NV_PFIFO_CACH1_DMAG, init->put_base); - NV_WRITE(NV_PFIFO_CACH1_DMAI, - nouveau_chip_instance_get(dev, cb_obj->instance)); - NV_WRITE(NV_PFIFO_SIZE , 0x0000FFFF); - NV_WRITE(NV_PFIFO_CACH1_HASH, 0x0000FFFF); + /* If this is the first channel, setup PFIFO ourselves. For any + * other case, the GPU will handle this when it switches contexts. + */ + if (dev_priv->fifo_alloc_count == 0) { + nouveau_fifo_context_restore(dev, init->channel); + } - 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); -#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); -#endif NV_WRITE(NV_PFIFO_CACH1_DMAPSH, 0x00000001); NV_WRITE(NV_PFIFO_CACH1_PSH0, 0x00000001); NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001); -- cgit v1.2.3 From 41da9fd2e59b2af295c8f345586030e5a70d7a83 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 2 Jan 2007 15:08:04 +1100 Subject: nouveau: Hook up grctx code for NV4x. This is enough to get grctx switching going on my NV40 and C51 after the binary driver has initialised the card first. Bumping the drm patchlevel because the ddx needs some modifications to have NV4x work at all with these changes. --- shared-core/nouveau_fifo.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 9cc579f9..15d2d928 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -357,11 +357,12 @@ 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; + struct nouveau_fifo *chan = &dev_priv->fifos[init->channel]; + uint32_t fifoctx, cb_inst, grctx_inst; int i; - cb_obj = dev_priv->fifos[init->channel].cmdbuf_obj; + cb_inst = nouveau_chip_instance_get(dev, chan->cmdbuf_obj->instance); + grctx_inst = nouveau_chip_instance_get(dev, chan->ramin_grctx); fifoctx = NV_RAMIN + dev_priv->ramfc_offset + init->channel*128; for (i=0;i<128;i+=4) NV_WRITE(fifoctx + i, 0); @@ -371,8 +372,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 , nouveau_chip_instance_get(dev, - cb_obj->instance)); + RAMFC_WR(DMA_INSTANCE , cb_inst); RAMFC_WR(DMA_FETCH , NV_PFIFO_CACH1_DMAF_TRIG_128_BYTES | NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES | NV_PFIFO_CACH1_DMAF_MAX_REQS_8 | @@ -381,7 +381,7 @@ static void nouveau_nv40_context_init(drm_device_t *dev, #endif 0x30000000 /* no idea.. */); RAMFC_WR(DMA_SUBROUTINE, init->put_base); - RAMFC_WR(GRCTX_INSTANCE, 0); /* XXX */ + RAMFC_WR(GRCTX_INSTANCE, grctx_inst); RAMFC_WR(DMA_TIMESLICE , 0x0001FFFF); } @@ -503,6 +503,11 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, } else if (dev_priv->card_type < NV_40) { nouveau_nv10_context_init(dev, init); } else { + ret = nv40_graph_context_create(dev, init->channel); + if (ret) { + nouveau_fifo_free(dev, init->channel); + return ret; + } nouveau_nv40_context_init(dev, init); } @@ -518,6 +523,19 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, */ if (dev_priv->fifo_alloc_count == 0) { nouveau_fifo_context_restore(dev, init->channel); + if (dev_priv->card_type >= NV_40) { + struct nouveau_fifo *chan; + uint32_t inst; + + chan = &dev_priv->fifos[init->channel]; + inst = nouveau_chip_instance_get(dev, + chan->ramin_grctx); + + /* see comments in nv40_graph_context_restore() */ + NV_WRITE(0x400784, inst); + NV_WRITE(0x40032C, inst | 0x01000000); + NV_WRITE(NV40_PFIFO_GRCTX_INSTANCE, inst); + } } NV_WRITE(NV_PFIFO_CACH1_DMAPSH, 0x00000001); -- cgit v1.2.3 From 91855bb2540bbb824d4d5d437f3eb2d5d06c11ba Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 2 Jan 2007 16:35:00 +1100 Subject: nouveau: oops, forgot to free RAMIN.. --- shared-core/nouveau_fifo.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 15d2d928..9f8c740e 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -590,6 +590,9 @@ void nouveau_fifo_free(drm_device_t* dev,int n) NV_WRITE(NV_RAMIN + dev_priv->ramfc_offset + n*ctx_size + i, 0); } + if (dev_priv->card_type >= NV_40) + nouveau_instmem_free(dev, dev_priv->fifos[n].ramin_grctx); + /* reenable the fifo caches */ NV_WRITE(NV_PFIFO_CACHES, 0x00000001); -- cgit v1.2.3 From f80659bc2967dbed4aed0d44a550bb4a9e4569b5 Mon Sep 17 00:00:00 2001 From: Stephane Marchesin Date: Fri, 5 Jan 2007 19:37:06 +0100 Subject: Cleanup the nv04 fifo code a bit. --- shared-core/nouveau_fifo.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 9f8c740e..ebaa5b88 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -267,31 +267,32 @@ nouveau_fifo_cmdbuf_alloc(struct drm_device *dev, int channel) return 0; } -static void nouveau_context_init(drm_device_t *dev, +#define RAMFC_WR(offset, val) NV_WRITE(fifoctx + NV04_RAMFC_##offset, (val)) +static void nouveau_nv04_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 ctx_addr, ctx_size = 32; + uint32_t fifoctx, ctx_size = 32; int i; cb_obj = dev_priv->fifos[init->channel].cmdbuf_obj; - ctx_addr=NV_RAMIN+dev_priv->ramfc_offset+init->channel*ctx_size; + fifoctx=NV_RAMIN+dev_priv->ramfc_offset+init->channel*ctx_size; // clear the fifo context for(i=0;iput_base); - NV_WRITE(ctx_addr+4,init->put_base); - // that's what is done in nvosdk, but that part of the code is buggy so... - NV_WRITE(ctx_addr+8, nouveau_chip_instance_get(dev, cb_obj->instance)); + RAMFC_WR(DMA_PUT , init->put_base); + RAMFC_WR(DMA_GET , init->put_base); + RAMFC_WR(DMA_INSTANCE , nouveau_chip_instance_get(dev, cb_obj->instance)); #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); + 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+16,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 } +#undef RAMFC_WR #define RAMFC_WR(offset, val) NV_WRITE(fifoctx + NV10_RAMFC_##offset, (val)) static void nouveau_nv10_context_init(drm_device_t *dev, @@ -499,7 +500,7 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, /* Construct inital RAMFC for new channel */ if (dev_priv->card_type < NV_10) { - nouveau_context_init(dev, init); + nouveau_nv04_context_init(dev, init); } else if (dev_priv->card_type < NV_40) { nouveau_nv10_context_init(dev, init); } else { -- cgit v1.2.3 From 9d167f1f4bc89b784248d22bc95dfc15a72d0244 Mon Sep 17 00:00:00 2001 From: Matthieu Castet Date: Fri, 5 Jan 2007 19:40:11 +0100 Subject: Add basic pgraph context for nv10. It only fake a context switch : pgraph state are not save/restored. --- shared-core/nouveau_fifo.c | 1 + 1 file changed, 1 insertion(+) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 9f8c740e..e97e4a68 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -488,6 +488,7 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, init->channel = i; init->put_base = 0; dev_priv->cur_fifo = init->channel; + dev_priv->fifos[i].pgraph_ctx_user = i << 24; nouveau_wait_for_idle(dev); -- cgit v1.2.3 From faa46122993bc5970b3d67933bd81d863a3c4762 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 8 Jan 2007 00:37:39 +1100 Subject: nouveau: avoid allocating vram that's used as instance memory. --- shared-core/nouveau_fifo.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'shared-core/nouveau_fifo.c') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 0e47da08..e5f825e6 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -69,11 +69,10 @@ static int nouveau_fifo_ctx_size(drm_device_t* dev) static int nouveau_fifo_instmem_configure(drm_device_t *dev) { drm_nouveau_private_t *dev_priv = dev->dev_private; - uint32_t obj_base, obj_size; int i; - /* Clear RAMIN */ - for (i=0x00710000; i<0x00800000; i++) + /* Clear start of RAMIN, enough to cover RAMFC/HT/RO basically */ + for (i=0x00710000; i<0x00730000; i++) NV_WRITE(i, 0x00000000); /* FIFO hash table (RAMHT) @@ -139,12 +138,9 @@ static int nouveau_fifo_instmem_configure(drm_device_t *dev) dev_priv->ramfc_offset, dev_priv->ramfc_size); - obj_base = dev_priv->ramfc_offset + dev_priv->ramfc_size; - obj_size = (512*1024) - obj_base; /*XXX: probably wrong on some cards*/ - if (nouveau_instmem_init(dev, obj_base, obj_size)) + if (nouveau_instmem_init(dev, dev_priv->ramfc_offset + + dev_priv->ramfc_size)) return 1; - DRM_DEBUG("RAMIN object space: offset=0x%08x, size=%dKiB\n", - obj_base, obj_size>>10); return 0; } -- cgit v1.2.3