From 22821cf01d6509b7c074e42ae0ef9567e48e97d2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 8 Jan 2007 22:26:35 +1100 Subject: add export symbol for memory manager --- linux-core/drm_sman.c | 1 + 1 file changed, 1 insertion(+) diff --git a/linux-core/drm_sman.c b/linux-core/drm_sman.c index 19a13f3a..e15db6d6 100644 --- a/linux-core/drm_sman.c +++ b/linux-core/drm_sman.c @@ -161,6 +161,7 @@ drm_sman_set_manager(drm_sman_t * sman, unsigned int manager, return 0; } +EXPORT_SYMBOL(drm_sman_set_manager); static drm_owner_item_t *drm_sman_get_owner_item(drm_sman_t * sman, unsigned long owner) -- cgit v1.2.3 From deba42ef32da0c2d0977cdeb639420e1ac1b7f2b Mon Sep 17 00:00:00 2001 From: Stephane Marchesin Date: Mon, 8 Jan 2007 20:55:57 +0100 Subject: nouveau: fix nv4a context size. --- shared-core/nv40_graph.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-core/nv40_graph.c b/shared-core/nv40_graph.c index 53f55bce..3e1b2f6f 100644 --- a/shared-core/nv40_graph.c +++ b/shared-core/nv40_graph.c @@ -10,7 +10,7 @@ */ #define NV40_GRCTX_SIZE (175*1024) #define NV43_GRCTX_SIZE (70*1024) -#define NV4A_GRCTX_SIZE (60*1024) +#define NV4A_GRCTX_SIZE (64*1024) #define NV4E_GRCTX_SIZE (25*1024) /*TODO: deciper what each offset in the context represents. The below -- cgit v1.2.3 From a70aedd5fc78a162aeb681d47a75edcc831ed3f3 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 9 Jan 2007 13:38:36 +1100 Subject: novueau: try resource 3 if resource 2 is 0 length This happens on my NV43 PPC --- shared-core/nouveau_state.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index 44f8c1aa..1e0587f6 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -66,8 +66,12 @@ int nouveau_firstopen(struct drm_device *dev) /* map larger RAMIN aperture on NV40 cards */ if (dev_priv->card_type >= NV_40) { - ret = drm_addmap(dev, drm_get_resource_start(dev, 2), - drm_get_resource_len(dev, 2), + int ramin_resource = 2; + if (drm_get_resource_len(dev, ramin_resource) == 0) + ramin_resource = 3; + + ret = drm_addmap(dev, drm_get_resource_start(dev, ramin_resource), + drm_get_resource_len(dev, ramin_resource), _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->ramin); -- cgit v1.2.3 From f6ba3b2603c58b9f5624fd4a97511b2913ec7866 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 9 Jan 2007 15:51:29 +1100 Subject: ttm: make ttm alloc/free into alloc_pages/free_pages Add a vmalloc flag to the page flags --- linux-core/drm_ttm.c | 39 ++++++++++++++++++++------------------- linux-core/drm_ttm.h | 1 + 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index 1c9b1cf7..c17c41cb 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -44,34 +44,39 @@ static void drm_ttm_cache_flush(void) * Use kmalloc if possible. Otherwise fall back to vmalloc. */ -static void *ttm_alloc(unsigned long size, int type) +static void ttm_alloc_pages(drm_ttm_t *ttm) { - void *ret = NULL; + unsigned long size = ttm->num_pages * sizeof(*ttm->pages); + ttm->pages = NULL; if (drm_alloc_memctl(size)) - return NULL; + return; + if (size <= PAGE_SIZE) { - ret = drm_alloc(size, type); + ttm->pages = drm_calloc(1, size, DRM_MEM_TTM); } - if (!ret) { - ret = vmalloc(size); + if (!ttm->pages) { + ttm->pages = vmalloc_user(size); + if (ttm->pages) + ttm->page_flags |= DRM_TTM_PAGE_VMALLOC; } - if (!ret) { + if (!ttm->pages) { drm_free_memctl(size); } - return ret; } -static void ttm_free(void *pointer, unsigned long size, int type) +static void ttm_free_pages(drm_ttm_t *ttm) { + unsigned long size = ttm->num_pages * sizeof(*ttm->pages); - if ((unsigned long)pointer >= VMALLOC_START && - (unsigned long)pointer <= VMALLOC_END) { - vfree(pointer); + if (ttm->page_flags & DRM_TTM_PAGE_VMALLOC) { + vfree(ttm->pages); + ttm->page_flags &= ~DRM_TTM_PAGE_VMALLOC; } else { - drm_free(pointer, size, type); + drm_free(ttm->pages, size, DRM_MEM_TTM); } drm_free_memctl(size); + ttm->pages = NULL; } /* @@ -198,9 +203,7 @@ int drm_destroy_ttm(drm_ttm_t * ttm) --bm->cur_pages; } } - ttm_free(ttm->pages, ttm->num_pages * sizeof(*ttm->pages), - DRM_MEM_TTM); - ttm->pages = NULL; + ttm_free_pages(ttm); } drm_ctl_free(ttm, sizeof(*ttm), DRM_MEM_TTM); @@ -277,14 +280,12 @@ static drm_ttm_t *drm_init_ttm(struct drm_device *dev, unsigned long size) * Account also for AGP module memory usage. */ - ttm->pages = ttm_alloc(ttm->num_pages * sizeof(*ttm->pages), - DRM_MEM_TTM); + ttm_alloc_pages(ttm); if (!ttm->pages) { drm_destroy_ttm(ttm); DRM_ERROR("Failed allocating page table\n"); return NULL; } - memset(ttm->pages, 0, ttm->num_pages * sizeof(*ttm->pages)); ttm->be = bo_driver->create_ttm_backend_entry(dev); if (!ttm->be) { drm_destroy_ttm(ttm); diff --git a/linux-core/drm_ttm.h b/linux-core/drm_ttm.h index 11a13754..796f2317 100644 --- a/linux-core/drm_ttm.h +++ b/linux-core/drm_ttm.h @@ -141,5 +141,6 @@ static __inline__ drm_ttm_t *drm_ttm_from_object(drm_ttm_object_t * to) #define DRM_TTM_PAGE_USED 0x02 #define DRM_TTM_PAGE_BOUND 0x04 #define DRM_TTM_PAGE_PRESENT 0x08 +#define DRM_TTM_PAGE_VMALLOC 0x10 #endif -- cgit v1.2.3 From ec12209c763d0ea258b3e1e567bf097f9e918265 Mon Sep 17 00:00:00 2001 From: Stephane Marchesin Date: Wed, 10 Jan 2007 04:42:09 +0100 Subject: nouveau: Don't use DRIVER_USE_MTRR, we already setup our own mtrr over vram. --- linux-core/nouveau_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-core/nouveau_drv.c b/linux-core/nouveau_drv.c index 91de2b31..ac030d89 100644 --- a/linux-core/nouveau_drv.c +++ b/linux-core/nouveau_drv.c @@ -38,7 +38,7 @@ extern int nouveau_max_ioctl; static int probe(struct pci_dev *pdev, const struct pci_device_id *ent); static struct drm_driver driver = { .driver_features = - DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | + DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, .load = nouveau_load, .firstopen = nouveau_firstopen, -- cgit v1.2.3 From ac076cb9aff976e8fae567cfa82a898bfc2712e8 Mon Sep 17 00:00:00 2001 From: "Jeremy Kolb jkolb@brandeis.edu" Date: Tue, 9 Jan 2007 23:12:37 -0500 Subject: nouveau: Fill in context_init for nv10-nv3x. Fill in the context with the values from PFIFO_CACH1. This should work from nv10 through the nv30 series. --- linux-core/nouveau_fifo.c | 679 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 678 insertions(+), 1 deletion(-) mode change 120000 => 100644 linux-core/nouveau_fifo.c diff --git a/linux-core/nouveau_fifo.c b/linux-core/nouveau_fifo.c deleted file mode 120000 index 60759a57..00000000 --- a/linux-core/nouveau_fifo.c +++ /dev/null @@ -1 +0,0 @@ -../shared-core/nouveau_fifo.c \ No newline at end of file diff --git a/linux-core/nouveau_fifo.c b/linux-core/nouveau_fifo.c new file mode 100644 index 00000000..7062bb81 --- /dev/null +++ b/linux-core/nouveau_fifo.c @@ -0,0 +1,678 @@ +/* + * 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; + } +} + +/* 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 + ***********************************/ + +/* voir nv_xaa.c : NVResetGraphics + * mémoire mappée par nv_driver.c : NVMapMem + * voir nv_driver.c : NVPreInit + */ + +static int nouveau_fifo_instmem_configure(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + int 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) + * 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 + */ + 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, + dev_priv->ramfc_size); + + if (nouveau_instmem_init(dev, dev_priv->ramfc_offset + + dev_priv->ramfc_size)) + return 1; + + return 0; +} + +int nouveau_fifo_init(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + int ret; + + 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); + /* 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_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 + 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_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); + + return 0; +} + +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; + struct nouveau_object *cb_dma = NULL; + int cb_min_size = max(NV03_FIFO_SIZE,PAGE_SIZE); + + /* 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 | NOUVEAU_MEM_MAPPED, + (DRMFILE)-2); + if (!cb) { + DRM_ERROR("Couldn't allocate DMA command buffer.\n"); + return DRM_ERR(ENOMEM); + } + + 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); + } + + 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; +} + +#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 fifoctx, ctx_size = 32; + int i; + + cb_obj = dev_priv->fifos[init->channel].cmdbuf_obj; + + fifoctx=NV_RAMIN+dev_priv->ramfc_offset+init->channel*ctx_size; + // clear the fifo context + for(i=0;iput_base); + RAMFC_WR(DMA_GET , init->put_base); + 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|NV_PFIFO_CACH1_DMAF_MAX_REQS_4|NV_PFIFO_CACH1_BIG_ENDIAN); +#else + 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, + drm_nouveau_fifo_alloc_t *init) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[init->channel]; + struct nouveau_object *cb_obj; + uint32_t fifoctx, cb_inst, ctx_size = 64; + int i; + + cb_obj = dev_priv->fifos[init->channel].cmdbuf_obj; + cb_inst = nouveau_chip_instance_get(dev, chan->cmdbuf_obj->instance); + fifoctx = NV_RAMIN + dev_priv->ramfc_offset + init->channel * ctx_size; + for (i = 0; i < ctx_size; i += 4) + NV_WRITE(fifoctx + i, 0); + RAMFC_WR(DMA_PUT, init->put_base); + RAMFC_WR(DMA_GET, init->put_base); + RAMFC_WR(REF_CNT, NV_READ(NV_PFIFO_CACH1_REF_CNT)); + RAMFC_WR(DMA_INSTANCE, (NV_READ(NV_PFIFO_CACH1_DMA_DCOUNT) << 16) | + NV_READ(NV_PFIFO_CACH1_DMAI)); + RAMFC_WR(DMA_STATE, NV_READ(NV_PFIFO_CACH1_DMAS)); + 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 | +#else + 0x00000000); +#endif + 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, 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_DMASR)); +} +#undef RAMFC_WR + +#define RAMFC_WR(offset, val) NV_WRITE(fifoctx + NV40_RAMFC_##offset, (val)) +static void nouveau_nv40_context_init(drm_device_t *dev, + drm_nouveau_fifo_alloc_t *init) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[init->channel]; + uint32_t fifoctx, cb_inst, grctx_inst; + int i; + + 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); + + /* 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_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 | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACH1_BIG_ENDIAN | +#endif + 0x30000000 /* no idea.. */); + RAMFC_WR(DMA_SUBROUTINE, init->put_base); + RAMFC_WR(GRCTX_INSTANCE, grctx_inst); + RAMFC_WR(DMA_TIMESLICE , 0x0001FFFF); +} + +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)); + 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)); + 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 + +/* 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) +{ + int i; + int ret; + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_object *cb_obj; + + /* + * Alright, here is the full story + * Nvidia cards have multiple hw fifo contexts (praise them for that, + * no complicated crash-prone context switches) + * 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) + break; + + DRM_INFO("Allocating FIFO number %d\n", i); + /* no more fifos. you lost. */ + if (i==nouveau_fifo_number(dev)) + return DRM_ERR(EINVAL); + + /* 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 = 0; + dev_priv->cur_fifo = init->channel; + dev_priv->fifos[i].pgraph_ctx_user = i << 24; + + nouveau_wait_for_idle(dev); + + /* 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); + + /* Construct inital RAMFC for new channel */ + if (dev_priv->card_type < NV_10) { + nouveau_nv04_context_init(dev, 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); + } + + /* 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); + + /* 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); + 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); + 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); + + /* make the fifo available to user space */ + /* first, the fifo control regs */ + 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[init->channel].regs); + 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; + dev_priv->fifo_alloc_count++; + + DRM_INFO("%s: initialised FIFO %d\n", __func__, init->channel); + return 0; +} + +/* stops a fifo */ +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); + + /* disable the fifo caches */ + NV_WRITE(NV_PFIFO_CACHES, 0x00000000); + + NV_WRITE(NV_PFIFO_MODE,NV_READ(NV_PFIFO_MODE)&~(1<ramfc_offset + n*ctx_size + i)); + 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); + + /* Deallocate command buffer, and dma object */ + nouveau_mem_free(dev, dev_priv->fifos[n].cmdbuf_mem); + + dev_priv->fifo_alloc_count--; +} + +/* 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].used && dev_priv->fifos[i].filp==filp) + nouveau_fifo_free(dev,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; + if (i==nouveau_fifo_number(dev)) + i=0; + DRM_DEBUG("%s: new cur_fifo is %d\n", __func__, i); + dev_priv->cur_fifo = i; + } + +/* if (dev_priv->cmdbuf_alloc) + nouveau_fifo_init(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].used && dev_priv->fifos[i].filp == filp) + return i; + return -1; +} + +/*********************************** + * ioctls wrapping the functions + ***********************************/ + +static int nouveau_ioctl_fifo_alloc(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_nouveau_fifo_alloc_t init; + int res; + DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_fifo_alloc_t __user *) data, sizeof(init)); + + res=nouveau_fifo_alloc(dev,&init,filp); + if (!res) + DRM_COPY_TO_USER_IOCTL((drm_nouveau_fifo_alloc_t __user *)data, init, sizeof(init)); + + return res; +} + +/*********************************** + * finally, the ioctl table + ***********************************/ + +drm_ioctl_desc_t nouveau_ioctls[] = { + [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}, + [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 125f3ff36796c8d28c29e960247fdd42d4cd877c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 10 Jan 2007 15:19:47 +1100 Subject: Revert "nouveau: Fill in context_init for nv10-nv3x." This reverts ac076cb9aff976e8fae567cfa82a898bfc2712e8 commit. Well it didn't do anything interesting... --- linux-core/nouveau_fifo.c | 679 +--------------------------------------------- 1 file changed, 1 insertion(+), 678 deletions(-) mode change 100644 => 120000 linux-core/nouveau_fifo.c diff --git a/linux-core/nouveau_fifo.c b/linux-core/nouveau_fifo.c deleted file mode 100644 index 7062bb81..00000000 --- a/linux-core/nouveau_fifo.c +++ /dev/null @@ -1,678 +0,0 @@ -/* - * 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; - } -} - -/* 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 - ***********************************/ - -/* voir nv_xaa.c : NVResetGraphics - * mémoire mappée par nv_driver.c : NVMapMem - * voir nv_driver.c : NVPreInit - */ - -static int nouveau_fifo_instmem_configure(drm_device_t *dev) -{ - drm_nouveau_private_t *dev_priv = dev->dev_private; - int 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) - * 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 - */ - 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, - dev_priv->ramfc_size); - - if (nouveau_instmem_init(dev, dev_priv->ramfc_offset + - dev_priv->ramfc_size)) - return 1; - - return 0; -} - -int nouveau_fifo_init(drm_device_t *dev) -{ - drm_nouveau_private_t *dev_priv = dev->dev_private; - int ret; - - 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); - /* 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_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 - 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_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); - - return 0; -} - -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; - struct nouveau_object *cb_dma = NULL; - int cb_min_size = max(NV03_FIFO_SIZE,PAGE_SIZE); - - /* 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 | NOUVEAU_MEM_MAPPED, - (DRMFILE)-2); - if (!cb) { - DRM_ERROR("Couldn't allocate DMA command buffer.\n"); - return DRM_ERR(ENOMEM); - } - - 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); - } - - 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; -} - -#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 fifoctx, ctx_size = 32; - int i; - - cb_obj = dev_priv->fifos[init->channel].cmdbuf_obj; - - fifoctx=NV_RAMIN+dev_priv->ramfc_offset+init->channel*ctx_size; - // clear the fifo context - for(i=0;iput_base); - RAMFC_WR(DMA_GET , init->put_base); - 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|NV_PFIFO_CACH1_DMAF_MAX_REQS_4|NV_PFIFO_CACH1_BIG_ENDIAN); -#else - 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, - drm_nouveau_fifo_alloc_t *init) -{ - drm_nouveau_private_t *dev_priv = dev->dev_private; - struct nouveau_fifo *chan = &dev_priv->fifos[init->channel]; - struct nouveau_object *cb_obj; - uint32_t fifoctx, cb_inst, ctx_size = 64; - int i; - - cb_obj = dev_priv->fifos[init->channel].cmdbuf_obj; - cb_inst = nouveau_chip_instance_get(dev, chan->cmdbuf_obj->instance); - fifoctx = NV_RAMIN + dev_priv->ramfc_offset + init->channel * ctx_size; - for (i = 0; i < ctx_size; i += 4) - NV_WRITE(fifoctx + i, 0); - RAMFC_WR(DMA_PUT, init->put_base); - RAMFC_WR(DMA_GET, init->put_base); - RAMFC_WR(REF_CNT, NV_READ(NV_PFIFO_CACH1_REF_CNT)); - RAMFC_WR(DMA_INSTANCE, (NV_READ(NV_PFIFO_CACH1_DMA_DCOUNT) << 16) | - NV_READ(NV_PFIFO_CACH1_DMAI)); - RAMFC_WR(DMA_STATE, NV_READ(NV_PFIFO_CACH1_DMAS)); - 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 | -#else - 0x00000000); -#endif - 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, 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_DMASR)); -} -#undef RAMFC_WR - -#define RAMFC_WR(offset, val) NV_WRITE(fifoctx + NV40_RAMFC_##offset, (val)) -static void nouveau_nv40_context_init(drm_device_t *dev, - drm_nouveau_fifo_alloc_t *init) -{ - drm_nouveau_private_t *dev_priv = dev->dev_private; - struct nouveau_fifo *chan = &dev_priv->fifos[init->channel]; - uint32_t fifoctx, cb_inst, grctx_inst; - int i; - - 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); - - /* 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_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 | -#ifdef __BIG_ENDIAN - NV_PFIFO_CACH1_BIG_ENDIAN | -#endif - 0x30000000 /* no idea.. */); - RAMFC_WR(DMA_SUBROUTINE, init->put_base); - RAMFC_WR(GRCTX_INSTANCE, grctx_inst); - RAMFC_WR(DMA_TIMESLICE , 0x0001FFFF); -} - -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)); - 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)); - 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 - -/* 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) -{ - int i; - int ret; - drm_nouveau_private_t *dev_priv = dev->dev_private; - struct nouveau_object *cb_obj; - - /* - * Alright, here is the full story - * Nvidia cards have multiple hw fifo contexts (praise them for that, - * no complicated crash-prone context switches) - * 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) - break; - - DRM_INFO("Allocating FIFO number %d\n", i); - /* no more fifos. you lost. */ - if (i==nouveau_fifo_number(dev)) - return DRM_ERR(EINVAL); - - /* 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 = 0; - dev_priv->cur_fifo = init->channel; - dev_priv->fifos[i].pgraph_ctx_user = i << 24; - - nouveau_wait_for_idle(dev); - - /* 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); - - /* Construct inital RAMFC for new channel */ - if (dev_priv->card_type < NV_10) { - nouveau_nv04_context_init(dev, 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); - } - - /* 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); - - /* 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); - 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); - 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); - - /* make the fifo available to user space */ - /* first, the fifo control regs */ - 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[init->channel].regs); - 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; - dev_priv->fifo_alloc_count++; - - DRM_INFO("%s: initialised FIFO %d\n", __func__, init->channel); - return 0; -} - -/* stops a fifo */ -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); - - /* disable the fifo caches */ - NV_WRITE(NV_PFIFO_CACHES, 0x00000000); - - NV_WRITE(NV_PFIFO_MODE,NV_READ(NV_PFIFO_MODE)&~(1<ramfc_offset + n*ctx_size + i)); - 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); - - /* Deallocate command buffer, and dma object */ - nouveau_mem_free(dev, dev_priv->fifos[n].cmdbuf_mem); - - dev_priv->fifo_alloc_count--; -} - -/* 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].used && dev_priv->fifos[i].filp==filp) - nouveau_fifo_free(dev,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; - if (i==nouveau_fifo_number(dev)) - i=0; - DRM_DEBUG("%s: new cur_fifo is %d\n", __func__, i); - dev_priv->cur_fifo = i; - } - -/* if (dev_priv->cmdbuf_alloc) - nouveau_fifo_init(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].used && dev_priv->fifos[i].filp == filp) - return i; - return -1; -} - -/*********************************** - * ioctls wrapping the functions - ***********************************/ - -static int nouveau_ioctl_fifo_alloc(DRM_IOCTL_ARGS) -{ - DRM_DEVICE; - drm_nouveau_fifo_alloc_t init; - int res; - DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_fifo_alloc_t __user *) data, sizeof(init)); - - res=nouveau_fifo_alloc(dev,&init,filp); - if (!res) - DRM_COPY_TO_USER_IOCTL((drm_nouveau_fifo_alloc_t __user *)data, init, sizeof(init)); - - return res; -} - -/*********************************** - * finally, the ioctl table - ***********************************/ - -drm_ioctl_desc_t nouveau_ioctls[] = { - [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}, - [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); - - diff --git a/linux-core/nouveau_fifo.c b/linux-core/nouveau_fifo.c new file mode 120000 index 00000000..60759a57 --- /dev/null +++ b/linux-core/nouveau_fifo.c @@ -0,0 +1 @@ +../shared-core/nouveau_fifo.c \ No newline at end of file -- cgit v1.2.3 From 8ff026723cf170034173052a58c650c8c1f28c0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Thu, 11 Jan 2007 09:02:07 +0100 Subject: radeon: Fix u32 overflows when determining AGP base address in card space. The overflows could lead to the AGP aperture overlapping the framebuffer area in the card's address space when the latter is located at the very end of the 32 bit address space, which would result in a freeze on X server startup, probably because the card read commands from the framebuffer instead of from AGP. See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=392915 . --- shared-core/radeon_cp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 4135f4d5..0fa6535d 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -1563,8 +1563,8 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) if (dev_priv->flags & RADEON_IS_AGP) { base = dev->agp->base; /* Check if valid */ - if ((base + dev_priv->gart_size) > dev_priv->fb_location && - base < (dev_priv->fb_location + dev_priv->fb_size)) { + if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location && + base < (dev_priv->fb_location + dev_priv->fb_size - 1)) { DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n", dev->agp->base); base = 0; @@ -1574,8 +1574,8 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) /* If not or if AGP is at 0 (Macs), try to put it elsewhere */ if (base == 0) { base = dev_priv->fb_location + dev_priv->fb_size; - if (((base + dev_priv->gart_size) & 0xfffffffful) - < base) + if (base < dev_priv->fb_location || + ((base + dev_priv->gart_size) & 0xfffffffful) < base) base = dev_priv->fb_location - dev_priv->gart_size; } -- cgit v1.2.3 From 4297a83b48664b2b6a6dc0a72a4d11b043f34778 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Fri, 12 Jan 2007 00:13:05 -0500 Subject: nouveau: get nv30 context switching to work. * Pulled in some registers from nv10reg.h. Needed for context switching. * Filled in nv30 graphics context (based on nv40_graph.c). * Figure out nv30 context table, set up on context creation. Allows the cards automatic switching to work. --- linux-core/Makefile.kernel | 2 +- shared-core/nouveau_drv.h | 8 ++ shared-core/nouveau_fifo.c | 139 +++++++++++++++++++------- shared-core/nouveau_reg.h | 15 +++ shared-core/nv30_graph.c | 243 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 369 insertions(+), 38 deletions(-) create mode 100644 shared-core/nv30_graph.c diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index b4ac2642..30df582c 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -22,7 +22,7 @@ i830-objs := i830_drv.o i830_dma.o i830_irq.o i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \ i915_buffer.o nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \ - nouveau_object.o nouveau_irq.o nv40_graph.o + nouveau_object.o nouveau_irq.o nv30_graph.o nv40_graph.o radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o sis-objs := sis_drv.o sis_mm.o ffb-objs := ffb_drv.o ffb_context.o diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 6b09046c..219ba123 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -142,6 +142,10 @@ typedef struct drm_nouveau_private { struct mem_block *fb_nomap_heap; struct mem_block *ramin_heap; + /* context table pointed to be NV_PGRAPH_CHANNEL_CTX_TABLE (0x400780) */ + uint32_t ctx_table_size; + struct mem_block *ctx_table; + struct nouveau_config config; } drm_nouveau_private_t; @@ -198,6 +202,10 @@ extern void nouveau_irq_preinstall(drm_device_t*); extern void nouveau_irq_postinstall(drm_device_t*); extern void nouveau_irq_uninstall(drm_device_t*); +/* nv30_graph.c */ +extern int nv30_graph_init(drm_device_t *dev); +extern int nv30_graph_context_create(drm_device_t *dev, int channel); + /* nv40_graph.c */ extern int nv40_graph_init(drm_device_t *dev); extern int nv40_graph_context_create(drm_device_t *dev, int channel); diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index e5f825e6..d41972b2 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -265,9 +265,9 @@ nouveau_fifo_cmdbuf_alloc(struct drm_device *dev, int channel) #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_fifo_alloc_t *init) { - drm_nouveau_private_t *dev_priv = dev->dev_private; + drm_nouveau_private_t *dev_priv = dev->dev_private; struct nouveau_object *cb_obj; uint32_t fifoctx, ctx_size = 32; int i; @@ -275,53 +275,109 @@ static void nouveau_nv04_context_init(drm_device_t *dev, cb_obj = dev_priv->fifos[init->channel].cmdbuf_obj; fifoctx=NV_RAMIN+dev_priv->ramfc_offset+init->channel*ctx_size; - // clear the fifo context - for(i=0;iput_base); + 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 - 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); + 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 - 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); + 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, - drm_nouveau_fifo_alloc_t *init) + drm_nouveau_fifo_alloc_t *init) { - drm_nouveau_private_t *dev_priv = dev->dev_private; + 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 , 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 | + NV_PFIFO_CACH1_DMAF_MAX_REQS_4 | + NV_PFIFO_CACH1_BIG_ENDIAN); +#else + + 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, 0); + +} + +static void nouveau_nv30_context_init(drm_device_t *dev, + drm_nouveau_fifo_alloc_t *init) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[init->channel]; struct nouveau_object *cb_obj; - uint32_t fifoctx; + uint32_t fifoctx, grctx_inst, cb_inst, ctx_size = 64; 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 , nouveau_chip_instance_get(dev, - cb_obj->instance)); + 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 * ctx_size; + + for (i = 0; i < ctx_size; i += 4) + NV_WRITE(fifoctx + i, 0); + + RAMFC_WR(DMA_PUT, init->put_base); + RAMFC_WR(DMA_GET, init->put_base); + RAMFC_WR(REF_CNT, NV_READ(NV_PFIFO_CACH1_REF_CNT)); + RAMFC_WR(DMA_INSTANCE, cb_inst); + RAMFC_WR(DMA_STATE, NV_READ(NV_PFIFO_CACH1_DMAS)); + 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 - 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); + NV_PFIFO_CACH1_BIG_ENDIAN | #else - 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); + 0x00000000); #endif - RAMFC_WR(DMA_SUBROUTINE, 0); + + 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)); + NV_WRITE(NV_PGRAPH_CHANNEL_CTX_SIZE, grctx_inst); /* Misnomer. Really a ptr to the grctx */ + + /* + * TODO: We need to put this somewhere... + */ + /* INSTANCE_WR(dev_priv->ctx_table, init->channel, grctx_inst); */ + RAMFC_WR(DMA_SUBROUTINE, init->put_base); } static void nouveau_nv10_context_save(drm_device_t *dev) @@ -498,8 +554,15 @@ 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_nv04_context_init(dev, init); - } else if (dev_priv->card_type < NV_40) { - nouveau_nv10_context_init(dev, init); + } else if (dev_priv->card_type < NV_30) { + nouveau_nv10_context_init(dev, init); + } else if (dev_priv->card_type < NV_40) { + ret = nv30_graph_context_create(dev, init->channel); + if (ret) { + nouveau_fifo_free(dev, init->channel); + return ret; + } + nouveau_nv30_context_init(dev, init); } else { ret = nv40_graph_context_create(dev, init->channel); if (ret) { @@ -521,7 +584,7 @@ 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) { + if (dev_priv->card_type >= NV_30) { struct nouveau_fifo *chan; uint32_t inst; @@ -530,9 +593,11 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, 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_PGRAPH_CHANNEL_CTX_SIZE, inst); + if (dev_priv->card_type >= NV_40) { + NV_WRITE(0x40032C, inst | 0x01000000); + NV_WRITE(NV40_PFIFO_GRCTX_INSTANCE, inst); + } } } diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h index 23fce39a..97d81048 100644 --- a/shared-core/nouveau_reg.h +++ b/shared-core/nouveau_reg.h @@ -71,6 +71,21 @@ #define NV_PGRAPH_FIFO 0x00400720 #define NV_PGRAPH_FFINTFC_ST2 0x00400764 +/* NV-Register NV_PGRAPH_CHANNEL_CTX_TABLE */ +#define NV_PGRAPH_CHANNEL_CTX_TABLE 0x00400780 +#define NV_PGRAPH_CHANNEL_CTX_TABLE_INST 0x0000FFFF +#define NV_PGRAPH_CHANNEL_CTX_TABLE_INST_0 0x00000000 + +/* NV-Register NV_PGRAPH_CHANNEL_CTX_SIZE */ +#define NV_PGRAPH_CHANNEL_CTX_SIZE 0x00400784 +#define NV_PGRAPH_CHANNEL_CTX_SIZE_VALUE 0x0000FFFF +#define NV_PGRAPH_CHANNEL_CTX_SIZE_VALUE_INIT 0x00001000 + +/* NV-Register NV_PGRAPH_CHANNEL_CTX_POINTER */ +#define NV_PGRAPH_CHANNEL_CTX_POINTER 0x00400788 +#define NV_PGRAPH_CHANNEL_CTX_POINTER_INST 0x0000FFFF +#define NV_PGRAPH_CHANNEL_CTX_POINTER_INST_0 0x00000000 + /* It's a guess that this works on NV03. Confirmed on NV04, though */ #define NV_PFIFO_DELAY_0 0x00002040 #define NV_PFIFO_DMA_TIMESLICE 0x00002044 diff --git a/shared-core/nv30_graph.c b/shared-core/nv30_graph.c new file mode 100644 index 00000000..dbc39490 --- /dev/null +++ b/shared-core/nv30_graph.c @@ -0,0 +1,243 @@ +/* + * Based on nv40_graph.c + * Someday this will all go away... + */ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +/* + * TODO: In the dump start seems to be 7654b0 while end is 76ac28. + * This is obviously not the correct size. + */ +#define NV30_GRCTX_SIZE (22392) + +/*TODO: deciper what each offset in the context represents. The below + * contexts are taken from dumps just after the 3D object is + * created. + */ +static void nv30_graph_context_init(drm_device_t *dev, struct mem_block *ctx) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + int i; + + INSTANCE_WR(ctx, 0x28/4, 0x10000000); + INSTANCE_WR(ctx, 0x40c/4, 0x00000101); + INSTANCE_WR(ctx, 0x420/4, 0x00000111); + INSTANCE_WR(ctx, 0x424/4, 0x00000060); + INSTANCE_WR(ctx, 0x440/4, 0x00000080); + INSTANCE_WR(ctx, 0x444/4, 0xffff0000); + INSTANCE_WR(ctx, 0x448/4, 0x00000001); + INSTANCE_WR(ctx, 0x45c/4, 0x44400000); + INSTANCE_WR(ctx, 0x448/4, 0xffff0000); + INSTANCE_WR(ctx, 0x4dc/4, 0xfff00000); + INSTANCE_WR(ctx, 0x4e0/4, 0xfff00000); + INSTANCE_WR(ctx, 0x4e8/4, 0x00011100); + + for (i = 0x504; i <= 0x540; i += 4) + INSTANCE_WR(ctx, i/4, 0x7ff00000); + + INSTANCE_WR(ctx, 0x54c/4, 0x4b7fffff); + INSTANCE_WR(ctx, 0x588/4, 0x00000080); + INSTANCE_WR(ctx, 0x58c/4, 0x30201000); + INSTANCE_WR(ctx, 0x590/4, 0x70605040); + INSTANCE_WR(ctx, 0x594/4, 0xb8a89888); + INSTANCE_WR(ctx, 0x598/4, 0xf8e8d8c8); + INSTANCE_WR(ctx, 0x5ac/4, 0xb0000000); + + for (i = 0x604; i <= 0x640; i += 4) + INSTANCE_WR(ctx, i/4, 0x00010588); + + for (i = 0x644; i <= 0x680; i += 4) + INSTANCE_WR(ctx, i/4, 0x00030303); + + for (i = 0x6c4; i <= 0x700; i += 4) + INSTANCE_WR(ctx, i/4, 0x0008aae4); + + for (i = 0x704; i <= 0x740; i += 4) + INSTANCE_WR(ctx, i/4, 0x1012000); + + for (i = 0x744; i <= 0x780; i += 4) + INSTANCE_WR(ctx, i/4, 0x0080008); + + INSTANCE_WR(ctx, 0x860/4, 0x00040000); + INSTANCE_WR(ctx, 0x864/4, 0x00010000); + INSTANCE_WR(ctx, 0x868/4, 0x00040000); + INSTANCE_WR(ctx, 0x86c/4, 0x00040000); + INSTANCE_WR(ctx, 0x870/4, 0x00040000); + INSTANCE_WR(ctx, 0x874/4, 0x00040000); + + for (i = 0x00; i <= 0x1170; i += 0x10) + { + INSTANCE_WR(ctx, (0x1f24 + i)/4, 0x000c001b); + INSTANCE_WR(ctx, (0x1f20 + i)/4, 0x0436086c); + INSTANCE_WR(ctx, (0x1f1c + i)/4, 0x10700ff9); + } + + INSTANCE_WR(ctx, 0x30bc/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x30c0/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x30c4/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x30c8/4, 0x0000ffff); + + INSTANCE_WR(ctx, 0x380c/4, 0x3f800000); + INSTANCE_WR(ctx, 0x3450/4, 0x3f800000); + INSTANCE_WR(ctx, 0x3820/4, 0x3f800000); + INSTANCE_WR(ctx, 0x3854/4, 0x3f800000); + INSTANCE_WR(ctx, 0x3850/4, 0x3f000000); + INSTANCE_WR(ctx, 0x384c/4, 0x40000000); + INSTANCE_WR(ctx, 0x3868/4, 0xbf800000); + INSTANCE_WR(ctx, 0x3860/4, 0x3f800000); + INSTANCE_WR(ctx, 0x386c/4, 0x40000000); + INSTANCE_WR(ctx, 0x3870/4, 0xbf800000); + + for (i = 0x4e0; i <= 0x4e1c; i += 4) + INSTANCE_WR(ctx, i/4, 0x001c527d); + INSTANCE_WR(ctx, 0x4e40, 0x001c527c); + + INSTANCE_WR(ctx, 0x5680/4, 0x000a0000); + INSTANCE_WR(ctx, 0x87c/4, 0x10000000); + INSTANCE_WR(ctx, 0x28/4, 0x10000011); +} + + +int +nv30_graph_context_create(drm_device_t *dev, int channel) +{ + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[channel]; + void (*ctx_init)(drm_device_t *, struct mem_block *); + unsigned int ctx_size; + int i, chipset; + + chipset = (NV_READ(NV_PMC_BOOT_0) & 0x0ff00000) >> 20; + switch (chipset) { + default: + ctx_size = NV30_GRCTX_SIZE; + ctx_init = nv30_graph_context_init; + break; + } + + /* Alloc and clear RAMIN to store the context */ + chan->ramin_grctx = nouveau_instmem_alloc(dev, ctx_size, 4); + if (!chan->ramin_grctx) + return DRM_ERR(ENOMEM); + for (i=0; iramin_grctx, i/4, 0x00000000); + + /* Initialise default context values */ + ctx_init(dev, chan->ramin_grctx); + + return 0; +} +#if 0 +/* Save current context (from PGRAPH) into the channel's context + *XXX: fails sometimes, not sure why.. + */ +void +nv40_graph_context_save_current(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + uint32_t instance; + int i; + + NV_WRITE(NV_PGRAPH_FIFO, 0); + + instance = NV_READ(0x40032C) & 0xFFFFF; + if (!instance) { + NV_WRITE(NV_PGRAPH_FIFO, 1); + return; + } + + NV_WRITE(0x400784, instance); + NV_WRITE(0x400310, NV_READ(0x400310) | 0x20); + NV_WRITE(0x400304, 1); + /* just in case, we don't want to spin in-kernel forever */ + for (i=0; i<1000; i++) { + if (NV_READ(0x40030C) == 0) + break; + } + if (i==1000) { + DRM_ERROR("failed to save current grctx to ramin\n"); + DRM_ERROR("instance = 0x%08x\n", NV_READ(0x40032C)); + DRM_ERROR("0x40030C = 0x%08x\n", NV_READ(0x40030C)); + NV_WRITE(NV_PGRAPH_FIFO, 1); + return; + } + + NV_WRITE(NV_PGRAPH_FIFO, 1); +} + +/* Restore the context for a specific channel into PGRAPH + * XXX: fails sometimes.. not sure why + */ +void +nv40_graph_context_restore(drm_device_t *dev, int channel) +{ + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[channel]; + uint32_t instance; + int i; + + instance = nouveau_chip_instance_get(dev, chan->ramin_grctx); + + NV_WRITE(NV_PGRAPH_FIFO, 0); + NV_WRITE(0x400784, instance); + NV_WRITE(0x400310, NV_READ(0x400310) | 0x40); + NV_WRITE(0x400304, 1); + /* just in case, we don't want to spin in-kernel forever */ + for (i=0; i<1000; i++) { + if (NV_READ(0x40030C) == 0) + break; + } + if (i==1000) { + DRM_ERROR("failed to restore grctx for ch%d to PGRAPH\n", + channel); + DRM_ERROR("instance = 0x%08x\n", instance); + DRM_ERROR("0x40030C = 0x%08x\n", NV_READ(0x40030C)); + NV_WRITE(NV_PGRAPH_FIFO, 1); + return; + } + + + /* 0x40032C, no idea of it's exact function. Could simply be a + * record of the currently active PGRAPH context. It's currently + * unknown as to what bit 24 does. The nv ddx has it set, so we will + * set it here too. + */ + NV_WRITE(0x40032C, instance | 0x01000000); + /* 0x32E0 records the instance address of the active FIFO's PGRAPH + * context. If at any time this doesn't match 0x40032C, you will + * recieve PGRAPH_INTR_CONTEXT_SWITCH + */ + NV_WRITE(NV40_PFIFO_GRCTX_INSTANCE, instance); + NV_WRITE(NV_PGRAPH_FIFO, 1); +} +#endif +int +nv30_graph_init(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + int i, chipset; + + chipset = (NV_READ(NV_PMC_BOOT_0) & 0x0ff00000) >> 20; + DRM_DEBUG("chipset (from PMC_BOOT_0): NV%02X\n", chipset); + + /* Create Context Pointer Table */ + dev_priv->ctx_table_size = 32 * 4; + dev_priv->ctx_table = nouveau_instmem_alloc(dev, dev_priv->ctx_table_size, 4); + if (!dev_priv->ctx_table) + return DRM_ERR(ENOMEM); + + for (i=0; i< dev_priv->ctx_table_size; i+=4) + INSTANCE_WR(dev_priv->ctx_table, i/4, 0x00000000); + + NV_WRITE(NV_PGRAPH_CHANNEL_CTX_TABLE, nouveau_chip_instance_get(dev, dev_priv->ctx_table)); + + return 0; +} + -- cgit v1.2.3 From 9d3deddc4a8f12b9493858a529570e77f8362ad1 Mon Sep 17 00:00:00 2001 From: Haihao Xiang Date: Fri, 12 Jan 2007 11:24:14 -0800 Subject: Delay for a usec while spinning waiting for ring buffer space. This means the loop will wait up to ~10ms for ring buffer space to become available, rather than just however long it takes to check the space 10000 times. This matches other drivers' behavior when waiting for ring buffer/fifo space. --- shared-core/i915_dma.c | 1 + 1 file changed, 1 insertion(+) diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 943a1772..912fe0b1 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -63,6 +63,7 @@ int i915_wait_ring(drm_device_t * dev, int n, const char *caller) i = 0; last_head = ring->head; + DRM_UDELAY(1); } return DRM_ERR(EBUSY); -- cgit v1.2.3 From 1bad7e0d02ff82227c34b853e06ca25a80193347 Mon Sep 17 00:00:00 2001 From: Matthieu Castet Date: Fri, 12 Jan 2007 20:30:14 +0100 Subject: nouveau : remove useless init : we clear RAMIN before --- shared-core/nouveau_fifo.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index d41972b2..98a1344e 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -329,9 +329,6 @@ 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, 0); - } static void nouveau_nv30_context_init(drm_device_t *dev, -- cgit v1.2.3 From 69a98d89d5204ec224703bddc3582bb854716a20 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sat, 13 Jan 2007 08:43:15 +1100 Subject: nouveau: add missing symlink --- linux-core/nv30_graph.c | 1 + 1 file changed, 1 insertion(+) create mode 120000 linux-core/nv30_graph.c diff --git a/linux-core/nv30_graph.c b/linux-core/nv30_graph.c new file mode 120000 index 00000000..25568ecb --- /dev/null +++ b/linux-core/nv30_graph.c @@ -0,0 +1 @@ +../shared-core/nv30_graph.c \ No newline at end of file -- cgit v1.2.3 From 1967aa82cfc18c422360ef544b66e316d98f53a1 Mon Sep 17 00:00:00 2001 From: Stephane Marchesin Date: Sat, 13 Jan 2007 12:32:45 +0100 Subject: nouveau: Oops, fix the nv04 RAMFC_DMA_FETCH value. --- shared-core/nouveau_reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h index 97d81048..a1d189f1 100644 --- a/shared-core/nouveau_reg.h +++ b/shared-core/nouveau_reg.h @@ -213,7 +213,7 @@ #define NV04_RAMFC_DMA_PUT 0x00 #define NV04_RAMFC_DMA_GET 0x04 #define NV04_RAMFC_DMA_INSTANCE 0x08 -#define NV04_RAMFC_DMA_FETCH 0x16 +#define NV04_RAMFC_DMA_FETCH 0x10 #define NV10_RAMFC_DMA_PUT 0x00 #define NV10_RAMFC_DMA_GET 0x04 -- cgit v1.2.3 From 4ae64a1b583be3ef13338e8029e7e9efe21f2c2f Mon Sep 17 00:00:00 2001 From: Matthieu Castet Date: Sat, 13 Jan 2007 21:41:33 +0100 Subject: nouveau: add and indent pgraph regs --- shared-core/nouveau_reg.h | 107 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 92 insertions(+), 15 deletions(-) diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h index a1d189f1..8058e980 100644 --- a/shared-core/nouveau_reg.h +++ b/shared-core/nouveau_reg.h @@ -55,6 +55,7 @@ #define NV_PMC_INTEN 0x00000140 # define NV_PMC_INTEN_MASTER_ENABLE (1<< 0) +#define NV_PGRAPH_DEBUG_4 0x00400090 #define NV_PGRAPH_INTSTAT 0x00400100 #define NV04_PGRAPH_INTEN 0x00400140 #define NV40_PGRAPH_INTEN 0x0040013C @@ -68,23 +69,99 @@ # define NV_PGRAPH_NV40_UNK220_FB_INSTANCE #define NV_PGRAPH_CTX_USER 0x00400148 #define NV_PGRAPH_CTX_SWITCH1 0x0040014C -#define NV_PGRAPH_FIFO 0x00400720 -#define NV_PGRAPH_FFINTFC_ST2 0x00400764 - -/* NV-Register NV_PGRAPH_CHANNEL_CTX_TABLE */ -#define NV_PGRAPH_CHANNEL_CTX_TABLE 0x00400780 -#define NV_PGRAPH_CHANNEL_CTX_TABLE_INST 0x0000FFFF -#define NV_PGRAPH_CHANNEL_CTX_TABLE_INST_0 0x00000000 +#define NV_PGRAPH_CTX_SWITCH2 0x00400150 +#define NV_PGRAPH_CTX_SWITCH3 0x00400154 +#define NV_PGRAPH_CTX_SWITCH4 0x00400158 +#define NV_PGRAPH_CTX_SWITCH5 0x0040015C +#define NV_PGRAPH_X_MISC 0x00400500 +#define NV_PGRAPH_Y_MISC 0x00400504 +#define NV_PGRAPH_VALID1 0x00400508 +#define NV_PGRAPH_SOURCE_COLOR 0x0040050C +#define NV_PGRAPH_MISC24_0 0x00400510 +#define NV_PGRAPH_XY_LOGIC_MISC0 0x00400514 +#define NV_PGRAPH_XY_LOGIC_MISC1 0x00400518 +#define NV_PGRAPH_XY_LOGIC_MISC2 0x0040051C +#define NV_PGRAPH_XY_LOGIC_MISC3 0x00400520 +#define NV_PGRAPH_CLIPX_0 0x00400524 +#define NV_PGRAPH_CLIPX_1 0x00400528 +#define NV_PGRAPH_CLIPY_0 0x0040052C +#define NV_PGRAPH_CLIPY_1 0x00400530 +#define NV_PGRAPH_ABS_ICLIP_XMAX 0x00400534 +#define NV_PGRAPH_ABS_ICLIP_YMAX 0x00400538 +#define NV_PGRAPH_ABS_UCLIP_XMIN 0x0040053C +#define NV_PGRAPH_ABS_UCLIP_YMIN 0x00400540 +#define NV_PGRAPH_ABS_UCLIP_XMAX 0x00400544 +#define NV_PGRAPH_ABS_UCLIP_YMAX 0x00400548 +#define NV_PGRAPH_ABS_UCLIPA_XMIN 0x00400560 +#define NV_PGRAPH_ABS_UCLIPA_YMIN 0x00400564 +#define NV_PGRAPH_ABS_UCLIPA_XMAX 0x00400568 +#define NV_PGRAPH_ABS_UCLIPA_YMAX 0x0040056C +#define NV_PGRAPH_MISC24_1 0x00400570 +#define NV_PGRAPH_MISC24_2 0x00400574 +#define NV_PGRAPH_VALID2 0x00400578 +#define NV_PGRAPH_PASSTHRU_0 0x0040057C +#define NV_PGRAPH_PASSTHRU_1 0x00400580 +#define NV_PGRAPH_PASSTHRU_2 0x00400584 +#define NV_PGRAPH_DIMX_TEXTURE 0x00400588 +#define NV_PGRAPH_WDIMX_TEXTURE 0x0040058C +#define NV_PGRAPH_MONO_COLOR0 0x00400600 +#define NV_PGRAPH_ROP3 0x00400604 +#define NV_PGRAPH_BETA_AND 0x00400608 +#define NV_PGRAPH_BETA_PREMULT 0x0040060C +#define NV_PGRAPH_BOFFSET0 0x00400640 +#define NV_PGRAPH_BOFFSET1 0x00400644 +#define NV_PGRAPH_BOFFSET2 0x00400648 +#define NV_PGRAPH_BOFFSET3 0x0040064C +#define NV_PGRAPH_BOFFSET4 0x00400650 +#define NV_PGRAPH_BOFFSET5 0x00400654 +#define NV_PGRAPH_BBASE0 0x00400658 +#define NV_PGRAPH_BBASE1 0x0040065C +#define NV_PGRAPH_BBASE2 0x00400660 +#define NV_PGRAPH_BBASE3 0x00400664 +#define NV_PGRAPH_BBASE4 0x00400668 +#define NV_PGRAPH_BBASE5 0x0040066C +#define NV_PGRAPH_BPITCH0 0x00400670 +#define NV_PGRAPH_BPITCH1 0x00400674 +#define NV_PGRAPH_BPITCH2 0x00400678 +#define NV_PGRAPH_BPITCH3 0x0040067C +#define NV_PGRAPH_BPITCH4 0x00400680 +#define NV_PGRAPH_BLIMIT0 0x00400684 +#define NV_PGRAPH_BLIMIT1 0x00400688 +#define NV_PGRAPH_BLIMIT2 0x0040068C +#define NV_PGRAPH_BLIMIT3 0x00400690 +#define NV_PGRAPH_BLIMIT4 0x00400694 +#define NV_PGRAPH_BLIMIT5 0x00400698 +#define NV_PGRAPH_BSWIZZLE2 0x0040069C +#define NV_PGRAPH_BSWIZZLE5 0x004006A0 +#define NV_PGRAPH_SURFACE 0x00400710 +#define NV_PGRAPH_STATE 0x00400714 +#define NV_PGRAPH_NOTIFY 0x00400718 -/* NV-Register NV_PGRAPH_CHANNEL_CTX_SIZE */ -#define NV_PGRAPH_CHANNEL_CTX_SIZE 0x00400784 -#define NV_PGRAPH_CHANNEL_CTX_SIZE_VALUE 0x0000FFFF -#define NV_PGRAPH_CHANNEL_CTX_SIZE_VALUE_INIT 0x00001000 +#define NV_PGRAPH_FIFO 0x00400720 -/* NV-Register NV_PGRAPH_CHANNEL_CTX_POINTER */ -#define NV_PGRAPH_CHANNEL_CTX_POINTER 0x00400788 -#define NV_PGRAPH_CHANNEL_CTX_POINTER_INST 0x0000FFFF -#define NV_PGRAPH_CHANNEL_CTX_POINTER_INST_0 0x00000000 +#define NV_PGRAPH_BPIXEL 0x00400724 +#define NV_PGRAPH_FFINTFC_ST2 0x00400764 +#define NV_PGRAPH_DMA_PITCH 0x00400770 +#define NV_PGRAPH_DVD_COLORFMT 0x00400774 +#define NV_PGRAPH_SCALED_FORMAT 0x00400778 +#define NV_PGRAPH_CHANNEL_CTX_TABLE 0x00400780 +#define NV_PGRAPH_CHANNEL_CTX_SIZE 0x00400784 +#define NV_PGRAPH_CHANNEL_CTX_POINTER 0x00400788 +#define NV_PGRAPH_PATT_COLOR0 0x00400800 +#define NV_PGRAPH_PATT_COLOR1 0x00400804 +#define NV_PGRAPH_PATTERN_SHAPE 0x00400810 +#define NV_PGRAPH_CHROMA 0x00400814 +#define NV_PGRAPH_STORED_FMT 0x00400830 +#define NV_PGRAPH_XFMODE0 0x00400F40 +#define NV_PGRAPH_XFMODE1 0x00400F44 +#define NV_PGRAPH_GLOBALSTATE0 0x00400F48 +#define NV_PGRAPH_GLOBALSTATE1 0x00400F4C +#define NV_PGRAPH_PIPE_ADDRESS 0x00400F50 +#define NV_PGRAPH_PIPE_DATA 0x00400F54 +#define NV_PGRAPH_DMA_START_0 0x00401000 +#define NV_PGRAPH_DMA_START_1 0x00401004 +#define NV_PGRAPH_DMA_LENGTH 0x00401008 +#define NV_PGRAPH_DMA_MISC 0x0040100C /* It's a guess that this works on NV03. Confirmed on NV04, though */ #define NV_PFIFO_DELAY_0 0x00002040 -- cgit v1.2.3 From cd5f543b2f3d6dd4c45f676c6fb9848b4d8a1c33 Mon Sep 17 00:00:00 2001 From: Matthieu Castet Date: Sat, 13 Jan 2007 21:43:47 +0100 Subject: nouveau: first step to make graph ctx works It is still not working, but now we could use some 3D commands without needed to run nvidia blob before. --- linux-core/Makefile.kernel | 2 +- linux-core/nv10_graph.c | 1 + shared-core/nouveau_drv.h | 9 +- shared-core/nouveau_fifo.c | 6 +- shared-core/nouveau_irq.c | 31 --- shared-core/nouveau_state.c | 2 + shared-core/nv10_graph.c | 594 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 608 insertions(+), 37 deletions(-) create mode 120000 linux-core/nv10_graph.c create mode 100644 shared-core/nv10_graph.c diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index 30df582c..1bfffa03 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -22,7 +22,7 @@ i830-objs := i830_drv.o i830_dma.o i830_irq.o i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \ i915_buffer.o nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \ - nouveau_object.o nouveau_irq.o nv30_graph.o nv40_graph.o + nouveau_object.o nouveau_irq.o nv10_graph.o nv30_graph.o nv40_graph.o radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o sis-objs := sis_drv.o sis_mm.o ffb-objs := ffb_drv.o ffb_context.o diff --git a/linux-core/nv10_graph.c b/linux-core/nv10_graph.c new file mode 120000 index 00000000..0d5a0eb4 --- /dev/null +++ b/linux-core/nv10_graph.c @@ -0,0 +1 @@ +../shared-core/nv10_graph.c \ No newline at end of file diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 219ba123..9466cdcd 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -90,8 +90,8 @@ struct nouveau_fifo /* objects belonging to this fifo */ struct nouveau_object *objs; - /* XXX move this in PGRAPH struct */ - uint32_t pgraph_ctx_user; + /* XXX dynamic alloc ? */ + uint32_t nv10_pgraph_ctx [340]; }; struct nouveau_config { @@ -202,6 +202,11 @@ extern void nouveau_irq_preinstall(drm_device_t*); extern void nouveau_irq_postinstall(drm_device_t*); extern void nouveau_irq_uninstall(drm_device_t*); +/* nv10_graph.c */ +extern void nouveau_nv10_context_switch(drm_device_t *dev); +extern int nv10_graph_init(drm_device_t *dev); +extern int nv10_graph_context_create(drm_device_t *dev, int channel); + /* nv30_graph.c */ extern int nv30_graph_init(drm_device_t *dev); extern int nv30_graph_context_create(drm_device_t *dev, int channel); diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 98a1344e..cb94afc5 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -538,7 +538,6 @@ 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); @@ -551,8 +550,9 @@ 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_nv04_context_init(dev, init); - } else if (dev_priv->card_type < NV_30) { - nouveau_nv10_context_init(dev, init); + } else if (dev_priv->card_type < NV_30) { + nv10_graph_context_create(dev, init->channel); + nouveau_nv10_context_init(dev, init); } else if (dev_priv->card_type < NV_40) { ret = nv30_graph_context_create(dev, init->channel); if (ret) { diff --git a/shared-core/nouveau_irq.c b/shared-core/nouveau_irq.c index 7a31fb0b..638b094b 100644 --- a/shared-core/nouveau_irq.c +++ b/shared-core/nouveau_irq.c @@ -237,37 +237,6 @@ static void nouveau_nv04_context_switch(drm_device_t *dev) } -static void nouveau_nv10_context_switch(drm_device_t *dev) -{ - drm_nouveau_private_t *dev_priv = dev->dev_private; - int channel, channel_old; - - channel=NV_READ(NV_PFIFO_CACH1_PSH1)&(nouveau_fifo_number(dev)-1); - channel_old = (NV_READ(NV_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); - - DRM_INFO("NV: PGRAPH context switch interrupt channel %x -> %x\n",channel_old, channel); - - NV_WRITE(NV_PGRAPH_FIFO,0x0); - NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000000); - NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000000); - NV_WRITE(NV_PFIFO_CACHES, 0x00000000); - - dev_priv->fifos[channel_old].pgraph_ctx_user = NV_READ(NV_PGRAPH_CTX_USER); - //XXX save PGRAPH context - NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x10000000); - NV_WRITE(NV_PGRAPH_CTX_USER, dev_priv->fifos[channel].pgraph_ctx_user); - //XXX restore PGRAPH context - printk("ctx_user %x %x\n", dev_priv->fifos[channel_old].pgraph_ctx_user, dev_priv->fifos[channel].pgraph_ctx_user); - - NV_WRITE(NV_PGRAPH_FFINTFC_ST2, NV_READ(NV_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF); - NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x10010100); - - NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001); - NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000001); - NV_WRITE(NV_PFIFO_CACHES, 0x00000001); - NV_WRITE(NV_PGRAPH_FIFO,0x1); -} - static void nouveau_pgraph_irq_handler(drm_device_t *dev) { uint32_t status; diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index 1e0587f6..6448512c 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -96,6 +96,8 @@ int nouveau_firstopen(struct drm_device *dev) /* FIXME: doesn't belong here, and have no idea what it's for.. */ if (dev_priv->card_type >= NV_40) nv40_graph_init(dev); + else if (dev_priv->card_type == NV_10) + nv10_graph_init(dev); return 0; } diff --git a/shared-core/nv10_graph.c b/shared-core/nv10_graph.c new file mode 100644 index 00000000..ccbb34de --- /dev/null +++ b/shared-core/nv10_graph.c @@ -0,0 +1,594 @@ +/* + * Copyright 2007 Matthieu CASTET + * 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_drm.h" +#include "nouveau_drv.h" + + +static void nv10_praph_pipe(drm_device_t *dev) { + drm_nouveau_private_t *dev_priv = dev->dev_private; + int i; + + nouveau_wait_for_idle(dev); + /* XXX check haiku comments */ + NV_WRITE(NV_PGRAPH_XFMODE0, 0x10000000); + NV_WRITE(NV_PGRAPH_XFMODE1, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x000064c0); + for (i = 0; i < 4; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + for (i = 0; i < 4; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00006ab0); + + for (i = 0; i < 3; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00006a80); + for (i = 0; i < 3; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00000040); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000008); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00000200); + for (i = 0; i < 48; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + nouveau_wait_for_idle(dev); + + NV_WRITE(NV_PGRAPH_XFMODE0, 0x00000000); + NV_WRITE(NV_PGRAPH_XFMODE1, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00006400); + for (i = 0; i < 211; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x40000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x40000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x40000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x40000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00006800); + for (i = 0; i < 162; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x3f800000); + for (i = 0; i < 25; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00006c00); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0xbf800000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00007000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x7149f2ca); + for (i = 0; i < 35; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00007400); + for (i = 0; i < 48; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00007800); + for (i = 0; i < 48; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00004400); + for (i = 0; i < 32; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00000000); + for (i = 0; i < 16; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV_PGRAPH_PIPE_ADDRESS, 0x00000040); + for (i = 0; i < 4; i++) + NV_WRITE(NV_PGRAPH_PIPE_DATA, 0x00000000); + + nouveau_wait_for_idle(dev); +} + +/* TODO replace address with name + use loops */ +static int nv10_graph_ctx_regs [] = { +NV_PGRAPH_XY_LOGIC_MISC0, +NV_PGRAPH_DEBUG_4, +0x004006b0, + +NV_PGRAPH_CTX_SWITCH1, +NV_PGRAPH_CTX_SWITCH2, +NV_PGRAPH_CTX_SWITCH3, +NV_PGRAPH_CTX_SWITCH4, +NV_PGRAPH_CTX_SWITCH5, +0x00400160, +0x00400180, +0x004001a0, +0x004001c0, +0x004001e0, +0x00400164, +0x00400184, +0x004001a4, +0x004001c4, +0x004001e4, +0x00400168, +0x00400188, +0x004001a8, +0x004001c8, +0x004001e8, +0x0040016c, +0x0040018c, +0x004001ac, +0x004001cc, +0x004001ec, +0x00400170, +0x00400190, +0x004001b0, +0x004001d0, +0x004001f0, +0x00400174, +0x00400194, +0x004001b4, +0x004001d4, +0x004001f4, +0x00400178, +0x00400198, +0x004001b8, +0x004001d8, +0x004001f8, +0x0040017c, +0x0040019c, +0x004001bc, +0x004001dc, +0x004001fc, +NV_PGRAPH_CTX_USER, +NV_PGRAPH_DMA_START_0, +NV_PGRAPH_DMA_START_1, +NV_PGRAPH_DMA_LENGTH, +NV_PGRAPH_DMA_MISC, +NV_PGRAPH_DMA_PITCH, +NV_PGRAPH_BOFFSET0, +NV_PGRAPH_BBASE0, +NV_PGRAPH_BLIMIT0, +NV_PGRAPH_BOFFSET1, +NV_PGRAPH_BBASE1, +NV_PGRAPH_BLIMIT1, +NV_PGRAPH_BOFFSET2, +NV_PGRAPH_BBASE2, +NV_PGRAPH_BLIMIT2, +NV_PGRAPH_BOFFSET3, +NV_PGRAPH_BBASE3, +NV_PGRAPH_BLIMIT3, +NV_PGRAPH_BOFFSET4, +NV_PGRAPH_BBASE4, +NV_PGRAPH_BLIMIT4, +NV_PGRAPH_BOFFSET5, +NV_PGRAPH_BBASE5, +NV_PGRAPH_BLIMIT5, +NV_PGRAPH_BPITCH0, +NV_PGRAPH_BPITCH1, +NV_PGRAPH_BPITCH2, +NV_PGRAPH_BPITCH3, +NV_PGRAPH_BPITCH4, +NV_PGRAPH_SURFACE, +NV_PGRAPH_STATE, +NV_PGRAPH_BSWIZZLE2, +NV_PGRAPH_BSWIZZLE5, +NV_PGRAPH_BPIXEL, +NV_PGRAPH_NOTIFY, +NV_PGRAPH_PATT_COLOR0, +NV_PGRAPH_PATT_COLOR1, +0x00400900, +0x00400904, +0x00400908, +0x0040090c, +0x00400910, +0x00400914, +0x00400918, +0x0040091c, +0x00400920, +0x00400924, +0x00400928, +0x0040092c, +0x00400930, +0x00400934, +0x00400938, +0x0040093c, +0x00400940, +0x00400944, +0x00400948, +0x0040094c, +0x00400950, +0x00400954, +0x00400958, +0x0040095c, +0x00400960, +0x00400964, +0x00400968, +0x0040096c, +0x00400970, +0x00400974, +0x00400978, +0x0040097c, +0x00400980, +0x00400984, +0x00400988, +0x0040098c, +0x00400990, +0x00400994, +0x00400998, +0x0040099c, +0x004009a0, +0x004009a4, +0x004009a8, +0x004009ac, +0x004009b0, +0x004009b4, +0x004009b8, +0x004009bc, +0x004009c0, +0x004009c4, +0x004009c8, +0x004009cc, +0x004009d0, +0x004009d4, +0x004009d8, +0x004009dc, +0x004009e0, +0x004009e4, +0x004009e8, +0x004009ec, +0x004009f0, +0x004009f4, +0x004009f8, +0x004009fc, +0x00400808, +0x0040080c, +NV_PGRAPH_PATTERN_SHAPE, +NV_PGRAPH_MONO_COLOR0, +NV_PGRAPH_ROP3, +NV_PGRAPH_CHROMA, +NV_PGRAPH_BETA_AND, +NV_PGRAPH_BETA_PREMULT, +0x00400e70, +0x00400e74, +0x00400e78, +0x00400e7c, +0x00400e80, +0x00400e84, +0x00400e88, +0x00400e8c, +0x00400ea0, +0x00400ea4, +0x00400ea8, +0x00400eac, +0x00400eb0, +0x00400eb4, +0x00400eb8, +0x00400ebc, +0x00400ec0, +0x00400ec4, +0x00400ec8, +0x00400ecc, +0x00400ed0, +0x00400ed4, +0x00400ed8, +0x00400edc, +0x00400ee0, +0x00400a00, +0x00400a04, +0x00400e90, +0x00400e94, +0x00400e98, +0x00400e9c, +0x00400f00, +0x00400f20, +0x00400f04, +0x00400f24, +0x00400f08, +0x00400f28, +0x00400f0c, +0x00400f2c, +0x00400f10, +0x00400f30, +0x00400f14, +0x00400f34, +0x00400f18, +0x00400f38, +0x00400f1c, +0x00400f3c, +NV_PGRAPH_XFMODE0, +NV_PGRAPH_XFMODE1, +NV_PGRAPH_GLOBALSTATE0, +NV_PGRAPH_GLOBALSTATE1, +NV_PGRAPH_STORED_FMT, +NV_PGRAPH_SOURCE_COLOR, +0x00400400, +0x00400480, +0x00400404, +0x00400484, +0x00400408, +0x00400488, +0x0040040c, +0x0040048c, +0x00400410, +0x00400490, +0x00400414, +0x00400494, +0x00400418, +0x00400498, +0x0040041c, +0x0040049c, +0x00400420, +0x004004a0, +0x00400424, +0x004004a4, +0x00400428, +0x004004a8, +0x0040042c, +0x004004ac, +0x00400430, +0x004004b0, +0x00400434, +0x004004b4, +0x00400438, +0x004004b8, +0x0040043c, +0x004004bc, +0x00400440, +0x004004c0, +0x00400444, +0x004004c4, +0x00400448, +0x004004c8, +0x0040044c, +0x004004cc, +0x00400450, +0x004004d0, +0x00400454, +0x004004d4, +0x00400458, +0x004004d8, +0x0040045c, +0x004004dc, +0x00400460, +0x004004e0, +0x00400464, +0x004004e4, +0x00400468, +0x004004e8, +0x0040046c, +0x004004ec, +0x00400470, +0x004004f0, +0x00400474, +0x004004f4, +0x00400478, +0x004004f8, +0x0040047c, +0x004004fc, +NV_PGRAPH_ABS_UCLIP_XMIN, +NV_PGRAPH_ABS_UCLIP_XMAX, +NV_PGRAPH_ABS_UCLIP_YMIN, +NV_PGRAPH_ABS_UCLIP_YMAX, +0x00400550, +0x00400558, +0x00400554, +0x0040055c, +NV_PGRAPH_ABS_UCLIPA_XMIN, +NV_PGRAPH_ABS_UCLIPA_XMAX, +NV_PGRAPH_ABS_UCLIPA_YMIN, +NV_PGRAPH_ABS_UCLIPA_YMAX, +NV_PGRAPH_ABS_ICLIP_XMAX, +NV_PGRAPH_ABS_ICLIP_YMAX, +NV_PGRAPH_XY_LOGIC_MISC1, +NV_PGRAPH_XY_LOGIC_MISC2, +NV_PGRAPH_XY_LOGIC_MISC3, +NV_PGRAPH_CLIPX_0, +NV_PGRAPH_CLIPX_1, +NV_PGRAPH_CLIPY_0, +NV_PGRAPH_CLIPY_1, +0x00400e40, +0x00400e44, +0x00400e48, +0x00400e4c, +0x00400e50, +0x00400e54, +0x00400e58, +0x00400e5c, +0x00400e60, +0x00400e64, +0x00400e68, +0x00400e6c, +0x00400e00, +0x00400e04, +0x00400e08, +0x00400e0c, +0x00400e10, +0x00400e14, +0x00400e18, +0x00400e1c, +0x00400e20, +0x00400e24, +0x00400e28, +0x00400e2c, +0x00400e30, +0x00400e34, +0x00400e38, +0x00400e3c, +NV_PGRAPH_PASSTHRU_0, +NV_PGRAPH_PASSTHRU_1, +NV_PGRAPH_PASSTHRU_2, +NV_PGRAPH_DIMX_TEXTURE, +NV_PGRAPH_WDIMX_TEXTURE, +NV_PGRAPH_DVD_COLORFMT, +NV_PGRAPH_SCALED_FORMAT, +NV_PGRAPH_MISC24_0, +NV_PGRAPH_MISC24_1, +NV_PGRAPH_MISC24_2, +NV_PGRAPH_X_MISC, +NV_PGRAPH_Y_MISC, +NV_PGRAPH_VALID1, +NV_PGRAPH_VALID2, +0 +}; + +void nouveau_nv10_context_switch(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + int channel, channel_old, i; + + channel=NV_READ(NV_PFIFO_CACH1_PSH1)&(nouveau_fifo_number(dev)-1); + channel_old = (NV_READ(NV_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); + + DRM_INFO("NV: PGRAPH context switch interrupt channel %x -> %x\n",channel_old, channel); + + NV_WRITE(NV_PGRAPH_FIFO,0x0); +#if 0 + NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000000); + NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000000); + NV_WRITE(NV_PFIFO_CACHES, 0x00000000); +#endif + + // save PGRAPH context + for (i = 0; nv10_graph_ctx_regs[i]; i++) + dev_priv->fifos[channel_old].nv10_pgraph_ctx[i] = NV_READ(nv10_graph_ctx_regs[i]); + + nouveau_wait_for_idle(dev); + + NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x10000000); + NV_WRITE(NV_PGRAPH_CTX_USER, (NV_READ(NV_PGRAPH_CTX_USER) & 0xffffff) | (0x1f << 24)); + + nouveau_wait_for_idle(dev); + // restore PGRAPH context + //XXX not working yet +#if 0 + for (i = 0; nv10_graph_ctx_regs[i]; i++) + NV_WRITE(nv10_graph_ctx_regs[i], dev_priv->fifos[channel].nv10_pgraph_ctx[i]); + nouveau_wait_for_idle(dev); +#endif + + NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x10010100); + NV_WRITE(NV_PGRAPH_CTX_USER, channel << 24); + NV_WRITE(NV_PGRAPH_FFINTFC_ST2, NV_READ(NV_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF); + +#if 0 + NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001); + NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000001); + NV_WRITE(NV_PFIFO_CACHES, 0x00000001); +#endif + NV_WRITE(NV_PGRAPH_FIFO,0x1); +} + +int nv10_graph_context_create(drm_device_t *dev, int channel) { + drm_nouveau_private_t *dev_priv = dev->dev_private; + DRM_DEBUG("nv10_graph_context_create %d\n", channel); + + memset(dev_priv->fifos[channel].nv10_pgraph_ctx, 0, sizeof(dev_priv->fifos[channel].nv10_pgraph_ctx)); + + //dev_priv->fifos[channel].pgraph_ctx_user = channel << 24; + dev_priv->fifos[channel].nv10_pgraph_ctx[0] = 0x0001ffff; + /* is it really needed ??? */ + dev_priv->fifos[channel].nv10_pgraph_ctx[1] = NV_READ(NV_PGRAPH_DEBUG_4); + dev_priv->fifos[channel].nv10_pgraph_ctx[2] = NV_READ(0x004006b0); + return 0; +} + + +int nv10_graph_init(drm_device_t *dev) { + //XXX should be call at each fifo init + nv10_praph_pipe(dev); + return 0; +} -- cgit v1.2.3 From f04347f371c6c9c3a47550c6b7d26b7bd5629c85 Mon Sep 17 00:00:00 2001 From: Matthieu Castet Date: Sat, 13 Jan 2007 23:19:41 +0100 Subject: nouveau: nv20 graph ctx switch. Untested... --- linux-core/Makefile.kernel | 3 +- linux-core/nv20_graph.c | 1 + shared-core/nouveau_drv.h | 5 ++ shared-core/nouveau_fifo.c | 28 ++++++-- shared-core/nouveau_irq.c | 3 + shared-core/nouveau_reg.h | 2 + shared-core/nouveau_state.c | 6 +- shared-core/nv20_graph.c | 155 ++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 194 insertions(+), 9 deletions(-) create mode 120000 linux-core/nv20_graph.c create mode 100644 shared-core/nv20_graph.c diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index 1bfffa03..b531a70f 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -22,7 +22,8 @@ i830-objs := i830_drv.o i830_dma.o i830_irq.o i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \ i915_buffer.o nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \ - nouveau_object.o nouveau_irq.o nv10_graph.o nv30_graph.o nv40_graph.o + nouveau_object.o nouveau_irq.o nv10_graph.o nv30_graph.o nv40_graph.o \ + nv20_graph.o radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o sis-objs := sis_drv.o sis_mm.o ffb-objs := ffb_drv.o ffb_context.o diff --git a/linux-core/nv20_graph.c b/linux-core/nv20_graph.c new file mode 120000 index 00000000..73049914 --- /dev/null +++ b/linux-core/nv20_graph.c @@ -0,0 +1 @@ +../shared-core/nv20_graph.c \ No newline at end of file diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 9466cdcd..4978c476 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -207,6 +207,11 @@ extern void nouveau_nv10_context_switch(drm_device_t *dev); extern int nv10_graph_init(drm_device_t *dev); extern int nv10_graph_context_create(drm_device_t *dev, int channel); +/* nv20_graph.c */ +extern void nouveau_nv20_context_switch(drm_device_t *dev); +extern int nv20_graph_init(drm_device_t *dev); +extern int nv20_graph_context_create(drm_device_t *dev, int channel); + /* nv30_graph.c */ extern int nv30_graph_init(drm_device_t *dev); extern int nv30_graph_context_create(drm_device_t *dev, int channel); diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index cb94afc5..1e2870f1 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -550,15 +550,22 @@ 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_nv04_context_init(dev, init); - } else if (dev_priv->card_type < NV_30) { + } else if (dev_priv->card_type < NV_20) { nv10_graph_context_create(dev, init->channel); nouveau_nv10_context_init(dev, init); - } else if (dev_priv->card_type < NV_40) { - ret = nv30_graph_context_create(dev, init->channel); - if (ret) { - nouveau_fifo_free(dev, init->channel); - return ret; - } + } else if (dev_priv->card_type < NV_30) { + ret = nv20_graph_context_create(dev, init->channel); + if (ret) { + nouveau_fifo_free(dev, init->channel); + return ret; + } + nouveau_nv10_context_init(dev, init); + } else if (dev_priv->card_type < NV_40) { + ret = nv30_graph_context_create(dev, init->channel); + if (ret) { + nouveau_fifo_free(dev, init->channel); + return ret; + } nouveau_nv30_context_init(dev, init); } else { ret = nv40_graph_context_create(dev, init->channel); @@ -652,6 +659,13 @@ void nouveau_fifo_free(drm_device_t* dev,int n) if (dev_priv->card_type >= NV_40) nouveau_instmem_free(dev, dev_priv->fifos[n].ramin_grctx); + else if (dev_priv->card_type >= NV_30) { + } + else if (dev_priv->card_type >= NV_20) { + /* clear ctx table */ + INSTANCE_WR(dev_priv->ctx_table, n, 0); + nouveau_instmem_free(dev, dev_priv->fifos[n].ramin_grctx); + } /* reenable the fifo caches */ NV_WRITE(NV_PFIFO_CACHES, 0x00000001); diff --git a/shared-core/nouveau_irq.c b/shared-core/nouveau_irq.c index 638b094b..a92b8168 100644 --- a/shared-core/nouveau_irq.c +++ b/shared-core/nouveau_irq.c @@ -329,6 +329,9 @@ static void nouveau_pgraph_irq_handler(drm_device_t *dev) case NV_10: nouveau_nv10_context_switch(dev); break; + case NV_20: + nouveau_nv20_context_switch(dev); + break; default: DRM_INFO("NV: Context switch not implemented\n"); break; diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h index 8058e980..543be694 100644 --- a/shared-core/nouveau_reg.h +++ b/shared-core/nouveau_reg.h @@ -140,6 +140,8 @@ #define NV_PGRAPH_FIFO 0x00400720 #define NV_PGRAPH_BPIXEL 0x00400724 +#define NV_PGRAPH_RDI_INDEX 0x00400750 +#define NV_PGRAPH_RDI_DATA 0x00400754 #define NV_PGRAPH_FFINTFC_ST2 0x00400764 #define NV_PGRAPH_DMA_PITCH 0x00400770 #define NV_PGRAPH_DVD_COLORFMT 0x00400774 diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index 6448512c..f324c5ff 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -96,7 +96,11 @@ int nouveau_firstopen(struct drm_device *dev) /* FIXME: doesn't belong here, and have no idea what it's for.. */ if (dev_priv->card_type >= NV_40) nv40_graph_init(dev); - else if (dev_priv->card_type == NV_10) + else if (dev_priv->card_type >= NV_30) { + } + else if (dev_priv->card_type >= NV_20) + nv20_graph_init(dev); + else if (dev_priv->card_type >= NV_10) nv10_graph_init(dev); return 0; diff --git a/shared-core/nv20_graph.c b/shared-core/nv20_graph.c new file mode 100644 index 00000000..6d00effa --- /dev/null +++ b/shared-core/nv20_graph.c @@ -0,0 +1,155 @@ +/* + * Copyright 2007 Matthieu CASTET + * 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" + +#define NV20_GRCTX_SIZE (3529) + +int nv20_graph_context_create(drm_device_t *dev, int channel) { + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[channel]; + unsigned int ctx_size = NV20_GRCTX_SIZE; + int i; + + /* Alloc and clear RAMIN to store the context */ + chan->ramin_grctx = nouveau_instmem_alloc(dev, ctx_size, 4); + if (!chan->ramin_grctx) + return DRM_ERR(ENOMEM); + for (i=0; iramin_grctx, i/4, 0x00000000); + + /* Initialise default context values */ + INSTANCE_WR(chan->ramin_grctx, 10, channel << 24); /* CTX_USER */ + + INSTANCE_WR(dev_priv->ctx_table, channel, nouveau_chip_instance_get(dev, chan->ramin_grctx)); + + return 0; +} + +static void nv20_graph_rdi(drm_device_t *dev) { + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + int i; + + NV_WRITE(NV_PGRAPH_RDI_INDEX, 0x2c80000); + for (i = 0; i < 32; i++) + NV_WRITE(NV_PGRAPH_RDI_DATA, 0); + + nouveau_wait_for_idle(dev); +} + +/* Save current context (from PGRAPH) into the channel's context + */ +static void nv20_graph_context_save_current(drm_device_t *dev, int channel) { + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + uint32_t instance; + + instance = INSTANCE_RD(dev_priv->ctx_table, channel); + if (!instance) { + return; + } + if (instance != nouveau_chip_instance_get(dev, dev_priv->fifos[channel].ramin_grctx)) + DRM_ERROR("nv20_graph_context_save_current : bad instance\n"); + + NV_WRITE(NV_PGRAPH_CHANNEL_CTX_SIZE, instance); + NV_WRITE(NV_PGRAPH_CHANNEL_CTX_POINTER, 2 /* save ctx */); +} + + +/* Restore the context for a specific channel into PGRAPH + */ +static void nv20_graph_context_restore(drm_device_t *dev, int channel) { + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + uint32_t instance; + + instance = INSTANCE_RD(dev_priv->ctx_table, channel); + if (!instance) { + return; + } + if (instance != nouveau_chip_instance_get(dev, dev_priv->fifos[channel].ramin_grctx)) + DRM_ERROR("nv20_graph_context_restore_current : bad instance\n"); + + NV_WRITE(NV_PGRAPH_CTX_USER, channel << 24); + NV_WRITE(NV_PGRAPH_CHANNEL_CTX_SIZE, instance); + NV_WRITE(NV_PGRAPH_CHANNEL_CTX_POINTER, 1 /* restore ctx */); +} + +void nouveau_nv20_context_switch(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + int channel, channel_old; + + channel=NV_READ(NV_PFIFO_CACH1_PSH1)&(nouveau_fifo_number(dev)-1); + channel_old = (NV_READ(NV_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); + + DRM_INFO("NV: PGRAPH context switch interrupt channel %x -> %x\n",channel_old, channel); + + NV_WRITE(NV_PGRAPH_FIFO,0x0); + + nv20_graph_context_save_current(dev, channel_old); + + nouveau_wait_for_idle(dev); + + NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x10000000); + + nv20_graph_context_restore(dev, channel_old); + + nouveau_wait_for_idle(dev); + + if ((NV_READ(NV_PGRAPH_CTX_USER) >> 24) != channel) + DRM_ERROR("nouveau_nv20_context_switch : wrong channel restored %x %x!!!\n", channel, NV_READ(NV_PGRAPH_CTX_USER) >> 24); + + NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x10010100); + NV_WRITE(NV_PGRAPH_FFINTFC_ST2, NV_READ(NV_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF); + + NV_WRITE(NV_PGRAPH_FIFO,0x1); +} + +int nv20_graph_init(drm_device_t *dev) { + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + int i; + + /* Create Context Pointer Table */ + dev_priv->ctx_table_size = 32 * 4; + dev_priv->ctx_table = nouveau_instmem_alloc(dev, dev_priv->ctx_table_size, 4); + if (!dev_priv->ctx_table) + return DRM_ERR(ENOMEM); + + for (i=0; i< dev_priv->ctx_table_size; i+=4) + INSTANCE_WR(dev_priv->ctx_table, i/4, 0x00000000); + + NV_WRITE(NV_PGRAPH_CHANNEL_CTX_TABLE, nouveau_chip_instance_get(dev, dev_priv->ctx_table)); + + //XXX need to be done and save/restore for each fifo ??? + nv20_graph_rdi(dev); + + return 0; +} -- cgit v1.2.3 From 06cd15559525cd023fe347fcb8e918c6418b938e Mon Sep 17 00:00:00 2001 From: Matthieu Castet Date: Sat, 13 Jan 2007 23:30:43 +0100 Subject: nouveau: opps restored the wrong channel --- shared-core/nv20_graph.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-core/nv20_graph.c b/shared-core/nv20_graph.c index 6d00effa..a148f5cb 100644 --- a/shared-core/nv20_graph.c +++ b/shared-core/nv20_graph.c @@ -119,7 +119,7 @@ void nouveau_nv20_context_switch(drm_device_t *dev) NV_WRITE(NV_PGRAPH_CTX_CONTROL, 0x10000000); - nv20_graph_context_restore(dev, channel_old); + nv20_graph_context_restore(dev, channel); nouveau_wait_for_idle(dev); -- cgit v1.2.3 From fdbc34fab03eba8d257e14c6d557ffed5fa32c2d Mon Sep 17 00:00:00 2001 From: Matthieu Castet Date: Sun, 14 Jan 2007 20:04:20 +0100 Subject: nouveau: opps nv20 ctx ramin size was wrong --- shared-core/nv20_graph.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared-core/nv20_graph.c b/shared-core/nv20_graph.c index a148f5cb..6e351a2d 100644 --- a/shared-core/nv20_graph.c +++ b/shared-core/nv20_graph.c @@ -27,7 +27,7 @@ #include "nouveau_drv.h" #include "nouveau_drm.h" -#define NV20_GRCTX_SIZE (3529) +#define NV20_GRCTX_SIZE (3529*4) int nv20_graph_context_create(drm_device_t *dev, int channel) { drm_nouveau_private_t *dev_priv = @@ -109,7 +109,7 @@ void nouveau_nv20_context_switch(drm_device_t *dev) channel=NV_READ(NV_PFIFO_CACH1_PSH1)&(nouveau_fifo_number(dev)-1); channel_old = (NV_READ(NV_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); - DRM_INFO("NV: PGRAPH context switch interrupt channel %x -> %x\n",channel_old, channel); + DRM_DEBUG("NV: PGRAPH context switch interrupt channel %x -> %x\n",channel_old, channel); NV_WRITE(NV_PGRAPH_FIFO,0x0); -- cgit v1.2.3