Index: dev/pci/drm/files.pcidrm =================================================================== RCS file: /pub/NetBSD-CVS/src/sys/dev/pci/drm/files.pcidrm,v retrieving revision 1.1 diff -u -p -r1.1 files.pcidrm --- dev/pci/drm/files.pcidrm 24 Mar 2007 15:04:10 -0000 1.1 +++ dev/pci/drm/files.pcidrm 24 Apr 2007 21:55:54 -0000 @@ -65,3 +65,23 @@ file dev/pci/drm/via_map.c viadrm file dev/pci/drm/via_mm.c viadrm file dev/pci/drm/via_verifier.c viadrm file dev/pci/drm/via_video.c viadrm + +device nouveau: drmbase +attach nouveau at drm +file dev/pci/drm/nouveau_drv.c nouveau +file dev/pci/drm/nouveau_fifo.c nouveau +file dev/pci/drm/nouveau_irq.c nouveau +file dev/pci/drm/nouveau_mem.c nouveau +file dev/pci/drm/nouveau_object.c nouveau +file dev/pci/drm/nouveau_state.c nouveau +file dev/pci/drm/nv04_fb.c nouveau +file dev/pci/drm/nv04_graph.c nouveau +file dev/pci/drm/nv04_mc.c nouveau +file dev/pci/drm/nv04_timer.c nouveau +file dev/pci/drm/nv10_fb.c nouveau +file dev/pci/drm/nv10_graph.c nouveau +file dev/pci/drm/nv20_graph.c nouveau +file dev/pci/drm/nv30_graph.c nouveau +file dev/pci/drm/nv40_fb.c nouveau +file dev/pci/drm/nv40_graph.c nouveau +file dev/pci/drm/nv40_mc.c nouveau Index: dev/pci/drm/drm_pciids.h =================================================================== RCS file: /pub/NetBSD-CVS/src/sys/dev/pci/drm/drm_pciids.h,v retrieving revision 1.1 diff -u -p -r1.1 drm_pciids.h --- dev/pci/drm/drm_pciids.h 20 Mar 2007 18:05:32 -0000 1.1 +++ dev/pci/drm/drm_pciids.h 24 Apr 2007 21:55:54 -0000 @@ -302,7 +302,7 @@ {0x105d, 0x5348, IMAGINE_REV4, "Revolution IV"}, \ {0, 0, 0, NULL} -#define nv_PCI_IDS \ +#define nouveau_PCI_IDS \ {0x10DE, 0x0020, NV04, "NVidia RIVA TNT"}, \ {0x10DE, 0x0028, NV04, "NVidia RIVA TNT2"}, \ {0x10DE, 0x002A, NV04, "NVidia Unknown TNT2"}, \ @@ -372,7 +372,7 @@ {0x10DE, 0x0309, NV30, "NVidia Quadro FX 1000"}, \ {0x10DE, 0x0311, NV30, "NVidia GeForce FX 5600 Ultra"}, \ {0x10DE, 0x0312, NV30, "NVidia GeForce FX 5600"}, \ - {0x10DE, 0x0313, NV30, "NVidia 0x0313"},}, \ + {0x10DE, 0x0313, NV30, "NVidia 0x0313"}, \ {0x10DE, 0x0314, NV30, "NVidia GeForce FX 5600SE"}, \ {0x10DE, 0x0316, NV30, "NVidia 0x0316"}, \ {0x10DE, 0x0317, NV30, "NVidia 0x0317"}, \ Index: dev/pci/drm/nouveau_drm.h =================================================================== RCS file: dev/pci/drm/nouveau_drm.h diff -N dev/pci/drm/nouveau_drm.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/pci/drm/nouveau_drm.h 24 Apr 2007 21:55:55 -0000 @@ -0,0 +1,152 @@ +/* + * Copyright 2005 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 + * VA LINUX SYSTEMS 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. + */ + +#ifndef __NOUVEAU_DRM_H__ +#define __NOUVEAU_DRM_H__ + +#define NOUVEAU_DRM_HEADER_PATCHLEVEL 6 + +typedef struct drm_nouveau_fifo_alloc { + int channel; + uint32_t put_base; + /* FIFO control regs */ + drm_handle_t ctrl; + int ctrl_size; + /* DMA command buffer */ + drm_handle_t cmdbuf; + int cmdbuf_size; +} +drm_nouveau_fifo_alloc_t; + +typedef struct drm_nouveau_object_init { + int channel; + uint32_t handle; + int class; +} +drm_nouveau_object_init_t; + +#define NOUVEAU_MEM_ACCESS_RO 1 +#define NOUVEAU_MEM_ACCESS_WO 2 +#define NOUVEAU_MEM_ACCESS_RW 3 +typedef struct drm_nouveau_dma_object_init { + int channel; + uint32_t handle; + int class; + int access; + int target; + uint32_t offset; + int size; +} +drm_nouveau_dma_object_init_t; + +#define NOUVEAU_MEM_FB 0x00000001 +#define NOUVEAU_MEM_AGP 0x00000002 +#define NOUVEAU_MEM_FB_ACCEPTABLE 0x00000004 +#define NOUVEAU_MEM_AGP_ACCEPTABLE 0x00000008 +#define NOUVEAU_MEM_PINNED 0x00000010 +#define NOUVEAU_MEM_USER_BACKED 0x00000020 +#define NOUVEAU_MEM_MAPPED 0x00000040 +#define NOUVEAU_MEM_INSTANCE 0x00000080 /* internal */ + +typedef struct drm_nouveau_mem_alloc { + int flags; + int alignment; + uint64_t size; // in bytes + uint64_t region_offset; +} +drm_nouveau_mem_alloc_t; + +typedef struct drm_nouveau_mem_free { + uint64_t region_offset; + int flags; +} +drm_nouveau_mem_free_t; + +/* FIXME : maybe unify {GET,SET}PARAMs */ +#define NOUVEAU_GETPARAM_PCI_VENDOR 3 +#define NOUVEAU_GETPARAM_PCI_DEVICE 4 +#define NOUVEAU_GETPARAM_BUS_TYPE 5 +#define NOUVEAU_GETPARAM_FB_PHYSICAL 6 +#define NOUVEAU_GETPARAM_AGP_PHYSICAL 7 +#define NOUVEAU_GETPARAM_FB_SIZE 8 +#define NOUVEAU_GETPARAM_AGP_SIZE 9 +typedef struct drm_nouveau_getparam { + uint64_t param; + uint64_t value; +} +drm_nouveau_getparam_t; + +#define NOUVEAU_SETPARAM_CMDBUF_LOCATION 1 +#define NOUVEAU_SETPARAM_CMDBUF_SIZE 2 +typedef struct drm_nouveau_setparam { + uint64_t param; + uint64_t value; +} +drm_nouveau_setparam_t; + +enum nouveau_card_type { + NV_UNKNOWN =0, + NV_01 =1, + NV_03 =3, + NV_04 =4, + NV_05 =5, + NV_10 =10, + NV_11 =10, + NV_15 =10, + NV_17 =10, + NV_20 =20, + NV_25 =20, + NV_30 =30, + NV_34 =30, + NV_40 =40, + NV_44 =44, + NV_50 =50, + NV_LAST =0xffff, +}; + +enum nouveau_bus_type { + NV_AGP =0, + NV_PCI =1, + NV_PCIE =2, +}; + +#define NOUVEAU_MAX_SAREA_CLIPRECTS 16 + +typedef struct drm_nouveau_sarea { + /* the cliprects */ + drm_clip_rect_t boxes[NOUVEAU_MAX_SAREA_CLIPRECTS]; + unsigned int nbox; +} +drm_nouveau_sarea_t; + +#define DRM_NOUVEAU_FIFO_ALLOC 0x00 +#define DRM_NOUVEAU_OBJECT_INIT 0x01 +#define DRM_NOUVEAU_DMA_OBJECT_INIT 0x02 +#define DRM_NOUVEAU_MEM_ALLOC 0x03 +#define DRM_NOUVEAU_MEM_FREE 0x04 +#define DRM_NOUVEAU_GETPARAM 0x05 +#define DRM_NOUVEAU_SETPARAM 0x06 + +#endif /* __NOUVEAU_DRM_H__ */ + Index: dev/pci/drm/nouveau_drv.c =================================================================== RCS file: dev/pci/drm/nouveau_drv.c diff -N dev/pci/drm/nouveau_drv.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/pci/drm/nouveau_drv.c 24 Apr 2007 21:55:55 -0000 @@ -0,0 +1,133 @@ +/* + * Copyright 2005 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 + * VA LINUX SYSTEMS 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 + +#include +#include + +#include "nouveau_drv.h" + +#include "drm_pciids.h" + +static drm_pci_id_list_t nouveau_pciidlist[] = { + nouveau_PCI_IDS +}; + +extern drm_ioctl_desc_t nouveau_ioctls[]; +extern int nouveau_max_ioctl; + +static void nouveau_configure(drm_device_t *dev) +{ + dev->driver.buf_priv_size = 1; /*No dev_priv*/ + dev->driver.load = nouveau_load; + dev->driver.firstopen = nouveau_firstopen; + dev->driver.lastclose = nouveau_lastclose; + dev->driver.unload = nouveau_unload; + dev->driver.preclose = nouveau_preclose; + dev->driver.irq_preinstall = nouveau_irq_preinstall; + dev->driver.irq_postinstall = nouveau_irq_postinstall; + dev->driver.irq_uninstall = nouveau_irq_uninstall; + dev->driver.irq_handler = nouveau_irq_handler; + + dev->driver.ioctls = nouveau_ioctls; + dev->driver.max_ioctl = nouveau_max_ioctl; + + dev->driver.name = DRIVER_NAME; + dev->driver.desc = DRIVER_DESC; + dev->driver.date = DRIVER_DATE; + dev->driver.major = DRIVER_MAJOR; + dev->driver.minor = DRIVER_MINOR; + dev->driver.patchlevel = DRIVER_PATCHLEVEL; + + dev->driver.use_agp = 1; + dev->driver.use_pci_dma = 1; + dev->driver.use_sg = 1; + dev->driver.use_irq = 1; + +} + +#ifdef __FreeBSD__ +static int +nouveau_probe(device_t dev) +{ + return drm_probe(dev, nouveau_pciidlist); +} + +static int +nouveau_attach(device_t nbdev) +{ + drm_device_t *dev = device_get_softc(nbdev); + + bzero(dev, sizeof(drm_device_t)); + nouveau_configure(dev); + return drm_attach(nbdev, nouveau_pciidlist); +} + +static device_method_t nouveau_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, nouveau_probe), + DEVMETHOD(device_attach, nouveau_attach), + DEVMETHOD(device_detach, drm_detach), + + { 0, 0 } +}; + +static driver_t nouveau_driver = { + "drm", + nouveau_methods, + sizeof(drm_device_t) +}; + +extern devclass_t drm_devclass; +#if __FreeBSD_version >= 700010 +DRIVER_MODULE(nouveau, vgapci, nouveau_driver, drm_devclass, 0, 0); +#else +DRIVER_MODULE(nouveau, pci, nouveau_driver, drm_devclass, 0, 0); +#endif +MODULE_DEPEND(nouveau, drm, 1, 1, 1); + +#elif defined(__NetBSD__) || defined(__OpenBSD__) + +static int +nouveau_probe(struct device *parent, struct cfdata *match, void *aux) +{ + struct pci_attach_args *pa = aux; + return drm_probe(pa, nouveau_pciidlist); +} + +static void +nouveau_attach(struct device *parent, struct device *self, void *aux) +{ + struct pci_attach_args *pa = aux; + drm_device_t *dev = (drm_device_t *)self; + + nouveau_configure(dev); + return drm_attach(self, pa, nouveau_pciidlist); +} + +CFATTACH_DECL(nouveau, sizeof(drm_device_t), nouveau_probe, nouveau_attach, + drm_detach, drm_activate); + +#endif Index: dev/pci/drm/nouveau_drv.h =================================================================== RCS file: dev/pci/drm/nouveau_drv.h diff -N dev/pci/drm/nouveau_drv.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/pci/drm/nouveau_drv.h 24 Apr 2007 21:55:55 -0000 @@ -0,0 +1,301 @@ +/* + * Copyright 2005 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 + * VA LINUX SYSTEMS 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. + */ + +#ifndef __NOUVEAU_DRV_H__ +#define __NOUVEAU_DRV_H__ + +#define DRIVER_AUTHOR "Stephane Marchesin" +#define DRIVER_EMAIL "dri-devel@lists.sourceforge.net" + +#define DRIVER_NAME "nouveau" +#define DRIVER_DESC "nVidia Riva/TNT/GeForce" +#define DRIVER_DATE "20060213" + +#define DRIVER_MAJOR 0 +#define DRIVER_MINOR 0 +#define DRIVER_PATCHLEVEL 6 + +#define NOUVEAU_FAMILY 0x0000FFFF +#define NOUVEAU_FLAGS 0xFFFF0000 + +#include "nouveau_drm.h" +#include "nouveau_reg.h" + +struct mem_block { + struct mem_block *next; + struct mem_block *prev; + uint64_t start; + uint64_t size; + DRMFILE filp; /* 0: free, -1: heap, other: real files */ + int flags; + drm_local_map_t *map; +}; + +enum nouveau_flags { + NV_NFORCE =0x10000000, + NV_NFORCE2 =0x20000000 +}; + +struct nouveau_object +{ + struct nouveau_object *next; + struct nouveau_object *prev; + int channel; + + struct mem_block *instance; + uint32_t ht_loc; + + uint32_t handle; + int class; + int engine; +}; + +struct nouveau_fifo +{ + int used; + /* owner of this fifo */ + DRMFILE filp; + /* mapping of the fifo itself */ + drm_local_map_t *map; + /* mapping of the regs controling the fifo */ + drm_local_map_t *regs; + /* dma object for the command buffer itself */ + struct mem_block *cmdbuf_mem; + struct nouveau_object *cmdbuf_obj; + /* PGRAPH context, for cards that keep it in RAMIN */ + struct mem_block *ramin_grctx; + /* objects belonging to this fifo */ + struct nouveau_object *objs; + + /* XXX dynamic alloc ? */ + uint32_t pgraph_ctx [340]; +}; + +struct nouveau_config { + struct { + int location; + int size; + } cmdbuf; +}; + +struct nouveau_engine_func { + struct { + int (*Init)(drm_device_t *dev); + void (*Takedown)(drm_device_t *dev); + } Mc; + + struct { + int (*Init)(drm_device_t *dev); + void (*Takedown)(drm_device_t *dev); + } Timer; + + struct { + int (*Init)(drm_device_t *dev); + void (*Takedown)(drm_device_t *dev); + } Fb; + + struct { + int (*Init)(drm_device_t *dev); + void (*Takedown)(drm_device_t *dev); + } Graph; + + struct { + int (*Init)(drm_device_t *dev); + void (*Takedown)(drm_device_t *dev); + } Fifo; +}; + +typedef struct drm_nouveau_private { + /* the card type, takes NV_* as values */ + int card_type; + /* exact chipset, derived from NV_PMC_BOOT_0 */ + int chipset; + int flags; + + drm_local_map_t *mmio; + drm_local_map_t *fb; + drm_local_map_t *ramin; /* NV40 onwards */ + + int fifo_alloc_count; + struct nouveau_fifo fifos[NV_MAX_FIFO_NUMBER]; + + struct nouveau_engine_func Engine; + + /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */ + uint32_t ramin_size; + uint32_t ramht_offset; + uint32_t ramht_size; + uint32_t ramht_bits; + uint32_t ramfc_offset; + uint32_t ramfc_size; + uint32_t ramro_offset; + uint32_t ramro_size; + + /* base physical adresses */ + uint64_t fb_phys; + uint64_t fb_available_size; + uint64_t agp_phys; + uint64_t agp_available_size; + + /* the mtrr covering the FB */ + int fb_mtrr; + + struct mem_block *agp_heap; + struct mem_block *fb_heap; + 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; + +/* nouveau_state.c */ +extern void nouveau_preclose(drm_device_t * dev, DRMFILE filp); +extern int nouveau_load(struct drm_device *dev, unsigned long flags); +extern int nouveau_firstopen(struct drm_device *dev); +extern void nouveau_lastclose(struct drm_device *dev); +extern int nouveau_unload(struct drm_device *dev); +extern int nouveau_ioctl_getparam(DRM_IOCTL_ARGS); +extern int nouveau_ioctl_setparam(DRM_IOCTL_ARGS); +extern void nouveau_wait_for_idle(struct drm_device *dev); +extern int nouveau_ioctl_card_init(DRM_IOCTL_ARGS); + +/* nouveau_mem.c */ +extern uint64_t nouveau_mem_fb_amount(struct drm_device *dev); +extern void nouveau_mem_release(DRMFILE filp, struct mem_block *heap); +extern int nouveau_ioctl_mem_alloc(DRM_IOCTL_ARGS); +extern int nouveau_ioctl_mem_free(DRM_IOCTL_ARGS); +extern struct mem_block* nouveau_mem_alloc(struct drm_device *dev, int alignment, uint64_t size, int flags, DRMFILE filp); +extern void nouveau_mem_free(struct drm_device* dev, struct mem_block*); +extern int nouveau_mem_init(struct drm_device *dev); +extern void nouveau_mem_close(struct drm_device *dev); +extern int nouveau_instmem_init(struct drm_device *dev); +extern struct mem_block* nouveau_instmem_alloc(struct drm_device *dev, + uint32_t size, uint32_t align); +extern void nouveau_instmem_free(struct drm_device *dev, + struct mem_block *block); +extern uint32_t nouveau_instmem_r32(drm_nouveau_private_t *dev_priv, + struct mem_block *mem, int index); +extern void nouveau_instmem_w32(drm_nouveau_private_t *dev_priv, + struct mem_block *mem, int index, + uint32_t val); + +/* nouveau_fifo.c */ +extern int nouveau_fifo_init(drm_device_t *dev); +extern int nouveau_fifo_number(drm_device_t *dev); +extern int nouveau_fifo_ctx_size(drm_device_t *dev); +extern void nouveau_fifo_cleanup(drm_device_t *dev, DRMFILE filp); +extern int nouveau_fifo_owner(drm_device_t *dev, DRMFILE filp, int channel); +extern void nouveau_fifo_free(drm_device_t *dev, int channel); + +/* nouveau_object.c */ +extern void nouveau_object_cleanup(drm_device_t *dev, int channel); +extern struct nouveau_object * +nouveau_object_gr_create(drm_device_t *dev, int channel, int class); +extern struct nouveau_object * +nouveau_object_dma_create(drm_device_t *dev, int channel, int class, + uint32_t offset, uint32_t size, + int access, int target); +extern void nouveau_object_free(drm_device_t *dev, struct nouveau_object *obj); +extern int nouveau_ioctl_object_init(DRM_IOCTL_ARGS); +extern int nouveau_ioctl_dma_object_init(DRM_IOCTL_ARGS); +extern uint32_t nouveau_chip_instance_get(drm_device_t *dev, struct mem_block *mem); + +/* nouveau_irq.c */ +extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS); +extern void nouveau_irq_preinstall(drm_device_t*); +extern void nouveau_irq_postinstall(drm_device_t*); +extern void nouveau_irq_uninstall(drm_device_t*); + +/* nv04_fb.c */ +extern int nv04_fb_init(drm_device_t *dev); +extern void nv04_fb_takedown(drm_device_t *dev); + +/* nv10_fb.c */ +extern int nv10_fb_init(drm_device_t *dev); +extern void nv10_fb_takedown(drm_device_t *dev); + +/* nv40_fb.c */ +extern int nv40_fb_init(drm_device_t *dev); +extern void nv40_fb_takedown(drm_device_t *dev); + +/* nv04_graph.c */ +extern void nouveau_nv04_context_switch(drm_device_t *dev); +extern int nv04_graph_init(drm_device_t *dev); +extern void nv04_graph_takedown(drm_device_t *dev); +extern int nv04_graph_context_create(drm_device_t *dev, int channel); + +/* nv10_graph.c */ +extern void nouveau_nv10_context_switch(drm_device_t *dev); +extern int nv10_graph_init(drm_device_t *dev); +extern void nv10_graph_takedown(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 void nv20_graph_takedown(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 void nv30_graph_takedown(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 void nv40_graph_takedown(drm_device_t *dev); +extern int nv40_graph_context_create(drm_device_t *dev, int channel); +extern void nv40_graph_context_save_current(drm_device_t *dev); +extern void nv40_graph_context_restore(drm_device_t *dev, int channel); + +/* nv04_mc.c */ +extern int nv04_mc_init(drm_device_t *dev); +extern void nv04_mc_takedown(drm_device_t *dev); + +/* nv40_mc.c */ +extern int nv40_mc_init(drm_device_t *dev); +extern void nv40_mc_takedown(drm_device_t *dev); + +/* nv04_timer.c */ +extern int nv04_timer_init(drm_device_t *dev); +extern void nv04_timer_takedown(drm_device_t *dev); + +#if defined(__powerpc__) +#define NV_READ(reg) in_be32((void __iomem *)(dev_priv->mmio)->handle + (reg) ) +#define NV_WRITE(reg,val) out_be32((void __iomem *)(dev_priv->mmio)->handle + (reg) , (val) ) +#else +#define NV_READ(reg) DRM_READ32( dev_priv->mmio, (reg) ) +#define NV_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) ) +#endif + +#define INSTANCE_WR(mem,ofs,val) nouveau_instmem_w32(dev_priv,(mem),(ofs),(val)) +#define INSTANCE_RD(mem,ofs) nouveau_instmem_r32(dev_priv,(mem),(ofs)) + +#endif /* __NOUVEAU_DRV_H__ */ + Index: dev/pci/drm/nouveau_fifo.c =================================================================== RCS file: dev/pci/drm/nouveau_fifo.c diff -N dev/pci/drm/nouveau_fifo.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/pci/drm/nouveau_fifo.c 24 Apr 2007 21:55:55 -0000 @@ -0,0 +1,719 @@ +/* + * 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 + +#include +#include +#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 */ +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; + + NV_WRITE(NV03_PFIFO_RAMHT, + (0x03 << 24) /* search 128 */ | + ((dev_priv->ramht_bits - 9) << 16) | + (dev_priv->ramht_offset >> 8) + ); + + NV_WRITE(NV03_PFIFO_RAMRO, dev_priv->ramro_offset>>8); + + switch(dev_priv->card_type) + { + case NV_50: + case NV_40: + NV_WRITE(NV40_PFIFO_RAMFC, 0x30002); + break; + case NV_44: + 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: + NV_WRITE(NV03_PFIFO_RAMFC, (dev_priv->ramfc_offset>>8) | + (1 << 16) /* 64 Bytes entry*/); + break; + case NV_04: + case NV_03: + NV_WRITE(NV03_PFIFO_RAMFC, dev_priv->ramfc_offset>>8); + break; + } + + return 0; +} + +int nouveau_fifo_init(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + int ret; + + NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) & + ~NV_PMC_ENABLE_PFIFO); + NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) | + NV_PMC_ENABLE_PFIFO); + + NV_WRITE(NV03_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(NV04_PFIFO_MODE, 0x00000000); + + NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000000); + NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000000); + /* Channel 0 active, PIO mode */ + NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, 0x00000000); + /* PUT and GET to 0 */ + NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT, 0x00000000); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET, 0x00000000); + /* No cmdbuf object */ + NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE, 0x00000000); + NV_WRITE(NV03_PFIFO_CACHE0_PUSH0, 0x00000000); + NV_WRITE(NV03_PFIFO_CACHE0_PULL0, 0x00000000); + NV_WRITE(NV04_PFIFO_SIZE, 0x0000FFFF); + NV_WRITE(NV04_PFIFO_CACHE1_HASH, 0x0000FFFF); + NV_WRITE(NV04_PFIFO_CACHE0_PULL1, 0x00000001); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, 0x00000000); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000); + NV_WRITE(NV04_PFIFO_CACHE1_ENGINE, 0x00000000); + + NV_WRITE(NV04_PFIFO_CACHE1_DMA_FETCH, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + 0x00000000); + + NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001); + NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000001); + NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000001); + NV_WRITE(NV04_PFIFO_CACHE1_PULL1, 0x00000001); + + /* FIXME on NV04 */ + if (dev_priv->card_type >= NV_10) { + NV_WRITE(NV10_PGRAPH_CTX_USER, 0x0); + NV_WRITE(NV04_PFIFO_DELAY_0, 0xff /* retrycount*/ ); + if (dev_priv->card_type >= NV_40) + NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x00002001); + else + NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10110000); + } else { + NV_WRITE(NV04_PGRAPH_CTX_USER, 0x0); + NV_WRITE(NV04_PFIFO_DELAY_0, 0xff /* retrycount*/ ); + NV_WRITE(NV04_PGRAPH_CTX_CONTROL, 0x10110000); + } + + NV_WRITE(NV04_PFIFO_DMA_TIMESLICE, 0x001fffff); + NV_WRITE(NV03_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_object_dma_create(dev, channel, + NV_CLASS_DMA_IN_MEMORY, + cb->start - dev_priv->agp_phys, + cb->size, + NV_DMA_ACCESS_RO, NV_DMA_TARGET_AGP); + } else if (dev_priv->card_type != NV_04) { + cb_dma = nouveau_object_dma_create(dev, channel, + NV_CLASS_DMA_IN_MEMORY, + 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_object_dma_create(dev, channel, + NV_CLASS_DMA_IN_MEMORY, + 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, int channel) +{ + 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[channel].cmdbuf_obj; + + fifoctx=NV_RAMIN+dev_priv->ramfc_offset+channel*ctx_size; + + // clear the fifo context + for(i=0;iinstance)); + + RAMFC_WR(DMA_FETCH, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + 0x00000000); +} +#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, int channel) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_object *cb_obj; + uint32_t fifoctx; + int i; + cb_obj = dev_priv->fifos[channel].cmdbuf_obj; + fifoctx = NV_RAMIN + dev_priv->ramfc_offset + 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_INSTANCE , nouveau_chip_instance_get(dev, + cb_obj->instance)); + + RAMFC_WR(DMA_FETCH, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + 0x00000000); +} + +static void nouveau_nv30_context_init(drm_device_t *dev, int channel) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[channel]; + struct nouveau_object *cb_obj; + uint32_t fifoctx, grctx_inst, cb_inst, ctx_size = 64; + int i; + + cb_obj = dev_priv->fifos[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 + channel * ctx_size; + + for (i = 0; i < ctx_size; i += 4) + NV_WRITE(fifoctx + i, 0); + + RAMFC_WR(REF_CNT, NV_READ(NV10_PFIFO_CACHE1_REF_CNT)); + RAMFC_WR(DMA_INSTANCE, cb_inst); + RAMFC_WR(DMA_STATE, NV_READ(NV04_PFIFO_CACHE1_DMA_STATE)); + RAMFC_WR(DMA_FETCH, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + 0x00000000); + + RAMFC_WR(ENGINE, NV_READ(NV04_PFIFO_CACHE1_ENGINE)); + RAMFC_WR(PULL1_ENGINE, NV_READ(NV04_PFIFO_CACHE1_PULL1)); + RAMFC_WR(ACQUIRE_VALUE, NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_VALUE)); + RAMFC_WR(ACQUIRE_TIMESTAMP, NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP)); + RAMFC_WR(ACQUIRE_TIMEOUT, NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT)); + RAMFC_WR(SEMAPHORE, NV_READ(NV10_PFIFO_CACHE1_SEMAPHORE)); +} + +#if 0 +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(NV03_PFIFO_CACHE1_PUSH1) & (nouveau_fifo_number(dev)-1); + fifoctx = NV_RAMIN + dev_priv->ramfc_offset + channel*64; + + RAMFC_WR(DMA_PUT , NV_READ(NV04_PFIFO_CACHE1_DMA_PUT)); + RAMFC_WR(DMA_GET , NV_READ(NV04_PFIFO_CACHE1_DMA_GET)); + RAMFC_WR(REF_CNT , NV_READ(NV10_PFIFO_CACHE1_REF_CNT)); + RAMFC_WR(DMA_INSTANCE , NV_READ(NV04_PFIFO_CACHE1_DMA_INSTANCE)); + RAMFC_WR(DMA_STATE , NV_READ(NV04_PFIFO_CACHE1_DMA_STATE)); + RAMFC_WR(DMA_FETCH , NV_READ(NV04_PFIFO_CACHE1_DMA_FETCH)); + RAMFC_WR(ENGINE , NV_READ(NV04_PFIFO_CACHE1_ENGINE)); + RAMFC_WR(PULL1_ENGINE , NV_READ(NV04_PFIFO_CACHE1_PULL1)); + RAMFC_WR(ACQUIRE_VALUE , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_VALUE)); + RAMFC_WR(ACQUIRE_TIMESTAMP, NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP)); + RAMFC_WR(ACQUIRE_TIMEOUT , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT)); + RAMFC_WR(SEMAPHORE , NV_READ(NV10_PFIFO_CACHE1_SEMAPHORE)); + RAMFC_WR(DMA_SUBROUTINE , NV_READ(NV10_PFIFO_CACHE1_DMA_SUBROUTINE)); +} +#endif + +#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, int channel) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[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 + 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_INSTANCE , cb_inst); + RAMFC_WR(DMA_FETCH , NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + 0x30000000 /* no idea.. */); + RAMFC_WR(GRCTX_INSTANCE, grctx_inst); + RAMFC_WR(DMA_TIMESLICE , 0x0001FFFF); +} + +#if 0 +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(NV03_PFIFO_CACHE1_PUSH1) & (nouveau_fifo_number(dev)-1); + fifoctx = NV_RAMIN + dev_priv->ramfc_offset + channel*128; + + RAMFC_WR(DMA_PUT , NV_READ(NV04_PFIFO_CACHE1_DMA_PUT)); + RAMFC_WR(DMA_GET , NV_READ(NV04_PFIFO_CACHE1_DMA_GET)); + RAMFC_WR(REF_CNT , NV_READ(NV10_PFIFO_CACHE1_REF_CNT)); + RAMFC_WR(DMA_INSTANCE , NV_READ(NV04_PFIFO_CACHE1_DMA_INSTANCE)); + RAMFC_WR(DMA_DCOUNT , NV_READ(NV10_PFIFO_CACHE1_DMA_DCOUNT)); + RAMFC_WR(DMA_STATE , NV_READ(NV04_PFIFO_CACHE1_DMA_STATE)); + RAMFC_WR(DMA_FETCH , NV_READ(NV04_PFIFO_CACHE1_DMA_FETCH)); + RAMFC_WR(ENGINE , NV_READ(NV04_PFIFO_CACHE1_ENGINE)); + RAMFC_WR(PULL1_ENGINE , NV_READ(NV04_PFIFO_CACHE1_PULL1)); + RAMFC_WR(ACQUIRE_VALUE , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_VALUE)); + RAMFC_WR(ACQUIRE_TIMESTAMP, NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP)); + RAMFC_WR(ACQUIRE_TIMEOUT , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT)); + RAMFC_WR(SEMAPHORE , NV_READ(NV10_PFIFO_CACHE1_SEMAPHORE)); + RAMFC_WR(DMA_SUBROUTINE , NV_READ(NV04_PFIFO_CACHE1_DMA_GET)); + RAMFC_WR(GRCTX_INSTANCE , NV_READ(NV40_PFIFO_GRCTX_INSTANCE)); + RAMFC_WR(DMA_TIMESLICE , NV_READ(NV04_PFIFO_DMA_TIMESLICE) & 0x1FFFF); + RAMFC_WR(UNK_40 , NV_READ(NV40_PFIFO_UNK32E4)); +} +#endif +#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(NV03_PFIFO_CACHE1_PUSH1, 0x00010000|channel); + else + NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, 0x00000100|channel); + + NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT, 0 /*RAMFC_DMA_PUT*/); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET, 0 /*RAMFC_DMA_GET*/); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE, cb_inst); + NV_WRITE(NV04_PFIFO_SIZE , 0x0000FFFF); + NV_WRITE(NV04_PFIFO_CACHE1_HASH, 0x0000FFFF); + + NV_WRITE(NV04_PFIFO_CACHE0_PULL1, 0x00000001); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, 0x00000000); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000); + NV_WRITE(NV04_PFIFO_CACHE1_ENGINE, 0x00000000); + + NV_WRITE(NV04_PFIFO_CACHE1_DMA_FETCH, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | + NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 | +#ifdef __BIG_ENDIAN + NV_PFIFO_CACHE1_BIG_ENDIAN | +#endif + 0x00000000); +} + +/* allocates and initializes a fifo for user space consumption */ +static int nouveau_fifo_alloc(drm_device_t* dev, int *chan_ret, DRMFILE filp) +{ + int ret; + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_object *cb_obj; + int channel; + + /* + * 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(channel=0; channelfifos[channel].used==0) + break; + /* no more fifos. you lost. */ + if (channel==nouveau_fifo_number(dev)) + return DRM_ERR(EINVAL); + (*chan_ret) = channel; + + DRM_INFO("Allocating FIFO number %d\n", channel); + + /* that fifo is used */ + dev_priv->fifos[channel].used = 1; + dev_priv->fifos[channel].filp = filp; + /* FIFO has no objects yet */ + dev_priv->fifos[channel].objs = NULL; + + /* allocate a command buffer, and create a dma object for the gpu */ + ret = nouveau_fifo_cmdbuf_alloc(dev, channel); + if (ret) { + nouveau_fifo_free(dev, channel); + return ret; + } + cb_obj = dev_priv->fifos[channel].cmdbuf_obj; + + nouveau_wait_for_idle(dev); + + /* disable the fifo caches */ + NV_WRITE(NV03_PFIFO_CACHES, 0x00000000); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH, NV_READ(NV04_PFIFO_CACHE1_DMA_PUSH)&(~0x1)); + NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000000); + NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000000); + + /* Construct inital RAMFC for new channel */ + switch(dev_priv->card_type) + { + case NV_04: + case NV_05: + nv04_graph_context_create(dev, channel); + nouveau_nv04_context_init(dev, channel); + break; + case NV_10: + nv10_graph_context_create(dev, channel); + nouveau_nv10_context_init(dev, channel); + break; + case NV_20: + ret = nv20_graph_context_create(dev, channel); + if (ret) { + nouveau_fifo_free(dev, channel); + return ret; + } + nouveau_nv10_context_init(dev, channel); + break; + case NV_30: + ret = nv30_graph_context_create(dev, channel); + if (ret) { + nouveau_fifo_free(dev, channel); + return ret; + } + nouveau_nv30_context_init(dev, channel); + break; + case NV_40: + case NV_44: + case NV_50: + ret = nv40_graph_context_create(dev, channel); + if (ret) { + nouveau_fifo_free(dev, channel); + return ret; + } + nouveau_nv40_context_init(dev, channel); + break; + } + + /* enable the fifo dma operation */ + NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE)|(1<fifo_alloc_count == 0) { + nouveau_fifo_context_restore(dev, channel); + if (dev_priv->card_type >= NV_30) { + struct nouveau_fifo *chan; + uint32_t inst; + + chan = &dev_priv->fifos[channel]; + inst = nouveau_chip_instance_get(dev, + chan->ramin_grctx); + + /* see comments in nv40_graph_context_restore() */ + NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_SIZE, inst); + if (dev_priv->card_type >= NV_40) { + NV_WRITE(0x40032C, inst | 0x01000000); + NV_WRITE(NV40_PFIFO_GRCTX_INSTANCE, inst); + } + } + } + + NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001); + NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000001); + NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000001); + NV_WRITE(NV04_PFIFO_CACHE1_PULL1, 0x00000001); + + /* reenable the fifo caches */ + NV_WRITE(NV03_PFIFO_CACHES, 0x00000001); + + dev_priv->fifo_alloc_count++; + + DRM_INFO("%s: initialised FIFO %d\n", __func__, channel); + return 0; +} + +/* stops a fifo */ +void nouveau_fifo_free(drm_device_t* dev, int channel) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[channel]; + int i; + int ctx_size = nouveau_fifo_ctx_size(dev); + + chan->used = 0; + DRM_INFO("%s: freeing fifo %d\n", __func__, channel); + + /* disable the fifo caches */ + NV_WRITE(NV03_PFIFO_CACHES, 0x00000000); + + NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<ramfc_offset + + channel*ctx_size + i)); + NV_WRITE(NV_RAMIN + dev_priv->ramfc_offset + + channel*ctx_size + i, 0); + } + + /* Cleanup PGRAPH state */ + if (dev_priv->card_type >= NV_40) + nouveau_instmem_free(dev, chan->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, channel, 0); + nouveau_instmem_free(dev, chan->ramin_grctx); + } + + /* reenable the fifo caches */ + NV_WRITE(NV03_PFIFO_CACHES, 0x00000001); + + /* Deallocate command buffer */ + if (chan->cmdbuf_mem) + nouveau_mem_free(dev, chan->cmdbuf_mem); + + /* Destroy objects belonging to the channel */ + nouveau_object_cleanup(dev, channel); + + 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); +} + +int +nouveau_fifo_owner(drm_device_t *dev, DRMFILE filp, int channel) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + + if (channel >= nouveau_fifo_number(dev)) + return 0; + if (dev_priv->fifos[channel].used == 0) + return 0; + return (dev_priv->fifos[channel].filp == filp); +} + +/*********************************** + * ioctls wrapping the functions + ***********************************/ + +static int nouveau_ioctl_fifo_alloc(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_nouveau_private_t *dev_priv = dev->dev_private; + 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.channel, filp); + if (res) + return res; + + /* this should probably disappear in the next abi break? */ + init.put_base = 0; + + /* 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; + res = drm_addmap(dev, init.ctrl, init.ctrl_size, _DRM_REGISTERS, + 0, &dev_priv->fifos[init.channel].regs); + if (res != 0) + return res; + + /* 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; + + DRM_COPY_TO_USER_IOCTL((drm_nouveau_fifo_alloc_t __user *)data, + init, sizeof(init)); + return 0; +} + +/*********************************** + * 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); Index: dev/pci/drm/nouveau_irq.c =================================================================== RCS file: dev/pci/drm/nouveau_irq.c diff -N dev/pci/drm/nouveau_irq.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/pci/drm/nouveau_irq.c 24 Apr 2007 21:55:56 -0000 @@ -0,0 +1,443 @@ +/* + * Copyright (C) 2006 Ben Skeggs. + * + * 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 THE COPYRIGHT OWNER(S) 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. + * + */ + +/* + * Authors: + * Ben Skeggs + */ + +#include + +#include +#include + +#include "nouveau_drm.h" +#include "nouveau_drv.h" +#include "nouveau_reg.h" + +void nouveau_irq_preinstall(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + + DRM_DEBUG("IRQ: preinst\n"); + + if (!dev_priv) { + DRM_ERROR("AIII, no dev_priv\n"); + return; + } + if (!dev_priv->mmio) { + DRM_ERROR("AIII, no dev_priv->mmio\n"); + return; + } + + /* Disable/Clear PFIFO interrupts */ + NV_WRITE(NV03_PFIFO_INTR_EN_0, 0); + NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF); + /* Disable/Clear PGRAPH interrupts */ + if (dev_priv->card_typedev_private; + + if (!dev_priv) { + DRM_ERROR("AIII, no dev_priv\n"); + return; + } + if (!dev_priv->mmio) { + DRM_ERROR("AIII, no dev_priv->mmio\n"); + return; + } + + DRM_DEBUG("IRQ: postinst\n"); + + /* Enable PFIFO error reporting */ + NV_WRITE(NV03_PFIFO_INTR_EN_0 , + NV_PFIFO_INTR_CACHE_ERROR | + NV_PFIFO_INTR_RUNOUT | + NV_PFIFO_INTR_RUNOUT_OVERFLOW | + NV_PFIFO_INTR_DMA_PUSHER | + NV_PFIFO_INTR_DMA_PT | + NV_PFIFO_INTR_SEMAPHORE | + NV_PFIFO_INTR_ACQUIRE_TIMEOUT + ); + NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF); + + /* Enable PGRAPH interrupts */ + if (dev_priv->card_typedev_private; + + if (!dev_priv) { + DRM_ERROR("AIII, no dev_priv\n"); + return; + } + if (!dev_priv->mmio) { + DRM_ERROR("AIII, no dev_priv->mmio\n"); + return; + } + + DRM_DEBUG("IRQ: uninst\n"); + + /* Disable PFIFO interrupts */ + NV_WRITE(NV03_PFIFO_INTR_EN_0, 0); + /* Disable PGRAPH interrupts */ + if (dev_priv->card_typedev_private; + + status = NV_READ(NV03_PFIFO_INTR_0); + if (!status) + return; + chmode = NV_READ(NV04_PFIFO_MODE); + chstat = NV_READ(NV04_PFIFO_DMA); + channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); + + DRM_DEBUG("NV: PFIFO interrupt! Channel=%d, INTSTAT=0x%08x/MODE=0x%08x/PEND=0x%08x\n", channel, status, chmode, chstat); + + if (status & NV_PFIFO_INTR_CACHE_ERROR) { + uint32_t c1get, c1method, c1data; + + DRM_ERROR("NV: PFIFO error interrupt\n"); + + c1get = NV_READ(NV03_PFIFO_CACHE1_GET) >> 2; + if (dev_priv->card_type < NV_40) { + /* Untested, so it may not work.. */ + c1method = NV_READ(NV04_PFIFO_CACHE1_METHOD(c1get)); + c1data = NV_READ(NV04_PFIFO_CACHE1_DATA(c1get)); + } else { + c1method = NV_READ(NV40_PFIFO_CACHE1_METHOD(c1get)); + c1data = NV_READ(NV40_PFIFO_CACHE1_DATA(c1get)); + } + + DRM_ERROR("NV: Channel %d/%d - Method 0x%04x, Data 0x%08x\n", + channel, (c1method >> 13) & 7, + c1method & 0x1ffc, c1data + ); + + status &= ~NV_PFIFO_INTR_CACHE_ERROR; + NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR); + } + + if (status & NV_PFIFO_INTR_DMA_PUSHER) { + DRM_INFO("NV: PFIFO DMA pusher interrupt\n"); + + status &= ~NV_PFIFO_INTR_DMA_PUSHER; + NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_DMA_PUSHER); + + NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000); + if (NV_READ(NV04_PFIFO_CACHE1_DMA_PUT)!=NV_READ(NV04_PFIFO_CACHE1_DMA_GET)) + { + uint32_t getval=NV_READ(NV04_PFIFO_CACHE1_DMA_GET)+4; + NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET,getval); + } + } + + if (status) { + DRM_INFO("NV: unknown PFIFO interrupt. status=0x%08x\n", status); + + NV_WRITE(NV03_PFIFO_INTR_0, status); + } + + NV_WRITE(NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING); +} + +#if 0 +static void nouveau_nv04_context_switch(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + uint32_t channel,i; + uint32_t max=0; + NV_WRITE(NV04_PGRAPH_FIFO,0x0); + channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); + //DRM_INFO("raw PFIFO_CACH1_PHS1 reg is %x\n",NV_READ(NV03_PFIFO_CACHE1_PUSH1)); + //DRM_INFO("currently on channel %d\n",channel); + for (i=0;ififos[i].used)&&(i!=channel)) { + uint32_t put,get,pending; + //put=NV_READ(dev_priv->ramfc_offset+i*32); + //get=NV_READ(dev_priv->ramfc_offset+4+i*32); + put=NV_READ(NV03_FIFO_REGS_DMAPUT(i)); + get=NV_READ(NV03_FIFO_REGS_DMAGET(i)); + pending=NV_READ(NV04_PFIFO_DMA); + //DRM_INFO("Channel %d (put/get %x/%x)\n",i,put,get); + /* mark all pending channels as such */ + if ((put!=get)&!(pending&(1<cur_fifo=channel; + NV_WRITE(NV04_PFIFO_NEXT_CHANNEL,channel|0x100); +#endif + //NV_WRITE(NV03_PFIFO_CACHE1_PUSH1,max|0x100); + //NV_WRITE(0x2050,max|0x100); + + NV_WRITE(NV04_PGRAPH_FIFO,0x1); + +} +#endif + +static void +nouveau_graph_dump_trap_info(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + uint32_t address; + uint32_t channel; + uint32_t method, subc, data; + + address = NV_READ(0x400704); + data = NV_READ(0x400708); + channel = (address >> 20) & 0x1F; + subc = (address >> 16) & 0x7; + method = address & 0x1FFC; + + DRM_ERROR("NV: nSource: 0x%08x, nStatus: 0x%08x\n", + NV_READ(0x400108), NV_READ(0x400104)); + DRM_ERROR("NV: Channel %d/%d (class 0x%04x) -" + "Method 0x%04x, Data 0x%08x\n", + channel, subc, + NV_READ(0x400160+subc*4) & 0xFFFF, + method, data + ); +} + +static void nouveau_pgraph_irq_handler(drm_device_t *dev) +{ + uint32_t status; + drm_nouveau_private_t *dev_priv = dev->dev_private; + + status = NV_READ(NV03_PGRAPH_INTR); + if (!status) + return; + + if (status & NV_PGRAPH_INTR_NOTIFY) { + uint32_t nsource, nstatus, instance, notify; + DRM_DEBUG("NV: PGRAPH notify interrupt\n"); + + nstatus = NV_READ(0x00400104); + nsource = NV_READ(0x00400108); + DRM_DEBUG("nsource:0x%08x\tnstatus:0x%08x\n", nsource, nstatus); + + /* if this wasn't NOTIFICATION_PENDING, dump extra trap info */ + if (nsource & ~(1<<0)) { + nouveau_graph_dump_trap_info(dev); + } else { + instance = NV_READ(0x00400158); + notify = NV_READ(0x00400150) >> 16; + DRM_DEBUG("instance:0x%08x\tnotify:0x%08x\n", + nsource, nstatus); + } + + status &= ~NV_PGRAPH_INTR_NOTIFY; + NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY); + } + + if (status & NV_PGRAPH_INTR_BUFFER_NOTIFY) { + uint32_t nsource, nstatus, instance, notify; + DRM_DEBUG("NV: PGRAPH buffer notify interrupt\n"); + + nstatus = NV_READ(0x00400104); + nsource = NV_READ(0x00400108); + DRM_DEBUG("nsource:0x%08x\tnstatus:0x%08x\n", nsource, nstatus); + + instance = NV_READ(0x00400158); + notify = NV_READ(0x00400150) >> 16; + DRM_DEBUG("instance:0x%08x\tnotify:0x%08x\n", instance, notify); + + status &= ~NV_PGRAPH_INTR_BUFFER_NOTIFY; + NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_BUFFER_NOTIFY); + } + + if (status & NV_PGRAPH_INTR_MISSING_HW) { + DRM_ERROR("NV: PGRAPH missing hw interrupt\n"); + + status &= ~NV_PGRAPH_INTR_MISSING_HW; + NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_MISSING_HW); + } + + if (status & NV_PGRAPH_INTR_ERROR) { + uint32_t nsource, nstatus, instance; + + DRM_ERROR("NV: PGRAPH error interrupt\n"); + + nstatus = NV_READ(0x00400104); + nsource = NV_READ(0x00400108); + DRM_ERROR("nsource:0x%08x\tnstatus:0x%08x\n", nsource, nstatus); + + instance = NV_READ(0x00400158); + DRM_ERROR("instance:0x%08x\n", instance); + + nouveau_graph_dump_trap_info(dev); + + status &= ~NV_PGRAPH_INTR_ERROR; + NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_ERROR); + } + + if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) { + uint32_t channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); + DRM_INFO("NV: PGRAPH context switch interrupt channel %x\n",channel); + switch(dev_priv->card_type) + { + case NV_04: + case NV_05: + nouveau_nv04_context_switch(dev); + break; + case NV_10: + nouveau_nv10_context_switch(dev); + break; + case NV_20: + case NV_30: + nouveau_nv20_context_switch(dev); + break; + default: + DRM_INFO("NV: Context switch not implemented\n"); + break; + } + + status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; + NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); + } + + if (status) { + DRM_INFO("NV: Unknown PGRAPH interrupt! STAT=0x%08x\n", status); + NV_WRITE(NV03_PGRAPH_INTR, status); + } + + NV_WRITE(NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); +} + +static void nouveau_crtc_irq_handler(drm_device_t *dev, int crtc) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + if (crtc&1) { + NV_WRITE(NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK); + } + + if (crtc&2) { + NV_WRITE(NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK); + } +} + +irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS) +{ + drm_device_t *dev = (drm_device_t*)arg; + drm_nouveau_private_t *dev_priv = dev->dev_private; + uint32_t status; + + status = NV_READ(NV03_PMC_INTR_0); + if (!status) + return IRQ_NONE; + + DRM_DEBUG("PMC INTSTAT: 0x%08x\n", status); + + if (status & NV_PMC_INTR_0_PFIFO_PENDING) { + nouveau_fifo_irq_handler(dev); + status &= ~NV_PMC_INTR_0_PFIFO_PENDING; + } + if (status & NV_PMC_INTR_0_PGRAPH_PENDING) { + nouveau_pgraph_irq_handler(dev); + status &= ~NV_PMC_INTR_0_PGRAPH_PENDING; + } + if (status & NV_PMC_INTR_0_CRTCn_PENDING) { + nouveau_crtc_irq_handler(dev, (status>>24)&3); + status &= ~NV_PMC_INTR_0_CRTCn_PENDING; + } + + if (status) + DRM_ERROR("Unhandled PMC INTR status bits 0x%08x\n", status); + + return IRQ_HANDLED; +} + Index: dev/pci/drm/nouveau_mem.c =================================================================== RCS file: dev/pci/drm/nouveau_mem.c diff -N dev/pci/drm/nouveau_mem.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/pci/drm/nouveau_mem.c 24 Apr 2007 21:55:56 -0000 @@ -0,0 +1,689 @@ +/* + * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + * Copyright 2005 Stephane Marchesin + * + * The Weather Channel (TM) funded Tungsten Graphics to develop the + * initial release of the Radeon 8500 driver under the XFree86 license. + * This notice must be preserved. + * + * 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 + * THE AUTHORS AND/OR THEIR 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. + * + * Authors: + * Keith Whitwell + */ + +#include + +#include +#include +#include + +#include "nouveau_drv.h" + +static struct mem_block *split_block(struct mem_block *p, uint64_t start, uint64_t size, + DRMFILE filp) +{ + /* Maybe cut off the start of an existing block */ + if (start > p->start) { + struct mem_block *newblock = + drm_alloc(sizeof(*newblock), DRM_MEM_BUFS); + if (!newblock) + goto out; + newblock->start = start; + newblock->size = p->size - (start - p->start); + newblock->filp = NULL; + newblock->next = p->next; + newblock->prev = p; + p->next->prev = newblock; + p->next = newblock; + p->size -= newblock->size; + p = newblock; + } + + /* Maybe cut off the end of an existing block */ + if (size < p->size) { + struct mem_block *newblock = + drm_alloc(sizeof(*newblock), DRM_MEM_BUFS); + if (!newblock) + goto out; + newblock->start = start + size; + newblock->size = p->size - size; + newblock->filp = NULL; + newblock->next = p->next; + newblock->prev = p; + p->next->prev = newblock; + p->next = newblock; + p->size = size; + } + +out: + /* Our block is in the middle */ + p->filp = filp; + return p; +} + +static struct mem_block *alloc_block(struct mem_block *heap, uint64_t size, + int align2, DRMFILE filp) +{ + struct mem_block *p; + uint64_t mask = (1 << align2) - 1; + + if (!heap) + return NULL; + + list_for_each(p, heap) { + uint64_t start = (p->start + mask) & ~mask; + if (p->filp == 0 && start + size <= p->start + p->size) + return split_block(p, start, size, filp); + } + + return NULL; +} + +static struct mem_block *find_block(struct mem_block *heap, uint64_t start) +{ + struct mem_block *p; + + list_for_each(p, heap) + if (p->start == start) + return p; + + return NULL; +} + +static void free_block(struct mem_block *p) +{ + p->filp = NULL; + + /* Assumes a single contiguous range. Needs a special filp in + * 'heap' to stop it being subsumed. + */ + if (p->next->filp == 0) { + struct mem_block *q = p->next; + p->size += q->size; + p->next = q->next; + p->next->prev = p; + drm_free(q, sizeof(*q), DRM_MEM_BUFS); + } + + if (p->prev->filp == 0) { + struct mem_block *q = p->prev; + q->size += p->size; + q->next = p->next; + q->next->prev = q; + drm_free(p, sizeof(*q), DRM_MEM_BUFS); + } +} + +/* Initialize. How to check for an uninitialized heap? + */ +static int init_heap(struct mem_block **heap, uint64_t start, uint64_t size) +{ + struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFS); + + if (!blocks) + return DRM_ERR(ENOMEM); + + *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS); + if (!*heap) { + drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFS); + return DRM_ERR(ENOMEM); + } + + blocks->start = start; + blocks->size = size; + blocks->filp = NULL; + blocks->next = blocks->prev = *heap; + + memset(*heap, 0, sizeof(**heap)); + (*heap)->filp = (DRMFILE) - 1; + (*heap)->next = (*heap)->prev = blocks; + return 0; +} + +/* + * Free all blocks associated with the releasing filp + */ +void nouveau_mem_release(DRMFILE filp, struct mem_block *heap) +{ + struct mem_block *p; + + if (!heap || !heap->next) + return; + + list_for_each(p, heap) { + if (p->filp == filp) + p->filp = NULL; + } + + /* Assumes a single contiguous range. Needs a special filp in + * 'heap' to stop it being subsumed. + */ + list_for_each(p, heap) { + while ((p->filp == 0) && (p->next->filp == 0) && (p->next!=heap)) { + struct mem_block *q = p->next; + p->size += q->size; + p->next = q->next; + p->next->prev = p; + drm_free(q, sizeof(*q), DRM_MEM_DRIVER); + } + } +} + +/* + * Cleanup everything + */ +static void nouveau_mem_takedown(struct mem_block **heap) +{ + struct mem_block *p; + + if (!*heap) + return; + + for (p = (*heap)->next; p != *heap;) { + struct mem_block *q = p; + p = p->next; + drm_free(q, sizeof(*q), DRM_MEM_DRIVER); + } + + drm_free(*heap, sizeof(**heap), DRM_MEM_DRIVER); + *heap = NULL; +} + +void nouveau_mem_close(struct drm_device *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + nouveau_mem_takedown(&dev_priv->agp_heap); + nouveau_mem_takedown(&dev_priv->fb_heap); +} + +/* Inline function to read from PCI config space */ +static __inline__ uint32_t pci_read_config_dword(struct drm_device *dev, int where) +{ +#if defined(__FreeBSD__) + return pci_read_config(dev->device, where, 4); +#elif defined(__NetBSD__) || defined(__OpenBSD__) + pcitag_t pcitag; + pci_chipset_tag_t chipset_tag = dev->pa.pa_pc; + pcitag = pci_make_tag(chipset_tag, dev->pci_bus, dev->pci_slot, dev->pci_func); + + return (uint32_t)pci_conf_read(chipset_tag, pcitag, where); +#endif +} + +/* returns the amount of FB ram in bytes */ +uint64_t nouveau_mem_fb_amount(struct drm_device *dev) +{ + drm_nouveau_private_t *dev_priv=dev->dev_private; + switch(dev_priv->card_type) + { + case NV_03: + switch(NV_READ(NV03_BOOT_0)&NV03_BOOT_0_RAM_AMOUNT) + { + case NV03_BOOT_0_RAM_AMOUNT_8MB: + case NV03_BOOT_0_RAM_AMOUNT_8MB_SDRAM: + return 8*1024*1024; + case NV03_BOOT_0_RAM_AMOUNT_4MB: + return 4*1024*1024; + case NV03_BOOT_0_RAM_AMOUNT_2MB: + return 2*1024*1024; + } + break; + case NV_04: + case NV_05: + if (NV_READ(NV03_BOOT_0) & 0x00000100) { + return (((NV_READ(NV03_BOOT_0) >> 12) & 0xf)*2+2)*1024*1024; + } else + switch(NV_READ(NV03_BOOT_0)&NV03_BOOT_0_RAM_AMOUNT) + { + case NV04_BOOT_0_RAM_AMOUNT_32MB: + return 32*1024*1024; + case NV04_BOOT_0_RAM_AMOUNT_16MB: + return 16*1024*1024; + case NV04_BOOT_0_RAM_AMOUNT_8MB: + return 8*1024*1024; + case NV04_BOOT_0_RAM_AMOUNT_4MB: + return 4*1024*1024; + } + break; + case NV_10: + case NV_20: + case NV_30: + case NV_40: + case NV_44: + case NV_50: + default: + if (dev_priv->flags&NV_NFORCE) { + uint32_t mem; + mem = pci_read_config_dword(dev, 0x7C); + return (uint64_t)(((mem >> 6) & 31) + 1)*1024*1024; + } else if(dev_priv->flags&NV_NFORCE2) { + uint32_t mem; + mem = pci_read_config_dword(dev, 0x84); + return (uint64_t)(((mem >> 4) & 127) + 1)*1024*1024; + } else { + uint64_t mem; + mem=(NV_READ(NV04_FIFO_DATA)&NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK) >> NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT; + return mem*1024*1024; + } + break; + } + + DRM_ERROR("Unable to detect video ram size. Please report your setup to " DRIVER_EMAIL "\n"); + return 0; +} + + + +int nouveau_mem_init(struct drm_device *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + uint32_t fb_size; + dev_priv->agp_phys=0; + dev_priv->fb_phys=0; + + /* init AGP */ + dev_priv->agp_heap=NULL; + if (drm_device_is_agp(dev)) + { + int err; + drm_agp_info_t info; + drm_agp_mode_t mode; + drm_agp_buffer_t agp_req; + drm_agp_binding_t bind_req; + + err = drm_agp_acquire(dev); + if (err) { + DRM_ERROR("Unable to acquire AGP: %d\n", err); + goto no_agp; + } + + err = drm_agp_info(dev, &info); + if (err) { + DRM_ERROR("Unable to get AGP info: %d\n", err); + goto no_agp; + } + + /* see agp.h for the AGPSTAT_* modes available */ + mode.mode = info.mode; + err = drm_agp_enable(dev, mode); + if (err) { + DRM_ERROR("Unable to enable AGP: %d\n", err); + goto no_agp; + } + + agp_req.size = info.aperture_size; + agp_req.type = 0; + err = drm_agp_alloc(dev, &agp_req); + if (err) { + DRM_ERROR("Unable to alloc AGP: %d\n", err); + goto no_agp; + } + + bind_req.handle = agp_req.handle; + bind_req.offset = 0; + err = drm_agp_bind(dev, &bind_req); + if (err) { + DRM_ERROR("Unable to bind AGP: %d\n", err); + goto no_agp; + } + + if (init_heap(&dev_priv->agp_heap, info.aperture_base, info.aperture_size)) + goto no_agp; + + dev_priv->agp_phys = info.aperture_base; + dev_priv->agp_available_size = info.aperture_size; + } +no_agp: + + /* setup a mtrr over the FB */ + dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1), + nouveau_mem_fb_amount(dev), + DRM_MTRR_WC); + + /* Init FB */ + dev_priv->fb_phys=drm_get_resource_start(dev,1); + fb_size = nouveau_mem_fb_amount(dev); + /* On at least NV40, RAMIN is actually at the end of vram. + * We don't want to allocate this... */ + if (dev_priv->card_type >= NV_40) + fb_size -= dev_priv->ramin_size; + dev_priv->fb_available_size = fb_size; + DRM_DEBUG("Available VRAM: %dKiB\n", fb_size>>10); + + if (fb_size>256*1024*1024) { + /* On cards with > 256Mb, you can't map everything. + * So we create a second FB heap for that type of memory */ + if (init_heap(&dev_priv->fb_heap, drm_get_resource_start(dev,1), 256*1024*1024)) + return DRM_ERR(ENOMEM); + if (init_heap(&dev_priv->fb_nomap_heap, drm_get_resource_start(dev,1)+256*1024*1024, fb_size-256*1024*1024)) + return DRM_ERR(ENOMEM); + } else { + if (init_heap(&dev_priv->fb_heap, drm_get_resource_start(dev,1), fb_size)) + return DRM_ERR(ENOMEM); + dev_priv->fb_nomap_heap=NULL; + } + + return 0; +} + +struct mem_block* nouveau_mem_alloc(struct drm_device *dev, int alignment, uint64_t size, int flags, DRMFILE filp) +{ + struct mem_block *block; + int type; + drm_nouveau_private_t *dev_priv = dev->dev_private; + + /* + * Make things easier on ourselves: all allocations are page-aligned. + * We need that to map allocated regions into the user space + */ + if (alignment < PAGE_SHIFT) + alignment = PAGE_SHIFT; + + /* + * Warn about 0 sized allocations, but let it go through. It'll return 1 page + */ + if (size == 0) + DRM_INFO("warning : 0 byte allocation\n"); + + /* + * Keep alloc size a multiple of the page size to keep drm_addmap() happy + */ + if (size & PAGE_MASK) + size = ((size/PAGE_SIZE) + 1) * PAGE_SIZE; + + if (flags&NOUVEAU_MEM_AGP) { + type=NOUVEAU_MEM_AGP; + block = alloc_block(dev_priv->agp_heap, size, alignment, filp); + if (block) goto alloc_ok; + } + if (flags&(NOUVEAU_MEM_FB|NOUVEAU_MEM_FB_ACCEPTABLE)) { + type=NOUVEAU_MEM_FB; + if (!(flags&NOUVEAU_MEM_MAPPED)) { + block = alloc_block(dev_priv->fb_nomap_heap, size, alignment, filp); + if (block) goto alloc_ok; + } + block = alloc_block(dev_priv->fb_heap, size, alignment, filp); + if (block) goto alloc_ok; + } + if (flags&NOUVEAU_MEM_AGP_ACCEPTABLE) { + type=NOUVEAU_MEM_AGP; + block = alloc_block(dev_priv->agp_heap, size, alignment, filp); + if (block) goto alloc_ok; + } + + return NULL; + +alloc_ok: + block->flags=type; + + if (flags&NOUVEAU_MEM_MAPPED) + { + int ret; + block->flags|=NOUVEAU_MEM_MAPPED; + + if (type == NOUVEAU_MEM_AGP) + ret = drm_addmap(dev, block->start - dev->agp->base, block->size, + _DRM_AGP, 0, &block->map); + else + ret = drm_addmap(dev, block->start, block->size, + _DRM_FRAME_BUFFER, 0, &block->map); + if (ret) { + free_block(block); + return NULL; + } + } + + DRM_INFO("allocated 0x%llx\n", block->start); + return block; +} + +void nouveau_mem_free(struct drm_device* dev, struct mem_block* block) +{ + DRM_INFO("freeing 0x%llx\n", block->start); + if (block->flags&NOUVEAU_MEM_MAPPED) + drm_rmmap(dev, block->map); + free_block(block); +} + +static void +nouveau_instmem_determine_amount(struct drm_device *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + int i; + + /* Figure out how much instance memory we need */ + switch (dev_priv->card_type) { + case NV_40: + /* We'll want more instance memory than this on some NV4x cards. + * There's a 16MB aperture to play with that maps onto the end + * of vram. For now, only reserve a small piece until we know + * more about what each chipset requires. + */ + dev_priv->ramin_size = (1*1024* 1024); + break; + default: + /*XXX: what *are* the limits on ramin_size = (512*1024); + break; + } + DRM_DEBUG("RAMIN size: %dKiB\n", dev_priv->ramin_size>>10); + + /* Clear all of it, except the BIOS image that's in the first 64KiB */ + if (dev_priv->ramin) { + for (i=(64*1024); iramin_size; i+=4) + DRM_WRITE32(dev_priv->ramin, i, 0x00000000); + } else { + for (i=(64*1024); iramin_size; i+=4) + DRM_WRITE32(dev_priv->mmio, NV_RAMIN + i, 0x00000000); + } +} + +static void +nouveau_instmem_configure_fixed_tables(struct drm_device *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + + /* 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); + 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; + 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: + case NV_44: + dev_priv->ramfc_offset = 0x20000; + dev_priv->ramfc_size = nouveau_fifo_number(dev) * + nouveau_fifo_ctx_size(dev); + break; + case NV_30: + case NV_20: + case NV_10: + case NV_04: + case NV_03: + default: + dev_priv->ramfc_offset = 0x11400; + dev_priv->ramfc_size = nouveau_fifo_number(dev) * + nouveau_fifo_ctx_size(dev); + break; + } + DRM_DEBUG("RAMFC offset=0x%x, size=%d\n", dev_priv->ramfc_offset, + dev_priv->ramfc_size); +} + +int nouveau_instmem_init(struct drm_device *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + uint32_t offset; + int ret = 0; + + nouveau_instmem_determine_amount(dev); + nouveau_instmem_configure_fixed_tables(dev); + + /* Create a heap to manage RAMIN allocations, we don't allocate + * the space that was reserved for RAMHT/FC/RO. + */ + offset = dev_priv->ramfc_offset + dev_priv->ramfc_size; + ret = init_heap(&dev_priv->ramin_heap, + offset, dev_priv->ramin_size - offset); + if (ret) { + dev_priv->ramin_heap = NULL; + DRM_ERROR("Failed to init RAMIN heap\n"); + } + + return ret; +} + +struct mem_block *nouveau_instmem_alloc(struct drm_device *dev, + uint32_t size, uint32_t align) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct mem_block *block; + + if (!dev_priv->ramin_heap) { + DRM_ERROR("instmem alloc called without init\n"); + return NULL; + } + + block = alloc_block(dev_priv->ramin_heap, size, align, (DRMFILE)-2); + if (block) { + block->flags = NOUVEAU_MEM_INSTANCE; + DRM_DEBUG("instance(size=%d, align=%d) alloc'd at 0x%08x\n", + size, (1<start); + } + + return block; +} + +void nouveau_instmem_free(struct drm_device *dev, struct mem_block *block) +{ + if (dev && block) { + free_block(block); + } +} + +uint32_t nouveau_instmem_r32(drm_nouveau_private_t *dev_priv, + struct mem_block *mem, int index) +{ + uint32_t ofs = (uint32_t)mem->start + (index<<2); + + if (dev_priv->ramin) { +#if defined(__powerpc__) + return in_be32((void __iomem *)(dev_priv->ramin)->handle + ofs); +#else + return DRM_READ32(dev_priv->ramin, ofs); +#endif + } else { + return NV_READ(NV_RAMIN+ofs); + } +} + +void nouveau_instmem_w32(drm_nouveau_private_t *dev_priv, + struct mem_block *mem, int index, uint32_t val) +{ + uint32_t ofs = (uint32_t)mem->start + (index<<2); + + if (dev_priv->ramin) { +#if defined(__powerpc__) + out_be32((void __iomem *)(dev_priv->ramin)->handle + ofs, val); +#else + DRM_WRITE32(dev_priv->ramin, ofs, val); +#endif + } else { + NV_WRITE(NV_RAMIN+ofs, val); + } +} + +/* + * Ioctls + */ + +int nouveau_ioctl_mem_alloc(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_nouveau_private_t *dev_priv = dev->dev_private; + drm_nouveau_mem_alloc_t alloc; + struct mem_block *block; + + if (!dev_priv) { + DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL(alloc, (drm_nouveau_mem_alloc_t __user *) data, + sizeof(alloc)); + + block=nouveau_mem_alloc(dev, alloc.alignment, alloc.size, alloc.flags, filp); + if (!block) + return DRM_ERR(ENOMEM); + alloc.region_offset=block->start; + alloc.flags=block->flags; + + DRM_COPY_TO_USER_IOCTL((drm_nouveau_mem_alloc_t __user *) data, alloc, sizeof(alloc)); + + return 0; +} + +int nouveau_ioctl_mem_free(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_nouveau_private_t *dev_priv = dev->dev_private; + drm_nouveau_mem_free_t memfree; + struct mem_block *block; + + DRM_COPY_FROM_USER_IOCTL(memfree, (drm_nouveau_mem_free_t __user *) data, + sizeof(memfree)); + + block=NULL; + if (memfree.flags&NOUVEAU_MEM_FB) + block = find_block(dev_priv->fb_heap, memfree.region_offset); + else if (memfree.flags&NOUVEAU_MEM_AGP) + block = find_block(dev_priv->agp_heap, memfree.region_offset); + if (!block) + return DRM_ERR(EFAULT); + if (block->filp != filp) + return DRM_ERR(EPERM); + + nouveau_mem_free(dev, block); + return 0; +} + + Index: dev/pci/drm/nouveau_object.c =================================================================== RCS file: dev/pci/drm/nouveau_object.c diff -N dev/pci/drm/nouveau_object.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/pci/drm/nouveau_object.c 24 Apr 2007 21:55:57 -0000 @@ -0,0 +1,607 @@ +/* + * Copyright (C) 2006 Ben Skeggs. + * + * 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 THE COPYRIGHT OWNER(S) 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. + * + */ + +/* + * Authors: + * Ben Skeggs + */ + +#include + +#include +#include + +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +/* TODO + * - Check object class, deny unsafe objects (add card-specific versioning?) + * - Get rid of DMA object creation, this should be wrapped by MM routines. + */ + +/* Translate a RAMIN offset into a value the card understands, will be useful + * in the future when we can access more instance ram which isn't mapped into + * the PRAMIN aperture + */ +uint32_t +nouveau_chip_instance_get(drm_device_t *dev, struct mem_block *mem) +{ + uint32_t inst = (uint32_t)mem->start >> 4; + DRM_DEBUG("****** on-chip instance for 0x%016llx = 0x%08x\n", + mem->start, inst); + return inst; +} + +static void +nouveau_object_link(drm_device_t *dev, struct nouveau_object *obj) +{ + drm_nouveau_private_t *dev_priv=dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[obj->channel]; + + if (!chan->objs) { + chan->objs = obj; + return; + } + + obj->prev = NULL; + obj->next = chan->objs; + + chan->objs->prev = obj; + chan->objs = obj; +} + +static void +nouveau_object_unlink(drm_device_t *dev, struct nouveau_object *obj) +{ + drm_nouveau_private_t *dev_priv=dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[obj->channel]; + + if (obj->prev == NULL) { + if (obj->next) + obj->next->prev = NULL; + chan->objs = obj->next; + } else if (obj->next == NULL) { + if (obj->prev) + obj->prev->next = NULL; + } else { + obj->prev->next = obj->next; + obj->next->prev = obj->prev; + } +} + +static struct nouveau_object * +nouveau_object_handle_find(drm_device_t *dev, int channel, uint32_t handle) +{ + drm_nouveau_private_t *dev_priv=dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[channel]; + struct nouveau_object *obj = chan->objs; + + DRM_DEBUG("Looking for handle 0x%08x\n", handle); + while (obj) { + if (obj->handle == handle) + return obj; + obj = obj->next; + } + + DRM_DEBUG("...couldn't find handle\n"); + return NULL; +} + +/* NVidia uses context objects to drive drawing operations. + + Context objects can be selected into 8 subchannels in the FIFO, + and then used via DMA command buffers. + + A context object is referenced by a user defined handle (CARD32). The HW + looks up graphics objects in a hash table in the instance RAM. + + An entry in the hash table consists of 2 CARD32. The first CARD32 contains + the handle, the second one a bitfield, that contains the address of the + object in instance RAM. + + The format of the second CARD32 seems to be: + + NV4 to NV30: + + 15: 0 instance_addr >> 4 + 17:16 engine (here uses 1 = graphics) + 28:24 channel id (here uses 0) + 31 valid (use 1) + + NV40: + + 15: 0 instance_addr >> 4 (maybe 19-0) + 21:20 engine (here uses 1 = graphics) + I'm unsure about the other bits, but using 0 seems to work. + + The key into the hash table depends on the object handle and channel id and + is given as: +*/ +static uint32_t +nouveau_ht_handle_hash(drm_device_t *dev, int channel, uint32_t handle) +{ + drm_nouveau_private_t *dev_priv=dev->dev_private; + uint32_t hash = 0; + int i; + + for (i=32;i>0;i-=dev_priv->ramht_bits) { + hash ^= (handle & ((1 << dev_priv->ramht_bits) - 1)); + handle >>= dev_priv->ramht_bits; + } + hash ^= channel << (dev_priv->ramht_bits - 4); + return hash << 3; +} + +static int +nouveau_ht_object_insert(drm_device_t* dev, int channel, uint32_t handle, + struct nouveau_object *obj) +{ + drm_nouveau_private_t *dev_priv=dev->dev_private; + int ht_base = NV_RAMIN + dev_priv->ramht_offset; + int ht_end = ht_base + dev_priv->ramht_size; + int o_ofs, ofs; + + obj->handle = handle; + o_ofs = ofs = nouveau_ht_handle_hash(dev, channel, obj->handle); + + while (NV_READ(ht_base + ofs) || NV_READ(ht_base + ofs + 4)) { + ofs += 8; + if (ofs == ht_end) ofs = ht_base; + if (ofs == o_ofs) { + DRM_ERROR("no free hash table entries\n"); + return 1; + } + } + ofs += ht_base; + + DRM_DEBUG("Channel %d - Handle 0x%08x at 0x%08x\n", + channel, obj->handle, ofs); + + NV_WRITE(NV_RAMHT_HANDLE_OFFSET + ofs, obj->handle); + if (dev_priv->card_type >= NV_40) + NV_WRITE(NV_RAMHT_CONTEXT_OFFSET + ofs, + (channel << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) | + (obj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT) | + nouveau_chip_instance_get(dev, obj->instance) + ); + else + NV_WRITE(NV_RAMHT_CONTEXT_OFFSET + ofs, + NV_RAMHT_CONTEXT_VALID | + (channel << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) | + (obj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT) | + nouveau_chip_instance_get(dev, obj->instance) + ); + + obj->ht_loc = ofs; + return 0; +} + +static void nouveau_hash_table_remove(drm_device_t* dev, + struct nouveau_object *obj) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + + DRM_DEBUG("Remove handle 0x%08x at 0x%08x from HT\n", + obj->handle, obj->ht_loc); + if (obj->ht_loc) { + DRM_DEBUG("... HT entry was: 0x%08x/0x%08x\n", + NV_READ(obj->ht_loc), NV_READ(obj->ht_loc+4)); + NV_WRITE(obj->ht_loc , 0x00000000); + NV_WRITE(obj->ht_loc+4, 0x00000000); + } +} + +static struct nouveau_object * +nouveau_object_instance_alloc(drm_device_t* dev, int channel) +{ + drm_nouveau_private_t *dev_priv=dev->dev_private; + struct nouveau_object *obj; + + /* Create object struct */ + obj = drm_calloc(1, sizeof(struct nouveau_object), DRM_MEM_DRIVER); + if (!obj) { + DRM_ERROR("couldn't alloc memory for object\n"); + return NULL; + } + + /* Allocate instance memory */ + obj->instance = nouveau_instmem_alloc(dev, + (dev_priv->card_type >= NV_40 ? 32 : 16), 4); + if (!obj->instance) { + DRM_ERROR("couldn't alloc RAMIN for object\n"); + drm_free(obj, sizeof(struct nouveau_object), DRM_MEM_DRIVER); + return NULL; + } + + /* Bind object to channel */ + obj->channel = channel; + obj->handle = ~0; + nouveau_object_link(dev, obj); + + return obj; +} + +static void +nouveau_object_instance_free(drm_device_t *dev, struct nouveau_object *obj) +{ + drm_nouveau_private_t *dev_priv=dev->dev_private; + int i; + + /* Unbind object from channel */ + nouveau_object_unlink(dev, obj); + + /* Clean RAMIN entry */ + DRM_DEBUG("Instance entry for 0x%08x" + "(engine %d, class 0x%x) before destroy:\n", + obj->handle, obj->engine, obj->class); + for (i=0; i<(obj->instance->size/4); i++) { + DRM_DEBUG(" +0x%02x: 0x%08x\n", (i*4), + INSTANCE_RD(obj->instance, i)); + INSTANCE_WR(obj->instance, i, 0x00000000); + } + + /* Free RAMIN */ + nouveau_instmem_free(dev, obj->instance); +} + +/* + DMA objects are used to reference a piece of memory in the + framebuffer, PCI or AGP address space. Each object is 16 bytes big + and looks as follows: + + entry[0] + 11:0 class (seems like I can always use 0 here) + 12 page table present? + 13 page entry linear? + 15:14 access: 0 rw, 1 ro, 2 wo + 17:16 target: 0 NV memory, 1 NV memory tiled, 2 PCI, 3 AGP + 31:20 dma adjust (bits 0-11 of the address) + entry[1] + dma limit + entry[2] + 1 0 readonly, 1 readwrite + 31:12 dma frame address (bits 12-31 of the address) + + Non linear page tables seem to need a list of frame addresses afterwards, + the rivatv project has some info on this. + + The method below creates a DMA object in instance RAM and returns a handle + to it that can be used to set up context objects. +*/ + +struct nouveau_object * +nouveau_object_dma_create(drm_device_t* dev, int channel, int class, + uint32_t offset, uint32_t size, + int access, int target) +{ + drm_nouveau_private_t *dev_priv=dev->dev_private; + struct nouveau_object *obj; + uint32_t frame, adjust; + uint32_t pte_flags = 0; + + DRM_DEBUG("offset:0x%08x, size:0x%08x, target:%d, access:%d\n", + offset, size, target, access); + + switch (target) { + case NV_DMA_TARGET_AGP: + offset += dev_priv->agp_phys; + break; + default: + break; + } + + switch (access) { + case NV_DMA_ACCESS_RO: + break; + case NV_DMA_ACCESS_WO: + case NV_DMA_ACCESS_RW: + pte_flags |= (1 << 1); + break; + default: + DRM_ERROR("invalid access mode=%d\n", access); + return NULL; + } + + frame = offset & ~0x00000FFF; + adjust = offset & 0x00000FFF; + + obj = nouveau_object_instance_alloc(dev, channel); + if (!obj) { + DRM_ERROR("couldn't allocate DMA object\n"); + return obj; + } + + obj->engine = 0; + obj->class = class; + + INSTANCE_WR(obj->instance, 0, ((1<<12) | (1<<13) | + (adjust << 20) | + (access << 14) | + (target << 16) | + class)); + INSTANCE_WR(obj->instance, 1, size-1); + INSTANCE_WR(obj->instance, 2, frame | pte_flags); + INSTANCE_WR(obj->instance, 3, frame | pte_flags); + + return obj; +} + + +/* Context objects in the instance RAM have the following structure. + * On NV40 they are 32 byte long, on NV30 and smaller 16 bytes. + + NV4 - NV30: + + entry[0] + 11:0 class + 12 chroma key enable + 13 user clip enable + 14 swizzle enable + 17:15 patch config: + scrcopy_and, rop_and, blend_and, scrcopy, srccopy_pre, blend_pre + 18 synchronize enable + 19 endian: 1 big, 0 little + 21:20 dither mode + 23 single step enable + 24 patch status: 0 invalid, 1 valid + 25 context_surface 0: 1 valid + 26 context surface 1: 1 valid + 27 context pattern: 1 valid + 28 context rop: 1 valid + 29,30 context beta, beta4 + entry[1] + 7:0 mono format + 15:8 color format + 31:16 notify instance address + entry[2] + 15:0 dma 0 instance address + 31:16 dma 1 instance address + entry[3] + dma method traps + + NV40: + No idea what the exact format is. Here's what can be deducted: + + entry[0]: + 11:0 class (maybe uses more bits here?) + 17 user clip enable + 21:19 patch config + 25 patch status valid ? + entry[1]: + 15:0 DMA notifier (maybe 20:0) + entry[2]: + 15:0 DMA 0 instance (maybe 20:0) + 24 big endian + entry[3]: + 15:0 DMA 1 instance (maybe 20:0) + entry[4]: + entry[5]: + set to 0? +*/ +struct nouveau_object * +nouveau_object_gr_create(drm_device_t* dev, int channel, int class) +{ + drm_nouveau_private_t *dev_priv=dev->dev_private; + struct nouveau_object *obj; + + DRM_DEBUG("class=%x\n", class); + + obj = nouveau_object_instance_alloc(dev, channel); + if (!obj) { + DRM_ERROR("couldn't allocate context object\n"); + return obj; + } + + obj->engine = 1; + obj->class = class; + + switch (class) { + case NV_CLASS_NULL: + INSTANCE_WR(obj->instance, 0, 0x00001030); + INSTANCE_WR(obj->instance, 1, 0xFFFFFFFF); + INSTANCE_WR(obj->instance, 2, 0x00000000); + INSTANCE_WR(obj->instance, 2, 0x00000000); + break; + default: + if (dev_priv->card_type >= NV_40) { + INSTANCE_WR(obj->instance, 0, obj->class); + INSTANCE_WR(obj->instance, 1, 0x00000000); +#ifdef __BIG_ENDIAN + INSTANCE_WR(obj->instance, 2, 0x01000000); +#else + INSTANCE_WR(obj->instance, 2, 0x00000000); +#endif + INSTANCE_WR(obj->instance, 3, 0x00000000); + INSTANCE_WR(obj->instance, 4, 0x00000000); + INSTANCE_WR(obj->instance, 5, 0x00000000); + INSTANCE_WR(obj->instance, 6, 0x00000000); + INSTANCE_WR(obj->instance, 7, 0x00000000); + } else { +#ifdef __BIG_ENDIAN + INSTANCE_WR(obj->instance, 0, obj->class | 0x00080000); +#else + INSTANCE_WR(obj->instance, 0, obj->class); +#endif + INSTANCE_WR(obj->instance, 1, 0x00000000); + INSTANCE_WR(obj->instance, 2, 0x00000000); + INSTANCE_WR(obj->instance, 3, 0x00000000); + } + } + + return obj; +} + +void +nouveau_object_free(drm_device_t *dev, struct nouveau_object *obj) +{ + nouveau_object_instance_free(dev, obj); + if (obj->handle != ~0) + nouveau_hash_table_remove(dev, obj); + drm_free(obj, sizeof(struct nouveau_object), DRM_MEM_DRIVER); +} + +void nouveau_object_cleanup(drm_device_t *dev, int channel) +{ + drm_nouveau_private_t *dev_priv=dev->dev_private; + + while (dev_priv->fifos[channel].objs) { + nouveau_object_free(dev, dev_priv->fifos[channel].objs); + } +} + +int nouveau_ioctl_object_init(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_nouveau_object_init_t init; + struct nouveau_object *obj; + + DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_object_init_t __user *) + data, sizeof(init)); + + if (!nouveau_fifo_owner(dev, filp, init.channel)) { + DRM_ERROR("pid %d doesn't own channel %d\n", + DRM_CURRENTPID, init.channel); + return DRM_ERR(EINVAL); + } + + //FIXME: check args, only allow trusted objects to be created + + if (nouveau_object_handle_find(dev, init.channel, init.handle)) { + DRM_ERROR("Channel %d: handle 0x%08x already exists\n", + init.channel, init.handle); + return DRM_ERR(EINVAL); + } + + obj = nouveau_object_gr_create(dev, init.channel, init.class); + if (!obj) + return DRM_ERR(ENOMEM); + + if (nouveau_ht_object_insert(dev, init.channel, init.handle, obj)) { + nouveau_object_free(dev, obj); + return DRM_ERR(ENOMEM); + } + + return 0; +} + +static int +nouveau_dma_object_check_access(drm_device_t *dev, + drm_nouveau_dma_object_init_t *init) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + uint64_t limit; + + /* Check for known DMA object classes */ + switch (init->class) { + case NV_CLASS_DMA_IN_MEMORY: + case NV_CLASS_DMA_FROM_MEMORY: + case NV_CLASS_DMA_TO_MEMORY: + break; + default: + DRM_ERROR("invalid class = 0x%x\n", init->class); + return DRM_ERR(EPERM); + } + + /* Check access mode, and translate to NV_DMA_ACCESS_* */ + switch (init->access) { + case NOUVEAU_MEM_ACCESS_RO: + init->access = NV_DMA_ACCESS_RO; + break; + case NOUVEAU_MEM_ACCESS_WO: + init->access = NV_DMA_ACCESS_WO; + break; + case NOUVEAU_MEM_ACCESS_RW: + init->access = NV_DMA_ACCESS_RW; + break; + default: + DRM_ERROR("invalid access mode = %d\n", init->access); + return DRM_ERR(EPERM); + } + + /* Check that request is within the allowed limits of "target" */ + switch (init->target) { + case NOUVEAU_MEM_FB: + limit = dev_priv->fb_available_size; + init->target = NV_DMA_TARGET_VIDMEM; + break; + case NOUVEAU_MEM_AGP: + limit = dev_priv->agp_available_size; + init->target = NV_DMA_TARGET_AGP; + break; + default: + DRM_ERROR("invalid target = 0x%x\n", init->target); + return DRM_ERR(EPERM); + } + + if ((init->offset > limit) || (init->offset + init->size) > limit) { + DRM_ERROR("access out of allowed range (%d,0x%08x,0x%08x)\n", + init->target, init->offset, init->size); + return DRM_ERR(EPERM); + } + + return 0; +} + +int nouveau_ioctl_dma_object_init(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_nouveau_dma_object_init_t init; + struct nouveau_object *obj; + + DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_dma_object_init_t __user *) + data, sizeof(init)); + + if (!nouveau_fifo_owner(dev, filp, init.channel)) { + DRM_ERROR("pid %d doesn't own channel %d\n", + DRM_CURRENTPID, init.channel); + return DRM_ERR(EINVAL); + } + + if (nouveau_dma_object_check_access(dev, &init)) + return DRM_ERR(EPERM); + + if (nouveau_object_handle_find(dev, init.channel, init.handle)) { + DRM_ERROR("Channel %d: handle 0x%08x already exists\n", + init.channel, init.handle); + return DRM_ERR(EINVAL); + } + + obj = nouveau_object_dma_create(dev, init.channel, init.class, + init.offset, init.size, + init.access, init.target); + if (!obj) + return DRM_ERR(ENOMEM); + + obj->handle = init.handle; + if (nouveau_ht_object_insert(dev, init.channel, init.handle, obj)) { + nouveau_object_free(dev, obj); + return DRM_ERR(ENOMEM); + } + + return 0; +} + Index: dev/pci/drm/nouveau_reg.h =================================================================== RCS file: dev/pci/drm/nouveau_reg.h diff -N dev/pci/drm/nouveau_reg.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/pci/drm/nouveau_reg.h 24 Apr 2007 21:55:58 -0000 @@ -0,0 +1,471 @@ +#define NV04 04 +#define NV10 10 +#define NV20 20 +#define NV30 30 +#define NV40 40 + +#define NV03_BOOT_0 0x00100000 +# define NV03_BOOT_0_RAM_AMOUNT 0x00000003 +# define NV03_BOOT_0_RAM_AMOUNT_8MB 0x00000000 +# define NV03_BOOT_0_RAM_AMOUNT_2MB 0x00000001 +# define NV03_BOOT_0_RAM_AMOUNT_4MB 0x00000002 +# define NV03_BOOT_0_RAM_AMOUNT_8MB_SDRAM 0x00000003 +# define NV04_BOOT_0_RAM_AMOUNT_32MB 0x00000000 +# define NV04_BOOT_0_RAM_AMOUNT_4MB 0x00000001 +# define NV04_BOOT_0_RAM_AMOUNT_8MB 0x00000002 +# define NV04_BOOT_0_RAM_AMOUNT_16MB 0x00000003 + +#define NV04_FIFO_DATA 0x0010020c +# define NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK 0xfff00000 +# define NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT 20 + +#define NV03_PGRAPH_STATUS 0x004006b0 +#define NV04_PGRAPH_STATUS 0x00400700 + +#define NV_RAMIN 0x00700000 + +#define NV_RAMHT_HANDLE_OFFSET 0 +#define NV_RAMHT_CONTEXT_OFFSET 4 +# define NV_RAMHT_CONTEXT_VALID (1<<31) +# define NV_RAMHT_CONTEXT_CHANNEL_SHIFT 24 +# define NV_RAMHT_CONTEXT_ENGINE_SHIFT 16 +# define NV_RAMHT_CONTEXT_ENGINE_SOFTWARE 0 +# define NV_RAMHT_CONTEXT_ENGINE_GRAPHICS 1 +# define NV_RAMHT_CONTEXT_INSTANCE_SHIFT 0 +# define NV40_RAMHT_CONTEXT_CHANNEL_SHIFT 23 +# define NV40_RAMHT_CONTEXT_ENGINE_SHIFT 20 +# define NV40_RAMHT_CONTEXT_INSTANCE_SHIFT 0 + +/* DMA object defines */ +#define NV_DMA_ACCESS_RW 0 +#define NV_DMA_ACCESS_RO 1 +#define NV_DMA_ACCESS_WO 2 +#define NV_DMA_TARGET_VIDMEM 0 +#define NV_DMA_TARGET_PCI 2 +#define NV_DMA_TARGET_AGP 3 + +/* Some object classes we care about in the drm */ +#define NV_CLASS_DMA_FROM_MEMORY 0x00000002 +#define NV_CLASS_DMA_TO_MEMORY 0x00000003 +#define NV_CLASS_NULL 0x00000030 +#define NV_CLASS_DMA_IN_MEMORY 0x0000003D + +#define NV03_FIFO_SIZE 0x8000UL +#define NV_MAX_FIFO_NUMBER 32 +#define NV03_FIFO_REGS_SIZE 0x10000 +#define NV03_FIFO_REGS(i) (0x00800000+i*NV03_FIFO_REGS_SIZE) +# define NV03_FIFO_REGS_DMAPUT(i) (NV03_FIFO_REGS(i)+0x40) +# define NV03_FIFO_REGS_DMAGET(i) (NV03_FIFO_REGS(i)+0x44) + +#define NV03_PMC_BOOT_0 0x00000000 +#define NV03_PMC_INTR_0 0x00000100 +# define NV_PMC_INTR_0_PFIFO_PENDING (1<< 8) +# define NV_PMC_INTR_0_PGRAPH_PENDING (1<<12) +# define NV_PMC_INTR_0_CRTC0_PENDING (1<<24) +# define NV_PMC_INTR_0_CRTC1_PENDING (1<<25) +# define NV_PMC_INTR_0_CRTCn_PENDING (3<<24) +#define NV03_PMC_INTR_EN_0 0x00000140 +# define NV_PMC_INTR_EN_0_MASTER_ENABLE (1<< 0) +#define NV03_PMC_ENABLE 0x00000200 +# define NV_PMC_ENABLE_PFIFO (1<< 8) +# define NV_PMC_ENABLE_PGRAPH (1<<12) +/* Disabling the below bit breaks newer (G7X only?) mobile chipsets, + * the card will hang early on in the X init process. + */ +# define NV_PMC_ENABLE_UNK13 (1<<13) +#define NV40_PMC_1700 0x00001700 +#define NV40_PMC_1704 0x00001704 +#define NV40_PMC_1708 0x00001708 +#define NV40_PMC_170C 0x0000170C + +#define NV04_PTIMER_INTR_0 0x00009100 +#define NV04_PTIMER_INTR_EN_0 0x00009140 +#define NV04_PTIMER_NUMERATOR 0x00009200 +#define NV04_PTIMER_DENOMINATOR 0x00009210 +#define NV04_PTIMER_TIME_0 0x00009400 +#define NV04_PTIMER_TIME_1 0x00009410 +#define NV04_PTIMER_ALARM_0 0x00009420 + +#define NV04_PFB_CFG0 0x00100200 +#define NV04_PFB_CFG1 0x00100204 +#define NV40_PFB_020C 0x0010020C +#define NV10_PFB_TILE(i) (0x00100240 + (i*16)) +#define NV10_PFB_TILE__SIZE 8 +#define NV10_PFB_TLIMIT(i) (0x00100244 + (i*16)) +#define NV10_PFB_TSIZE(i) (0x00100248 + (i*16)) +#define NV10_PFB_TSTATUS(i) (0x0010024C + (i*16)) +#define NV10_PFB_CLOSE_PAGE2 0x0010033C +#define NV40_PFB_TILE(i) (0x00100600 + (i*16)) +#define NV40_PFB_TILE__SIZE_0 12 +#define NV40_PFB_TILE__SIZE_1 15 +#define NV40_PFB_TLIMIT(i) (0x00100604 + (i*16)) +#define NV40_PFB_TSIZE(i) (0x00100608 + (i*16)) +#define NV40_PFB_TSTATUS(i) (0x0010060C + (i*16)) + +#define NV04_PGRAPH_DEBUG_0 0x00400080 +#define NV04_PGRAPH_DEBUG_1 0x00400084 +#define NV04_PGRAPH_DEBUG_2 0x00400088 +#define NV04_PGRAPH_DEBUG_3 0x0040008c +#define NV10_PGRAPH_DEBUG_4 0x00400090 +#define NV03_PGRAPH_INTR 0x00400100 +#define NV03_PGRAPH_INTR_EN 0x00400140 +#define NV40_PGRAPH_INTR_EN 0x0040013C +# define NV_PGRAPH_INTR_NOTIFY (1<< 0) +# define NV_PGRAPH_INTR_MISSING_HW (1<< 4) +# define NV_PGRAPH_INTR_CONTEXT_SWITCH (1<<12) +# define NV_PGRAPH_INTR_BUFFER_NOTIFY (1<<16) +# define NV_PGRAPH_INTR_ERROR (1<<20) +#define NV10_PGRAPH_CTX_CONTROL 0x00400144 +#define NV10_PGRAPH_CTX_USER 0x00400148 +#define NV10_PGRAPH_CTX_SWITCH1 0x0040014C +#define NV10_PGRAPH_CTX_SWITCH2 0x00400150 +#define NV10_PGRAPH_CTX_SWITCH3 0x00400154 +#define NV10_PGRAPH_CTX_SWITCH4 0x00400158 +#define NV10_PGRAPH_CTX_SWITCH5 0x0040015C +#define NV04_PGRAPH_CTX_SWITCH1 0x00400160 +#define NV10_PGRAPH_CTX_CACHE1 0x00400160 +#define NV04_PGRAPH_CTX_SWITCH2 0x00400164 +#define NV04_PGRAPH_CTX_SWITCH3 0x00400168 +#define NV04_PGRAPH_CTX_SWITCH4 0x0040016C +#define NV04_PGRAPH_CTX_CONTROL 0x00400170 +#define NV04_PGRAPH_CTX_USER 0x00400174 +#define NV04_PGRAPH_CTX_CACHE1 0x00400180 +#define NV10_PGRAPH_CTX_CACHE2 0x00400180 +#define NV03_PGRAPH_CTX_CONTROL 0x00400190 +#define NV03_PGRAPH_CTX_USER 0x00400194 +#define NV04_PGRAPH_CTX_CACHE2 0x004001A0 +#define NV10_PGRAPH_CTX_CACHE3 0x004001A0 +#define NV04_PGRAPH_CTX_CACHE3 0x004001C0 +#define NV10_PGRAPH_CTX_CACHE4 0x004001C0 +#define NV04_PGRAPH_CTX_CACHE4 0x004001E0 +#define NV10_PGRAPH_CTX_CACHE5 0x004001E0 +#define NV03_PGRAPH_ABS_X_RAM 0x00400400 +#define NV03_PGRAPH_ABS_Y_RAM 0x00400480 +#define NV03_PGRAPH_X_MISC 0x00400500 +#define NV03_PGRAPH_Y_MISC 0x00400504 +#define NV04_PGRAPH_VALID1 0x00400508 +#define NV04_PGRAPH_SOURCE_COLOR 0x0040050C +#define NV04_PGRAPH_MISC24_0 0x00400510 +#define NV03_PGRAPH_XY_LOGIC_MISC0 0x00400514 +#define NV03_PGRAPH_XY_LOGIC_MISC1 0x00400518 +#define NV03_PGRAPH_XY_LOGIC_MISC2 0x0040051C +#define NV03_PGRAPH_XY_LOGIC_MISC3 0x00400520 +#define NV03_PGRAPH_CLIPX_0 0x00400524 +#define NV03_PGRAPH_CLIPX_1 0x00400528 +#define NV03_PGRAPH_CLIPY_0 0x0040052C +#define NV03_PGRAPH_CLIPY_1 0x00400530 +#define NV03_PGRAPH_ABS_ICLIP_XMAX 0x00400534 +#define NV03_PGRAPH_ABS_ICLIP_YMAX 0x00400538 +#define NV03_PGRAPH_ABS_UCLIP_XMIN 0x0040053C +#define NV03_PGRAPH_ABS_UCLIP_YMIN 0x00400540 +#define NV03_PGRAPH_ABS_UCLIP_XMAX 0x00400544 +#define NV03_PGRAPH_ABS_UCLIP_YMAX 0x00400548 +#define NV03_PGRAPH_ABS_UCLIPA_XMIN 0x00400560 +#define NV03_PGRAPH_ABS_UCLIPA_YMIN 0x00400564 +#define NV03_PGRAPH_ABS_UCLIPA_XMAX 0x00400568 +#define NV03_PGRAPH_ABS_UCLIPA_YMAX 0x0040056C +#define NV04_PGRAPH_MISC24_1 0x00400570 +#define NV04_PGRAPH_MISC24_2 0x00400574 +#define NV04_PGRAPH_VALID2 0x00400578 +#define NV04_PGRAPH_PASSTHRU_0 0x0040057C +#define NV04_PGRAPH_PASSTHRU_1 0x00400580 +#define NV04_PGRAPH_PASSTHRU_2 0x00400584 +#define NV10_PGRAPH_DIMX_TEXTURE 0x00400588 +#define NV10_PGRAPH_WDIMX_TEXTURE 0x0040058C +#define NV04_PGRAPH_COMBINE_0_ALPHA 0x00400590 +#define NV04_PGRAPH_COMBINE_0_COLOR 0x00400594 +#define NV04_PGRAPH_COMBINE_1_ALPHA 0x00400598 +#define NV04_PGRAPH_COMBINE_1_COLOR 0x0040059C +#define NV04_PGRAPH_FORMAT_0 0x004005A8 +#define NV04_PGRAPH_FORMAT_1 0x004005AC +#define NV04_PGRAPH_FILTER_0 0x004005B0 +#define NV04_PGRAPH_FILTER_1 0x004005B4 +#define NV03_PGRAPH_MONO_COLOR0 0x00400600 +#define NV04_PGRAPH_ROP3 0x00400604 +#define NV04_PGRAPH_BETA_AND 0x00400608 +#define NV04_PGRAPH_BETA_PREMULT 0x0040060C +#define NV04_PGRAPH_LIMIT_VIOL_PIX 0x00400610 +#define NV04_PGRAPH_FORMATS 0x00400618 +#define NV10_PGRAPH_DEBUG_2 0x00400620 +#define NV04_PGRAPH_BOFFSET0 0x00400640 +#define NV04_PGRAPH_BOFFSET1 0x00400644 +#define NV04_PGRAPH_BOFFSET2 0x00400648 +#define NV04_PGRAPH_BOFFSET3 0x0040064C +#define NV04_PGRAPH_BOFFSET4 0x00400650 +#define NV04_PGRAPH_BOFFSET5 0x00400654 +#define NV04_PGRAPH_BBASE0 0x00400658 +#define NV04_PGRAPH_BBASE1 0x0040065C +#define NV04_PGRAPH_BBASE2 0x00400660 +#define NV04_PGRAPH_BBASE3 0x00400664 +#define NV04_PGRAPH_BBASE4 0x00400668 +#define NV04_PGRAPH_BBASE5 0x0040066C +#define NV04_PGRAPH_BPITCH0 0x00400670 +#define NV04_PGRAPH_BPITCH1 0x00400674 +#define NV04_PGRAPH_BPITCH2 0x00400678 +#define NV04_PGRAPH_BPITCH3 0x0040067C +#define NV04_PGRAPH_BPITCH4 0x00400680 +#define NV04_PGRAPH_BLIMIT0 0x00400684 +#define NV04_PGRAPH_BLIMIT1 0x00400688 +#define NV04_PGRAPH_BLIMIT2 0x0040068C +#define NV04_PGRAPH_BLIMIT3 0x00400690 +#define NV04_PGRAPH_BLIMIT4 0x00400694 +#define NV04_PGRAPH_BLIMIT5 0x00400698 +#define NV04_PGRAPH_BSWIZZLE2 0x0040069C +#define NV04_PGRAPH_BSWIZZLE5 0x004006A0 +#define NV04_PGRAPH_SURFACE 0x0040070C +#define NV04_PGRAPH_STATE 0x00400710 +#define NV10_PGRAPH_SURFACE 0x00400710 +#define NV04_PGRAPH_NOTIFY 0x00400714 +#define NV10_PGRAPH_STATE 0x00400714 +#define NV10_PGRAPH_NOTIFY 0x00400718 + +#define NV04_PGRAPH_FIFO 0x00400720 + +#define NV04_PGRAPH_BPIXEL 0x00400724 +#define NV10_PGRAPH_RDI_INDEX 0x00400750 +#define NV04_PGRAPH_FFINTFC_ST2 0x00400754 +#define NV10_PGRAPH_RDI_DATA 0x00400754 +#define NV04_PGRAPH_DMA_PITCH 0x00400760 +#define NV10_PGRAPH_FFINTFC_ST2 0x00400764 +#define NV04_PGRAPH_DVD_COLORFMT 0x00400764 +#define NV04_PGRAPH_SCALED_FORMAT 0x00400768 +#define NV10_PGRAPH_DMA_PITCH 0x00400770 +#define NV10_PGRAPH_DVD_COLORFMT 0x00400774 +#define NV10_PGRAPH_SCALED_FORMAT 0x00400778 +#define NV10_PGRAPH_CHANNEL_CTX_TABLE 0x00400780 +#define NV10_PGRAPH_CHANNEL_CTX_SIZE 0x00400784 +#define NV10_PGRAPH_CHANNEL_CTX_POINTER 0x00400788 +#define NV04_PGRAPH_PATT_COLOR0 0x00400800 +#define NV04_PGRAPH_PATT_COLOR1 0x00400804 +#define NV04_PGRAPH_PATTERN 0x00400808 +#define NV04_PGRAPH_PATTERN_SHAPE 0x00400810 +#define NV04_PGRAPH_CHROMA 0x00400814 +#define NV04_PGRAPH_CONTROL0 0x00400818 +#define NV04_PGRAPH_CONTROL1 0x0040081C +#define NV04_PGRAPH_CONTROL2 0x00400820 +#define NV04_PGRAPH_BLEND 0x00400824 +#define NV04_PGRAPH_STORED_FMT 0x00400830 +#define NV04_PGRAPH_PATT_COLORRAM 0x00400900 +#define NV40_PGRAPH_TILE0(i) 0x00400900 +#define NV40_PGRAPH_TLIMIT0(i) 0x00400904 +#define NV40_PGRAPH_TSIZE0(i) 0x00400908 +#define NV40_PGRAPH_TSTATUS0(i) 0x0040090C +#define NV10_PGRAPH_TILE(i) (0x00400B00 + (i*16)) +#define NV10_PGRAPH_TLIMIT(i) (0x00400B04 + (i*16)) +#define NV10_PGRAPH_TSIZE(i) (0x00400B08 + (i*16)) +#define NV10_PGRAPH_TSTATUS(i) (0x00400B0C + (i*16)) +#define NV04_PGRAPH_U_RAM 0x00400D00 +#define NV47_PGRAPH_TILE0(i) 0x00400D00 +#define NV47_PGRAPH_TLIMIT0(i) 0x00400D04 +#define NV47_PGRAPH_TSIZE0(i) 0x00400D08 +#define NV47_PGRAPH_TSTATUS0(i) 0x00400D0C +#define NV04_PGRAPH_V_RAM 0x00400D40 +#define NV04_PGRAPH_W_RAM 0x00400D80 +#define NV10_PGRAPH_WINDOWCLIP_HORIZONTAL 0x00400F00 +#define NV10_PGRAPH_WINDOWCLIP_VERTICAL 0x00400F20 +#define NV10_PGRAPH_XFMODE0 0x00400F40 +#define NV10_PGRAPH_XFMODE1 0x00400F44 +#define NV10_PGRAPH_GLOBALSTATE0 0x00400F48 +#define NV10_PGRAPH_GLOBALSTATE1 0x00400F4C +#define NV10_PGRAPH_PIPE_ADDRESS 0x00400F50 +#define NV10_PGRAPH_PIPE_DATA 0x00400F54 +#define NV04_PGRAPH_DMA_START_0 0x00401000 +#define NV04_PGRAPH_DMA_START_1 0x00401004 +#define NV04_PGRAPH_DMA_LENGTH 0x00401008 +#define NV04_PGRAPH_DMA_MISC 0x0040100C +#define NV04_PGRAPH_DMA_DATA_0 0x00401020 +#define NV04_PGRAPH_DMA_DATA_1 0x00401024 +#define NV04_PGRAPH_DMA_RM 0x00401030 +#define NV04_PGRAPH_DMA_A_XLATE_INST 0x00401040 +#define NV04_PGRAPH_DMA_A_CONTROL 0x00401044 +#define NV04_PGRAPH_DMA_A_LIMIT 0x00401048 +#define NV04_PGRAPH_DMA_A_TLB_PTE 0x0040104C +#define NV04_PGRAPH_DMA_A_TLB_TAG 0x00401050 +#define NV04_PGRAPH_DMA_A_ADJ_OFFSET 0x00401054 +#define NV04_PGRAPH_DMA_A_OFFSET 0x00401058 +#define NV04_PGRAPH_DMA_A_SIZE 0x0040105C +#define NV04_PGRAPH_DMA_A_Y_SIZE 0x00401060 +#define NV04_PGRAPH_DMA_B_XLATE_INST 0x00401080 +#define NV04_PGRAPH_DMA_B_CONTROL 0x00401084 +#define NV04_PGRAPH_DMA_B_LIMIT 0x00401088 +#define NV04_PGRAPH_DMA_B_TLB_PTE 0x0040108C +#define NV04_PGRAPH_DMA_B_TLB_TAG 0x00401090 +#define NV04_PGRAPH_DMA_B_ADJ_OFFSET 0x00401094 +#define NV04_PGRAPH_DMA_B_OFFSET 0x00401098 +#define NV04_PGRAPH_DMA_B_SIZE 0x0040109C +#define NV04_PGRAPH_DMA_B_Y_SIZE 0x004010A0 +#define NV40_PGRAPH_TILE1(i) 0x00406900 +#define NV40_PGRAPH_TLIMIT1(i) 0x00406904 +#define NV40_PGRAPH_TSIZE1(i) 0x00406908 +#define NV40_PGRAPH_TSTATUS1(i) 0x0040690C + + +/* It's a guess that this works on NV03. Confirmed on NV04, though */ +#define NV04_PFIFO_DELAY_0 0x00002040 +#define NV04_PFIFO_DMA_TIMESLICE 0x00002044 +#define NV04_PFIFO_NEXT_CHANNEL 0x00002050 +#define NV03_PFIFO_INTR_0 0x00002100 +#define NV03_PFIFO_INTR_EN_0 0x00002140 +# define NV_PFIFO_INTR_CACHE_ERROR (1<< 0) +# define NV_PFIFO_INTR_RUNOUT (1<< 4) +# define NV_PFIFO_INTR_RUNOUT_OVERFLOW (1<< 8) +# define NV_PFIFO_INTR_DMA_PUSHER (1<<12) +# define NV_PFIFO_INTR_DMA_PT (1<<16) +# define NV_PFIFO_INTR_SEMAPHORE (1<<20) +# define NV_PFIFO_INTR_ACQUIRE_TIMEOUT (1<<24) +#define NV03_PFIFO_RAMHT 0x00002210 +#define NV03_PFIFO_RAMFC 0x00002214 +#define NV03_PFIFO_RAMRO 0x00002218 +#define NV40_PFIFO_RAMFC 0x00002220 +#define NV03_PFIFO_CACHES 0x00002500 +#define NV04_PFIFO_MODE 0x00002504 +#define NV04_PFIFO_DMA 0x00002508 +#define NV04_PFIFO_SIZE 0x0000250c +#define NV03_PFIFO_CACHE0_PUSH0 0x00003000 +#define NV03_PFIFO_CACHE0_PULL0 0x00003040 +#define NV04_PFIFO_CACHE0_PULL0 0x00003050 +#define NV04_PFIFO_CACHE0_PULL1 0x00003054 +#define NV03_PFIFO_CACHE1_PUSH0 0x00003200 +#define NV03_PFIFO_CACHE1_PUSH1 0x00003204 +#define NV04_PFIFO_CACHE1_DMA_PUSH 0x00003220 +#define NV04_PFIFO_CACHE1_DMA_FETCH 0x00003224 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_8_BYTES 0x00000000 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_16_BYTES 0x00000008 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_24_BYTES 0x00000010 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_32_BYTES 0x00000018 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_40_BYTES 0x00000020 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_48_BYTES 0x00000028 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_56_BYTES 0x00000030 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_64_BYTES 0x00000038 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_72_BYTES 0x00000040 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_80_BYTES 0x00000048 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_88_BYTES 0x00000050 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_96_BYTES 0x00000058 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_104_BYTES 0x00000060 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES 0x00000068 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_120_BYTES 0x00000070 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES 0x00000078 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_136_BYTES 0x00000080 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_144_BYTES 0x00000088 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_152_BYTES 0x00000090 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_160_BYTES 0x00000098 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_168_BYTES 0x000000A0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_176_BYTES 0x000000A8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_184_BYTES 0x000000B0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_192_BYTES 0x000000B8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_200_BYTES 0x000000C0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_208_BYTES 0x000000C8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_216_BYTES 0x000000D0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_224_BYTES 0x000000D8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_232_BYTES 0x000000E0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_240_BYTES 0x000000E8 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_248_BYTES 0x000000F0 +# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_256_BYTES 0x000000F8 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE 0x0000E000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_32_BYTES 0x00000000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_64_BYTES 0x00002000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_96_BYTES 0x00004000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES 0x00006000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_160_BYTES 0x00008000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_192_BYTES 0x0000A000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_224_BYTES 0x0000C000 +# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_256_BYTES 0x0000E000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS 0x001F0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_0 0x00000000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_1 0x00010000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_2 0x00020000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_3 0x00030000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 0x00040000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_5 0x00050000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_6 0x00060000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_7 0x00070000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 0x00080000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_9 0x00090000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_10 0x000A0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_11 0x000B0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_12 0x000C0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_13 0x000D0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_14 0x000E0000 +# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_15 0x000F0000 +# define NV_PFIFO_CACHE1_ENDIAN 0x80000000 +# define NV_PFIFO_CACHE1_LITTLE_ENDIAN 0x7FFFFFFF +# define NV_PFIFO_CACHE1_BIG_ENDIAN 0x80000000 +#define NV04_PFIFO_CACHE1_DMA_STATE 0x00003228 +#define NV04_PFIFO_CACHE1_DMA_INSTANCE 0x0000322c +#define NV04_PFIFO_CACHE1_DMA_CTL 0x00003230 +#define NV04_PFIFO_CACHE1_DMA_PUT 0x00003240 +#define NV04_PFIFO_CACHE1_DMA_GET 0x00003244 +#define NV10_PFIFO_CACHE1_REF_CNT 0x00003248 +#define NV10_PFIFO_CACHE1_DMA_SUBROUTINE 0x0000324C +#define NV03_PFIFO_CACHE1_PULL0 0x00003240 +#define NV04_PFIFO_CACHE1_PULL0 0x00003250 +#define NV03_PFIFO_CACHE1_PULL1 0x00003250 +#define NV04_PFIFO_CACHE1_PULL1 0x00003254 +#define NV04_PFIFO_CACHE1_HASH 0x00003258 +#define NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT 0x00003260 +#define NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP 0x00003264 +#define NV10_PFIFO_CACHE1_ACQUIRE_VALUE 0x00003268 +#define NV10_PFIFO_CACHE1_SEMAPHORE 0x0000326C +#define NV03_PFIFO_CACHE1_GET 0x00003270 +#define NV04_PFIFO_CACHE1_ENGINE 0x00003280 +#define NV10_PFIFO_CACHE1_DMA_DCOUNT 0x000032A0 +#define NV40_PFIFO_GRCTX_INSTANCE 0x000032E0 +#define NV40_PFIFO_UNK32E4 0x000032E4 +#define NV04_PFIFO_CACHE1_METHOD(i) (0x00003800+(i*8)) +#define NV04_PFIFO_CACHE1_DATA(i) (0x00003804+(i*8)) +#define NV40_PFIFO_CACHE1_METHOD(i) (0x00090000+(i*8)) +#define NV40_PFIFO_CACHE1_DATA(i) (0x00090004+(i*8)) + +#define NV_CRTC0_INTSTAT 0x00600100 +#define NV_CRTC0_INTEN 0x00600140 +#define NV_CRTC1_INTSTAT 0x00602100 +#define NV_CRTC1_INTEN 0x00602140 +# define NV_CRTC_INTR_VBLANK (1<<0) + +/* Fifo commands. These are not regs, neither masks */ +#define NV03_FIFO_CMD_JUMP 0x20000000 +#define NV03_FIFO_CMD_JUMP_OFFSET_MASK 0x1ffffffc +#define NV03_FIFO_CMD_REWIND (NV03_FIFO_CMD_JUMP | (0 & NV03_FIFO_CMD_JUMP_OFFSET_MASK)) + +/* RAMFC offsets */ +#define NV04_RAMFC_DMA_PUT 0x00 +#define NV04_RAMFC_DMA_GET 0x04 +#define NV04_RAMFC_DMA_INSTANCE 0x08 +#define NV04_RAMFC_DMA_FETCH 0x10 + +#define NV10_RAMFC_DMA_PUT 0x00 +#define NV10_RAMFC_DMA_GET 0x04 +#define NV10_RAMFC_REF_CNT 0x08 +#define NV10_RAMFC_DMA_INSTANCE 0x0C +#define NV10_RAMFC_DMA_STATE 0x10 +#define NV10_RAMFC_DMA_FETCH 0x14 +#define NV10_RAMFC_ENGINE 0x18 +#define NV10_RAMFC_PULL1_ENGINE 0x1C +#define NV10_RAMFC_ACQUIRE_VALUE 0x20 +#define NV10_RAMFC_ACQUIRE_TIMESTAMP 0x24 +#define NV10_RAMFC_ACQUIRE_TIMEOUT 0x28 +#define NV10_RAMFC_SEMAPHORE 0x2C +#define NV10_RAMFC_DMA_SUBROUTINE 0x30 + +#define NV40_RAMFC_DMA_PUT 0x00 +#define NV40_RAMFC_DMA_GET 0x04 +#define NV40_RAMFC_REF_CNT 0x08 +#define NV40_RAMFC_DMA_INSTANCE 0x0C +#define NV40_RAMFC_DMA_DCOUNT /* ? */ 0x10 +#define NV40_RAMFC_DMA_STATE 0x14 +#define NV40_RAMFC_DMA_FETCH 0x18 +#define NV40_RAMFC_ENGINE 0x1C +#define NV40_RAMFC_PULL1_ENGINE 0x20 +#define NV40_RAMFC_ACQUIRE_VALUE 0x24 +#define NV40_RAMFC_ACQUIRE_TIMESTAMP 0x28 +#define NV40_RAMFC_ACQUIRE_TIMEOUT 0x2C +#define NV40_RAMFC_SEMAPHORE 0x30 +#define NV40_RAMFC_DMA_SUBROUTINE 0x34 +#define NV40_RAMFC_GRCTX_INSTANCE /* guess */ 0x38 +#define NV40_RAMFC_DMA_TIMESLICE 0x3C +#define NV40_RAMFC_UNK_40 0x40 +#define NV40_RAMFC_UNK_44 0x44 +#define NV40_RAMFC_UNK_48 0x48 +#define NV40_RAMFC_2088 0x4C +#define NV40_RAMFC_3300 0x50 + Index: dev/pci/drm/nouveau_state.c =================================================================== RCS file: dev/pci/drm/nouveau_state.c diff -N dev/pci/drm/nouveau_state.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/pci/drm/nouveau_state.c 24 Apr 2007 21:55:58 -0000 @@ -0,0 +1,380 @@ +/* + * Copyright 2005 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 + +#include +#include +#include + +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +static int nouveau_init_card_mappings(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + int ret; + + /* resource 0 is mmio regs */ + /* resource 1 is linear FB */ + /* resource 2 is RAMIN (mmio regs + 0x1000000) */ + /* resource 6 is bios */ + + /* map the mmio regs */ + ret = drm_addmap(dev, drm_get_resource_start(dev, 0), + drm_get_resource_len(dev, 0), + _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio); + if (ret) { + DRM_ERROR("Unable to initialize the mmio mapping (%d). " + "Please report your setup to " DRIVER_EMAIL "\n", + ret); + return 1; + } + DRM_DEBUG("regs mapped ok at 0x%lx\n", dev_priv->mmio->offset); + + /* map larger RAMIN aperture on NV40 cards */ + if (dev_priv->card_type >= NV_40) { + 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); + if (ret) { + DRM_ERROR("Failed to init RAMIN mapping, " + "limited instance memory available\n"); + dev_priv->ramin = NULL; + } + } else + dev_priv->ramin = NULL; + + return 0; +} + +static void nouveau_stub_takedown(drm_device_t *dev) {} +static int nouveau_init_engine_ptrs(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_engine_func *engine = &dev_priv->Engine; + + switch (dev_priv->chipset & 0xf0) { + case 0x00: + engine->Mc.Init = nv04_mc_init; + engine->Mc.Takedown = nv04_mc_takedown; + engine->Timer.Init = nv04_timer_init; + engine->Timer.Takedown = nv04_timer_takedown; + engine->Fb.Init = nv04_fb_init; + engine->Fb.Takedown = nv04_fb_takedown; + engine->Graph.Init = nv04_graph_init; + engine->Graph.Takedown = nv04_graph_takedown; + engine->Fifo.Init = nouveau_fifo_init; + engine->Fifo.Takedown = nouveau_stub_takedown; + break; + case 0x10: + engine->Mc.Init = nv04_mc_init; + engine->Mc.Takedown = nv04_mc_takedown; + engine->Timer.Init = nv04_timer_init; + engine->Timer.Takedown = nv04_timer_takedown; + engine->Fb.Init = nv10_fb_init; + engine->Fb.Takedown = nv10_fb_takedown; + engine->Graph.Init = nv10_graph_init; + engine->Graph.Takedown = nv10_graph_takedown; + engine->Fifo.Init = nouveau_fifo_init; + engine->Fifo.Takedown = nouveau_stub_takedown; + break; + case 0x20: + engine->Mc.Init = nv04_mc_init; + engine->Mc.Takedown = nv04_mc_takedown; + engine->Timer.Init = nv04_timer_init; + engine->Timer.Takedown = nv04_timer_takedown; + engine->Fb.Init = nv10_fb_init; + engine->Fb.Takedown = nv10_fb_takedown; + engine->Graph.Init = nv20_graph_init; + engine->Graph.Takedown = nv20_graph_takedown; + engine->Fifo.Init = nouveau_fifo_init; + engine->Fifo.Takedown = nouveau_stub_takedown; + break; + case 0x30: + engine->Mc.Init = nv04_mc_init; + engine->Mc.Takedown = nv04_mc_takedown; + engine->Timer.Init = nv04_timer_init; + engine->Timer.Takedown = nv04_timer_takedown; + engine->Fb.Init = nv10_fb_init; + engine->Fb.Takedown = nv10_fb_takedown; + engine->Graph.Init = nv30_graph_init; + engine->Graph.Takedown = nv30_graph_takedown; + engine->Fifo.Init = nouveau_fifo_init; + engine->Fifo.Takedown = nouveau_stub_takedown; + break; + case 0x40: + engine->Mc.Init = nv40_mc_init; + engine->Mc.Takedown = nv40_mc_takedown; + engine->Timer.Init = nv04_timer_init; + engine->Timer.Takedown = nv04_timer_takedown; + engine->Fb.Init = nv40_fb_init; + engine->Fb.Takedown = nv40_fb_takedown; + engine->Graph.Init = nv40_graph_init; + engine->Graph.Takedown = nv40_graph_takedown; + engine->Fifo.Init = nouveau_fifo_init; + engine->Fifo.Takedown = nouveau_stub_takedown; + break; + case 0x50: + default: + DRM_ERROR("NV%02x unsupported\n", dev_priv->chipset); + return 1; + } + + return 0; +} + +static int nouveau_card_init(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_engine_func *engine; + int ret; + + /* Map any PCI resources we need on the card */ + ret = nouveau_init_card_mappings(dev); + if (ret) return ret; + + /* Determine exact chipset we're running on */ + if (dev_priv->card_type < NV_10) + dev_priv->chipset = dev_priv->card_type; + else + dev_priv->chipset = + (NV_READ(NV03_PMC_BOOT_0) & 0x0ff00000) >> 20; + + /* Initialise internal driver API hooks */ + ret = nouveau_init_engine_ptrs(dev); + if (ret) return ret; + engine = &dev_priv->Engine; + + /* Initialise instance memory, must happen before mem_init so we + * know exactly how much VRAM we're able to use for "normal" + * purposes. + */ + ret = nouveau_instmem_init(dev); + if (ret) return ret; + + /* Setup the memory manager */ + ret = nouveau_mem_init(dev); + if (ret) return ret; + + /* Parse BIOS tables / Run init tables? */ + + /* PMC */ + ret = engine->Mc.Init(dev); + if (ret) return ret; + + /* PTIMER */ + ret = engine->Timer.Init(dev); + if (ret) return ret; + + /* PFB */ + ret = engine->Fb.Init(dev); + if (ret) return ret; + + /* PGRAPH */ + ret = engine->Graph.Init(dev); + if (ret) return ret; + + /* PFIFO */ + ret = engine->Fifo.Init(dev); + if (ret) return ret; + + /* what about PVIDEO/PCRTC/PRAMDAC etc? */ + + return 0; +} + +/* here a client dies, release the stuff that was allocated for its filp */ +void nouveau_preclose(drm_device_t * dev, DRMFILE filp) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + + nouveau_mem_release(filp,dev_priv->fb_heap); + nouveau_mem_release(filp,dev_priv->agp_heap); + nouveau_fifo_cleanup(dev, filp); +} + +/* first module load, setup the mmio/fb mapping */ +int nouveau_firstopen(struct drm_device *dev) +{ + int ret; + + ret = nouveau_card_init(dev); + if (ret) { + DRM_ERROR("nouveau_card_init() failed! (%d)\n", ret); + return ret; + } + + return 0; +} + +int nouveau_load(struct drm_device *dev, unsigned long flags) +{ + drm_nouveau_private_t *dev_priv; + + if (flags==NV_UNKNOWN) + return DRM_ERR(EINVAL); + + dev_priv = drm_alloc(sizeof(drm_nouveau_private_t), DRM_MEM_DRIVER); + if (!dev_priv) + return DRM_ERR(ENOMEM); + + memset(dev_priv, 0, sizeof(drm_nouveau_private_t)); + dev_priv->card_type=flags&NOUVEAU_FAMILY; + dev_priv->flags=flags&NOUVEAU_FLAGS; + + dev->dev_private = (void *)dev_priv; + +#if 0 + { + int ret; + ret = nouveau_card_init(dev); + if (ret) { + DRM_ERROR("nouveau_card_init() failed! (%d)\n", ret); + return ret; + } + } +#endif + + return 0; +} + +void nouveau_lastclose(struct drm_device *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + if(dev_priv->fb_mtrr>0) + { + drm_mtrr_del(dev_priv->fb_mtrr, drm_get_resource_start(dev, 1),nouveau_mem_fb_amount(dev), DRM_MTRR_WC); + dev_priv->fb_mtrr=0; + } +} + +int nouveau_unload(struct drm_device *dev) +{ + drm_free(dev->dev_private, sizeof(drm_nouveau_private_t), DRM_MEM_DRIVER); + dev->dev_private = NULL; + return 0; +} + +int nouveau_ioctl_getparam(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_nouveau_private_t *dev_priv = dev->dev_private; + drm_nouveau_getparam_t getparam; + + DRM_COPY_FROM_USER_IOCTL(getparam, (drm_nouveau_getparam_t __user *)data, + sizeof(getparam)); + + switch (getparam.param) { + case NOUVEAU_GETPARAM_PCI_VENDOR: + getparam.value=dev->pci_vendor; + break; + case NOUVEAU_GETPARAM_PCI_DEVICE: + getparam.value=dev->pci_device; + break; + case NOUVEAU_GETPARAM_BUS_TYPE: + if (drm_device_is_agp(dev)) + getparam.value=NV_AGP; + else if (drm_device_is_pcie(dev)) + getparam.value=NV_PCIE; + else + getparam.value=NV_PCI; + break; + case NOUVEAU_GETPARAM_FB_PHYSICAL: + getparam.value=dev_priv->fb_phys; + break; + case NOUVEAU_GETPARAM_AGP_PHYSICAL: + getparam.value=dev_priv->agp_phys; + break; + case NOUVEAU_GETPARAM_FB_SIZE: + getparam.value=dev_priv->fb_available_size; + break; + case NOUVEAU_GETPARAM_AGP_SIZE: + getparam.value=dev_priv->agp_available_size; + break; + default: + DRM_ERROR("unknown parameter %lld\n", getparam.param); + return DRM_ERR(EINVAL); + } + + DRM_COPY_TO_USER_IOCTL((drm_nouveau_getparam_t __user *)data, getparam, + sizeof(getparam)); + return 0; +} + +int nouveau_ioctl_setparam(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_nouveau_private_t *dev_priv = dev->dev_private; + drm_nouveau_setparam_t setparam; + + DRM_COPY_FROM_USER_IOCTL(setparam, (drm_nouveau_setparam_t __user *)data, + sizeof(setparam)); + + switch (setparam.param) { + case NOUVEAU_SETPARAM_CMDBUF_LOCATION: + switch (setparam.value) { + case NOUVEAU_MEM_AGP: + case NOUVEAU_MEM_FB: + break; + default: + DRM_ERROR("invalid CMDBUF_LOCATION value=%lld\n", + setparam.value); + return DRM_ERR(EINVAL); + } + dev_priv->config.cmdbuf.location = setparam.value; + break; + case NOUVEAU_SETPARAM_CMDBUF_SIZE: + dev_priv->config.cmdbuf.size = setparam.value; + break; + default: + DRM_ERROR("unknown parameter %lld\n", setparam.param); + return DRM_ERR(EINVAL); + } + + return 0; +} + +/* waits for idle */ +void nouveau_wait_for_idle(struct drm_device *dev) +{ + drm_nouveau_private_t *dev_priv=dev->dev_private; + switch(dev_priv->card_type) + { + case NV_03: + while(NV_READ(NV03_PGRAPH_STATUS)); + break; + default: + while(NV_READ(NV04_PGRAPH_STATUS)); + break; + } +} + + Index: dev/pci/drm/nv04_fb.c =================================================================== RCS file: dev/pci/drm/nv04_fb.c diff -N dev/pci/drm/nv04_fb.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/pci/drm/nv04_fb.c 24 Apr 2007 21:55:58 -0000 @@ -0,0 +1,27 @@ +#include + +#include +#include + +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv04_fb_init(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + + /* This is what the DDX did for NV_ARCH_04, but a mmio-trace shows + * nvidia reading PFB_CFG_0, then writing back its original value. + * (which was 0x701114 in this case) + */ + NV_WRITE(NV04_PFB_CFG0, 0x1114); + + return 0; +} + +void +nv04_fb_takedown(drm_device_t *dev) +{ +} + Index: dev/pci/drm/nv04_graph.c =================================================================== RCS file: dev/pci/drm/nv04_graph.c diff -N dev/pci/drm/nv04_graph.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/pci/drm/nv04_graph.c 24 Apr 2007 21:55:58 -0000 @@ -0,0 +1,400 @@ +/* + * Copyright 2007 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 + +#include +#include + +#include "nouveau_drm.h" +#include "nouveau_drv.h" + +struct reg_interval +{ + uint32_t reg; + int number; +} nv04_graph_ctx_regs [] = { + {NV04_PGRAPH_CTX_SWITCH1,1}, + {NV04_PGRAPH_CTX_SWITCH2,1}, + {NV04_PGRAPH_CTX_SWITCH3,1}, + {NV04_PGRAPH_CTX_SWITCH4,1}, + {NV04_PGRAPH_CTX_CACHE1,1}, + {NV04_PGRAPH_CTX_CACHE2,1}, + {NV04_PGRAPH_CTX_CACHE3,1}, + {NV04_PGRAPH_CTX_CACHE4,1}, + {0x00400184,1}, + {0x004001a4,1}, + {0x004001c4,1}, + {0x004001e4,1}, + {0x00400188,1}, + {0x004001a8,1}, + {0x004001c8,1}, + {0x004001e8,1}, + {0x0040018c,1}, + {0x004001ac,1}, + {0x004001cc,1}, + {0x004001ec,1}, + {0x00400190,1}, + {0x004001b0,1}, + {0x004001d0,1}, + {0x004001f0,1}, + {0x00400194,1}, + {0x004001b4,1}, + {0x004001d4,1}, + {0x004001f4,1}, + {0x00400198,1}, + {0x004001b8,1}, + {0x004001d8,1}, + {0x004001f8,1}, + {0x0040019c,1}, + {0x004001bc,1}, + {0x004001dc,1}, + {0x004001fc,1}, + {0x00400174,1}, + {NV04_PGRAPH_DMA_START_0,1}, + {NV04_PGRAPH_DMA_START_1,1}, + {NV04_PGRAPH_DMA_LENGTH,1}, + {NV04_PGRAPH_DMA_MISC,1}, + {NV04_PGRAPH_DMA_PITCH,1}, + {NV04_PGRAPH_BOFFSET0,1}, + {NV04_PGRAPH_BBASE0,1}, + {NV04_PGRAPH_BLIMIT0,1}, + {NV04_PGRAPH_BOFFSET1,1}, + {NV04_PGRAPH_BBASE1,1}, + {NV04_PGRAPH_BLIMIT1,1}, + {NV04_PGRAPH_BOFFSET2,1}, + {NV04_PGRAPH_BBASE2,1}, + {NV04_PGRAPH_BLIMIT2,1}, + {NV04_PGRAPH_BOFFSET3,1}, + {NV04_PGRAPH_BBASE3,1}, + {NV04_PGRAPH_BLIMIT3,1}, + {NV04_PGRAPH_BOFFSET4,1}, + {NV04_PGRAPH_BBASE4,1}, + {NV04_PGRAPH_BLIMIT4,1}, + {NV04_PGRAPH_BOFFSET5,1}, + {NV04_PGRAPH_BBASE5,1}, + {NV04_PGRAPH_BLIMIT5,1}, + {NV04_PGRAPH_BPITCH0,1}, + {NV04_PGRAPH_BPITCH1,1}, + {NV04_PGRAPH_BPITCH2,1}, + {NV04_PGRAPH_BPITCH3,1}, + {NV04_PGRAPH_BPITCH4,1}, + {NV04_PGRAPH_SURFACE,1}, + {NV04_PGRAPH_STATE,1}, + {NV04_PGRAPH_BSWIZZLE2,1}, + {NV04_PGRAPH_BSWIZZLE5,1}, + {NV04_PGRAPH_BPIXEL,1}, + {NV04_PGRAPH_NOTIFY,1}, + {NV04_PGRAPH_PATT_COLOR0,1}, + {NV04_PGRAPH_PATT_COLOR1,1}, + {NV04_PGRAPH_PATT_COLORRAM,64}, + {NV04_PGRAPH_PATTERN,1}, + {0x0040080c,1}, + {NV04_PGRAPH_PATTERN_SHAPE,1}, + {0x00400600,1}, + {NV04_PGRAPH_ROP3,1}, + {NV04_PGRAPH_CHROMA,1}, + {NV04_PGRAPH_BETA_AND,1}, + {NV04_PGRAPH_BETA_PREMULT,1}, + {NV04_PGRAPH_CONTROL0,1}, + {NV04_PGRAPH_CONTROL1,1}, + {NV04_PGRAPH_CONTROL2,1}, + {NV04_PGRAPH_BLEND,1}, + {NV04_PGRAPH_STORED_FMT,1}, + {NV04_PGRAPH_SOURCE_COLOR,1}, + {0x00400560,1}, + {0x00400568,1}, + {0x00400564,1}, + {0x0040056c,1}, + {0x00400400,1}, + {0x00400480,1}, + {0x00400404,1}, + {0x00400484,1}, + {0x00400408,1}, + {0x00400488,1}, + {0x0040040c,1}, + {0x0040048c,1}, + {0x00400410,1}, + {0x00400490,1}, + {0x00400414,1}, + {0x00400494,1}, + {0x00400418,1}, + {0x00400498,1}, + {0x0040041c,1}, + {0x0040049c,1}, + {0x00400420,1}, + {0x004004a0,1}, + {0x00400424,1}, + {0x004004a4,1}, + {0x00400428,1}, + {0x004004a8,1}, + {0x0040042c,1}, + {0x004004ac,1}, + {0x00400430,1}, + {0x004004b0,1}, + {0x00400434,1}, + {0x004004b4,1}, + {0x00400438,1}, + {0x004004b8,1}, + {0x0040043c,1}, + {0x004004bc,1}, + {0x00400440,1}, + {0x004004c0,1}, + {0x00400444,1}, + {0x004004c4,1}, + {0x00400448,1}, + {0x004004c8,1}, + {0x0040044c,1}, + {0x004004cc,1}, + {0x00400450,1}, + {0x004004d0,1}, + {0x00400454,1}, + {0x004004d4,1}, + {0x00400458,1}, + {0x004004d8,1}, + {0x0040045c,1}, + {0x004004dc,1}, + {0x00400460,1}, + {0x004004e0,1}, + {0x00400464,1}, + {0x004004e4,1}, + {0x00400468,1}, + {0x004004e8,1}, + {0x0040046c,1}, + {0x004004ec,1}, + {0x00400470,1}, + {0x004004f0,1}, + {0x00400474,1}, + {0x004004f4,1}, + {0x00400478,1}, + {0x004004f8,1}, + {0x0040047c,1}, + {0x004004fc,1}, + {0x0040053c,1}, + {0x00400544,1}, + {0x00400540,1}, + {0x00400548,1}, + {0x00400560,1}, + {0x00400568,1}, + {0x00400564,1}, + {0x0040056c,1}, + {0x00400534,1}, + {0x00400538,1}, + {0x00400514,1}, + {0x00400518,1}, + {0x0040051c,1}, + {0x00400520,1}, + {0x00400524,1}, + {0x00400528,1}, + {0x0040052c,1}, + {0x00400530,1}, + {0x00400d00,1}, + {0x00400d40,1}, + {0x00400d80,1}, + {0x00400d04,1}, + {0x00400d44,1}, + {0x00400d84,1}, + {0x00400d08,1}, + {0x00400d48,1}, + {0x00400d88,1}, + {0x00400d0c,1}, + {0x00400d4c,1}, + {0x00400d8c,1}, + {0x00400d10,1}, + {0x00400d50,1}, + {0x00400d90,1}, + {0x00400d14,1}, + {0x00400d54,1}, + {0x00400d94,1}, + {0x00400d18,1}, + {0x00400d58,1}, + {0x00400d98,1}, + {0x00400d1c,1}, + {0x00400d5c,1}, + {0x00400d9c,1}, + {0x00400d20,1}, + {0x00400d60,1}, + {0x00400da0,1}, + {0x00400d24,1}, + {0x00400d64,1}, + {0x00400da4,1}, + {0x00400d28,1}, + {0x00400d68,1}, + {0x00400da8,1}, + {0x00400d2c,1}, + {0x00400d6c,1}, + {0x00400dac,1}, + {0x00400d30,1}, + {0x00400d70,1}, + {0x00400db0,1}, + {0x00400d34,1}, + {0x00400d74,1}, + {0x00400db4,1}, + {0x00400d38,1}, + {0x00400d78,1}, + {0x00400db8,1}, + {0x00400d3c,1}, + {0x00400d7c,1}, + {0x00400dbc,1}, + {0x00400590,1}, + {0x00400594,1}, + {0x00400598,1}, + {0x0040059c,1}, + {0x004005a8,1}, + {0x004005ac,1}, + {0x004005b0,1}, + {0x004005b4,1}, + {0x004005c0,1}, + {0x004005c4,1}, + {0x004005c8,1}, + {0x004005cc,1}, + {0x004005d0,1}, + {0x004005d4,1}, + {0x004005d8,1}, + {0x004005dc,1}, + {0x004005e0,1}, + {NV04_PGRAPH_PASSTHRU_0,1}, + {NV04_PGRAPH_PASSTHRU_1,1}, + {NV04_PGRAPH_PASSTHRU_2,1}, + {NV04_PGRAPH_DVD_COLORFMT,1}, + {NV04_PGRAPH_SCALED_FORMAT,1}, + {NV04_PGRAPH_MISC24_0,1}, + {NV04_PGRAPH_MISC24_1,1}, + {NV04_PGRAPH_MISC24_2,1}, + {0x00400500,1}, + {0x00400504,1}, + {NV04_PGRAPH_VALID1,1}, + {NV04_PGRAPH_VALID2,1} + + +}; + +void nouveau_nv04_context_switch(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + int channel, channel_old, i, j, index; + + channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); + channel_old = (NV_READ(NV04_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); + + DRM_DEBUG("NV: PGRAPH context switch interrupt channel %x -> %x\n",channel_old, channel); + + NV_WRITE(NV03_PFIFO_CACHES, 0x0); + NV_WRITE(NV04_PFIFO_CACHE0_PULL0, 0x0); + NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x0); + NV_WRITE(NV04_PGRAPH_FIFO,0x0); + + nouveau_wait_for_idle(dev); + + // save PGRAPH context + index=0; + for (i = 0; ififos[channel_old].pgraph_ctx[index] = NV_READ(nv04_graph_ctx_regs[i].reg+j*4); + index++; + } + + NV_WRITE(NV04_PGRAPH_CTX_CONTROL, 0x10000000); + NV_WRITE(NV04_PGRAPH_CTX_USER, (NV_READ(NV04_PGRAPH_CTX_USER) & 0xffffff) | (0x0f << 24)); + + // restore PGRAPH context + index=0; + for (i = 0; ififos[channel].pgraph_ctx[index]); + index++; + } + + NV_WRITE(NV04_PGRAPH_CTX_CONTROL, 0x10010100); + NV_WRITE(NV04_PGRAPH_CTX_USER, channel << 24); + NV_WRITE(NV04_PGRAPH_FFINTFC_ST2, NV_READ(NV04_PGRAPH_FFINTFC_ST2)&0x000FFFFF); + + NV_WRITE(NV04_PGRAPH_FIFO,0x0); + NV_WRITE(NV04_PFIFO_CACHE0_PULL0, 0x0); + NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x1); + NV_WRITE(NV03_PFIFO_CACHES, 0x1); + NV_WRITE(NV04_PGRAPH_FIFO,0x1); +} + +int nv04_graph_context_create(drm_device_t *dev, int channel) { + drm_nouveau_private_t *dev_priv = dev->dev_private; + DRM_DEBUG("nv04_graph_context_create %d\n", channel); + + memset(dev_priv->fifos[channel].pgraph_ctx, 0, sizeof(dev_priv->fifos[channel].pgraph_ctx)); + + //dev_priv->fifos[channel].pgraph_ctx_user = channel << 24; + dev_priv->fifos[channel].pgraph_ctx[0] = 0x0001ffff; + /* is it really needed ??? */ + //dev_priv->fifos[channel].pgraph_ctx[1] = NV_READ(NV_PGRAPH_DEBUG_4); + //dev_priv->fifos[channel].pgraph_ctx[2] = NV_READ(0x004006b0); + + return 0; +} + + +int nv04_graph_init(drm_device_t *dev) { + drm_nouveau_private_t *dev_priv = dev->dev_private; + int i,sum=0; + + NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) & + ~NV_PMC_ENABLE_PGRAPH); + NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) | + NV_PMC_ENABLE_PGRAPH); + + // check the context is big enough + for ( i = 0 ; isizeof(dev_priv->fifos[0].pgraph_ctx) ) + DRM_ERROR("pgraph_ctx too small\n"); + + NV_WRITE(NV03_PGRAPH_INTR_EN, 0x00000000); + NV_WRITE(NV03_PGRAPH_INTR , 0xFFFFFFFF); + + NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x000001FF); + NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x1230C000); + NV_WRITE(NV04_PGRAPH_DEBUG_1, 0x72111101); + NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x11D5F071); + NV_WRITE(NV04_PGRAPH_DEBUG_3, 0x0004FF31); + NV_WRITE(NV04_PGRAPH_DEBUG_3, 0x4004FF31 | + (0x00D00000) | + (1<<29) | + (1<<31)); + + NV_WRITE(NV04_PGRAPH_STATE , 0xFFFFFFFF); + NV_WRITE(NV04_PGRAPH_CTX_CONTROL , 0x10010100); + NV_WRITE(NV04_PGRAPH_FIFO , 0x00000001); + + /* These don't belong here, they're part of a per-channel context */ + NV_WRITE(NV04_PGRAPH_PATTERN_SHAPE, 0x00000000); + NV_WRITE(NV04_PGRAPH_BETA_AND , 0xFFFFFFFF); + + return 0; +} + +void nv04_graph_takedown(drm_device_t *dev) +{ +} + Index: dev/pci/drm/nv04_mc.c =================================================================== RCS file: dev/pci/drm/nv04_mc.c diff -N dev/pci/drm/nv04_mc.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/pci/drm/nv04_mc.c 24 Apr 2007 21:55:58 -0000 @@ -0,0 +1,28 @@ +#include + +#include +#include + +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv04_mc_init(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + + /* Power up everything, resetting each individual unit will + * be done later if needed. + */ + NV_WRITE(NV03_PMC_ENABLE, 0xFFFFFFFF); + + NV_WRITE(NV03_PMC_INTR_EN_0, 0); + + return 0; +} + +void +nv04_mc_takedown(drm_device_t *dev) +{ +} + Index: dev/pci/drm/nv04_timer.c =================================================================== RCS file: dev/pci/drm/nv04_timer.c diff -N dev/pci/drm/nv04_timer.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/pci/drm/nv04_timer.c 24 Apr 2007 21:55:58 -0000 @@ -0,0 +1,27 @@ +#include + +#include +#include + +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv04_timer_init(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + + NV_WRITE(NV04_PTIMER_INTR_EN_0, 0x00000000); + NV_WRITE(NV04_PTIMER_INTR_0, 0xFFFFFFFF); + + NV_WRITE(NV04_PTIMER_NUMERATOR, 0x00000008); + NV_WRITE(NV04_PTIMER_DENOMINATOR, 0x00000003); + + return 0; +} + +void +nv04_timer_takedown(drm_device_t *dev) +{ +} + Index: dev/pci/drm/nv10_fb.c =================================================================== RCS file: dev/pci/drm/nv10_fb.c diff -N dev/pci/drm/nv10_fb.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/pci/drm/nv10_fb.c 24 Apr 2007 21:55:58 -0000 @@ -0,0 +1,29 @@ +#include + +#include +#include + +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv10_fb_init(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + uint32_t fb_bar_size; + int i; + + fb_bar_size = drm_get_resource_len(dev, 0) - 1; + for (i=0; i + * 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 + +#include +#include + +#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(NV10_PGRAPH_XFMODE0, 0x10000000); + NV_WRITE(NV10_PGRAPH_XFMODE1, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); + for (i = 0; i < 4; i++) + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); + for (i = 0; i < 4; i++) + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); + + for (i = 0; i < 3; i++) + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); + + NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80); + for (i = 0; i < 3; i++) + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000008); + + NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00000200); + for (i = 0; i < 48; i++) + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + + nouveau_wait_for_idle(dev); + + NV_WRITE(NV10_PGRAPH_XFMODE0, 0x00000000); + NV_WRITE(NV10_PGRAPH_XFMODE1, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00006400); + for (i = 0; i < 211; i++) + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x40000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x40000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x40000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x40000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); + + NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00006800); + for (i = 0; i < 162; i++) + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000); + for (i = 0; i < 25; i++) + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00006c00); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0xbf800000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00007000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca); + for (i = 0; i < 35; i++) + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + + + NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00007400); + for (i = 0; i < 48; i++) + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00007800); + for (i = 0; i < 48; i++) + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00004400); + for (i = 0; i < 32; i++) + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00000000); + for (i = 0; i < 16; i++) + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + + NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); + for (i = 0; i < 4; i++) + NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000); + + nouveau_wait_for_idle(dev); +} + +/* TODO replace address with name + use loops */ +static int nv10_graph_ctx_regs [] = { +NV03_PGRAPH_XY_LOGIC_MISC0, + +NV10_PGRAPH_CTX_SWITCH1, +NV10_PGRAPH_CTX_SWITCH2, +NV10_PGRAPH_CTX_SWITCH3, +NV10_PGRAPH_CTX_SWITCH4, +NV10_PGRAPH_CTX_SWITCH5, +NV10_PGRAPH_CTX_CACHE1, /* 8 values from 0x400160 to 0x40017c */ +NV10_PGRAPH_CTX_CACHE2, /* 8 values from 0x400180 to 0x40019c */ +NV10_PGRAPH_CTX_CACHE3, /* 8 values from 0x4001a0 to 0x4001bc */ +NV10_PGRAPH_CTX_CACHE4, /* 8 values from 0x4001c0 to 0x4001dc */ +NV10_PGRAPH_CTX_CACHE5, /* 8 values from 0x4001e0 to 0x4001fc */ +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, +NV10_PGRAPH_CTX_USER, +NV04_PGRAPH_DMA_START_0, +NV04_PGRAPH_DMA_START_1, +NV04_PGRAPH_DMA_LENGTH, +NV04_PGRAPH_DMA_MISC, +NV10_PGRAPH_DMA_PITCH, +NV04_PGRAPH_BOFFSET0, +NV04_PGRAPH_BBASE0, +NV04_PGRAPH_BLIMIT0, +NV04_PGRAPH_BOFFSET1, +NV04_PGRAPH_BBASE1, +NV04_PGRAPH_BLIMIT1, +NV04_PGRAPH_BOFFSET2, +NV04_PGRAPH_BBASE2, +NV04_PGRAPH_BLIMIT2, +NV04_PGRAPH_BOFFSET3, +NV04_PGRAPH_BBASE3, +NV04_PGRAPH_BLIMIT3, +NV04_PGRAPH_BOFFSET4, +NV04_PGRAPH_BBASE4, +NV04_PGRAPH_BLIMIT4, +NV04_PGRAPH_BOFFSET5, +NV04_PGRAPH_BBASE5, +NV04_PGRAPH_BLIMIT5, +NV04_PGRAPH_BPITCH0, +NV04_PGRAPH_BPITCH1, +NV04_PGRAPH_BPITCH2, +NV04_PGRAPH_BPITCH3, +NV04_PGRAPH_BPITCH4, +NV10_PGRAPH_SURFACE, +NV10_PGRAPH_STATE, +NV04_PGRAPH_BSWIZZLE2, +NV04_PGRAPH_BSWIZZLE5, +NV04_PGRAPH_BPIXEL, +NV10_PGRAPH_NOTIFY, +NV04_PGRAPH_PATT_COLOR0, +NV04_PGRAPH_PATT_COLOR1, +NV04_PGRAPH_PATT_COLORRAM, /* 64 values from 0x400900 to 0x4009fc */ +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, +NV04_PGRAPH_PATTERN, /* 2 values from 0x400808 to 0x40080c */ +0x0040080c, +NV04_PGRAPH_PATTERN_SHAPE, +NV03_PGRAPH_MONO_COLOR0, +NV04_PGRAPH_ROP3, +NV04_PGRAPH_CHROMA, +NV04_PGRAPH_BETA_AND, +NV04_PGRAPH_BETA_PREMULT, +0x00400e70, +0x00400e74, +0x00400e78, +0x00400e7c, +0x00400e80, +0x00400e84, +0x00400e88, +0x00400e8c, +0x00400ea0, +0x00400ea4, +0x00400ea8, +0x00400e90, +0x00400e94, +0x00400e98, +0x00400e9c, +NV10_PGRAPH_WINDOWCLIP_HORIZONTAL, /* 8 values from 0x400f00 to 0x400f1c */ +NV10_PGRAPH_WINDOWCLIP_VERTICAL, /* 8 values from 0x400f20 to 0x400f3c */ +0x00400f04, +0x00400f24, +0x00400f08, +0x00400f28, +0x00400f0c, +0x00400f2c, +0x00400f10, +0x00400f30, +0x00400f14, +0x00400f34, +0x00400f18, +0x00400f38, +0x00400f1c, +0x00400f3c, +NV10_PGRAPH_XFMODE0, +NV10_PGRAPH_XFMODE1, +NV10_PGRAPH_GLOBALSTATE0, +NV10_PGRAPH_GLOBALSTATE1, +NV04_PGRAPH_STORED_FMT, +NV04_PGRAPH_SOURCE_COLOR, +NV03_PGRAPH_ABS_X_RAM, /* 32 values from 0x400400 to 0x40047c */ +NV03_PGRAPH_ABS_Y_RAM, /* 32 values from 0x400480 to 0x4004fc */ +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, +NV03_PGRAPH_ABS_UCLIP_XMIN, +NV03_PGRAPH_ABS_UCLIP_XMAX, +NV03_PGRAPH_ABS_UCLIP_YMIN, +NV03_PGRAPH_ABS_UCLIP_YMAX, +0x00400550, +0x00400558, +0x00400554, +0x0040055c, +NV03_PGRAPH_ABS_UCLIPA_XMIN, +NV03_PGRAPH_ABS_UCLIPA_XMAX, +NV03_PGRAPH_ABS_UCLIPA_YMIN, +NV03_PGRAPH_ABS_UCLIPA_YMAX, +NV03_PGRAPH_ABS_ICLIP_XMAX, +NV03_PGRAPH_ABS_ICLIP_YMAX, +NV03_PGRAPH_XY_LOGIC_MISC1, +NV03_PGRAPH_XY_LOGIC_MISC2, +NV03_PGRAPH_XY_LOGIC_MISC3, +NV03_PGRAPH_CLIPX_0, +NV03_PGRAPH_CLIPX_1, +NV03_PGRAPH_CLIPY_0, +NV03_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, +NV04_PGRAPH_PASSTHRU_0, +NV04_PGRAPH_PASSTHRU_1, +NV04_PGRAPH_PASSTHRU_2, +NV10_PGRAPH_DIMX_TEXTURE, +NV10_PGRAPH_WDIMX_TEXTURE, +NV10_PGRAPH_DVD_COLORFMT, +NV10_PGRAPH_SCALED_FORMAT, +NV04_PGRAPH_MISC24_0, +NV04_PGRAPH_MISC24_1, +NV04_PGRAPH_MISC24_2, +NV03_PGRAPH_X_MISC, +NV03_PGRAPH_Y_MISC, +NV04_PGRAPH_VALID1, +NV04_PGRAPH_VALID2, +}; + +static int nv17_graph_ctx_regs [] = { +NV10_PGRAPH_DEBUG_4, +0x004006b0, +0x00400eac, +0x00400eb0, +0x00400eb4, +0x00400eb8, +0x00400ebc, +0x00400ec0, +0x00400ec4, +0x00400ec8, +0x00400ecc, +0x00400ed0, +0x00400ed4, +0x00400ed8, +0x00400edc, +0x00400ee0, +0x00400a00, +0x00400a04, +}; + +static int nv10_graph_ctx_regs_find_offset(drm_device_t *dev, int reg) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + int i, j; + for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++) { + if (nv10_graph_ctx_regs[i] == reg) + return i; + } + if (dev_priv->chipset>=0x17) { + for (j = 0; j < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++,j++) { + if (nv17_graph_ctx_regs[j] == reg) + return i; + } + } + return -1; +} + +static void restore_ctx_regs(drm_device_t *dev, int channel) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_fifo *fifo = &dev_priv->fifos[channel]; + int i, j; + for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++) + NV_WRITE(nv10_graph_ctx_regs[i], fifo->pgraph_ctx[i]); + if (dev_priv->chipset>=0x17) { + for (j = 0; j < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++,j++) + NV_WRITE(nv17_graph_ctx_regs[j], fifo->pgraph_ctx[i]); + } + nouveau_wait_for_idle(dev); +} + +void nouveau_nv10_context_switch(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + int channel, channel_old, i, j; + + channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); + channel_old = (NV_READ(NV10_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(NV04_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; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++) + dev_priv->fifos[channel_old].pgraph_ctx[i] = NV_READ(nv10_graph_ctx_regs[i]); + if (dev_priv->chipset>=0x17) { + for (j = 0; j < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++,j++) + dev_priv->fifos[channel_old].pgraph_ctx[i] = NV_READ(nv17_graph_ctx_regs[j]); + } + + nouveau_wait_for_idle(dev); + + NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10000000); + NV_WRITE(NV10_PGRAPH_CTX_USER, (NV_READ(NV10_PGRAPH_CTX_USER) & 0xffffff) | (0x1f << 24)); + + nouveau_wait_for_idle(dev); + // restore PGRAPH context +#if 1 + restore_ctx_regs(dev, channel); +#endif + + NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100); + NV_WRITE(NV10_PGRAPH_CTX_USER, channel << 24); + NV_WRITE(NV10_PGRAPH_FFINTFC_ST2, NV_READ(NV10_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(NV04_PGRAPH_FIFO,0x1); +} + +#define NV_WRITE_CTX(reg, val) do { \ + int offset = nv10_graph_ctx_regs_find_offset(dev, reg); \ + if (offset > 0) \ + fifo->pgraph_ctx[offset] = val; \ + } while (0) +int nv10_graph_context_create(drm_device_t *dev, int channel) { + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_fifo *fifo = &dev_priv->fifos[channel]; + uint32_t tmp, vramsz; + + DRM_DEBUG("nv10_graph_context_create %d\n", channel); + + memset(fifo->pgraph_ctx, 0, sizeof(fifo->pgraph_ctx)); + + /* per channel init from ddx */ + tmp = NV_READ(NV10_PGRAPH_SURFACE) & 0x0007ff00; + /*XXX the original ddx code, does this in 2 steps : + * tmp = NV_READ(NV10_PGRAPH_SURFACE) & 0x0007ff00; + * NV_WRITE(NV10_PGRAPH_SURFACE, tmp); + * tmp = NV_READ(NV10_PGRAPH_SURFACE) | 0x00020100; + * NV_WRITE(NV10_PGRAPH_SURFACE, tmp); + */ + tmp |= 0x00020100; + NV_WRITE_CTX(NV10_PGRAPH_SURFACE, tmp); + + vramsz = drm_get_resource_len(dev, 0) - 1; + NV_WRITE_CTX(NV04_PGRAPH_BOFFSET0, 0); + NV_WRITE_CTX(NV04_PGRAPH_BOFFSET1, 0); + NV_WRITE_CTX(NV04_PGRAPH_BLIMIT0 , vramsz); + NV_WRITE_CTX(NV04_PGRAPH_BLIMIT1 , vramsz); + + NV_WRITE_CTX(NV04_PGRAPH_PATTERN_SHAPE, 0x00000000); + NV_WRITE_CTX(NV04_PGRAPH_BETA_AND , 0xFFFFFFFF); + + + NV_WRITE_CTX(NV03_PGRAPH_XY_LOGIC_MISC0, 0x0001ffff); + /* is it really needed ??? */ + if (dev_priv->chipset>=0x17) { + NV_WRITE_CTX(NV10_PGRAPH_DEBUG_4, NV_READ(NV10_PGRAPH_DEBUG_4)); + NV_WRITE_CTX(0x004006b0, NV_READ(0x004006b0)); + } + + /* for the first channel init the regs */ + if (dev_priv->fifo_alloc_count == 0) + restore_ctx_regs(dev, channel); + + + //XXX should be saved/restored for each fifo + //we supposed here we have X fifo and only one 3D fifo. + nv10_praph_pipe(dev); + return 0; +} + + +int nv10_graph_init(drm_device_t *dev) { + drm_nouveau_private_t *dev_priv = dev->dev_private; + int i; + + NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) & + ~NV_PMC_ENABLE_PGRAPH); + NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) | + NV_PMC_ENABLE_PGRAPH); + + NV_WRITE(NV03_PGRAPH_INTR_EN, 0x00000000); + NV_WRITE(NV03_PGRAPH_INTR , 0xFFFFFFFF); + + NV_WRITE(NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x00000000); + NV_WRITE(NV04_PGRAPH_DEBUG_1, 0x00118700); + NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x24E00810); + NV_WRITE(NV04_PGRAPH_DEBUG_3, 0x55DE0030 | + (1<<29) | + (1<<31)); + + /* copy tile info from PFB */ + for (i=0; i + * 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 + +#include +#include + +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +#define NV20_GRCTX_SIZE (3529*4) + +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(NV10_PGRAPH_RDI_INDEX, 0x2c80000); + for (i = 0; i < 32; i++) + NV_WRITE(NV10_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(NV10_PGRAPH_CHANNEL_CTX_SIZE, instance); + NV_WRITE(NV10_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(NV10_PGRAPH_CTX_USER, channel << 24); + NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_SIZE, instance); + NV_WRITE(NV10_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(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); + channel_old = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); + + DRM_DEBUG("NV: PGRAPH context switch interrupt channel %x -> %x\n",channel_old, channel); + + NV_WRITE(NV04_PGRAPH_FIFO,0x0); + + nv20_graph_context_save_current(dev, channel_old); + + nouveau_wait_for_idle(dev); + + NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10000000); + + nv20_graph_context_restore(dev, channel); + + nouveau_wait_for_idle(dev); + + if ((NV_READ(NV10_PGRAPH_CTX_USER) >> 24) != channel) + DRM_ERROR("nouveau_nv20_context_switch : wrong channel restored %x %x!!!\n", channel, NV_READ(NV10_PGRAPH_CTX_USER) >> 24); + + NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100); + NV_WRITE(NV10_PGRAPH_FFINTFC_ST2, NV_READ(NV10_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF); + + NV_WRITE(NV04_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; + uint32_t tmp, vramsz; + + NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) & + ~NV_PMC_ENABLE_PGRAPH); + NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) | + NV_PMC_ENABLE_PGRAPH); + + /* 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(NV10_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); + + NV_WRITE(NV03_PGRAPH_INTR_EN, 0x00000000); + NV_WRITE(NV03_PGRAPH_INTR , 0xFFFFFFFF); + + NV_WRITE(NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x00000000); + NV_WRITE(NV04_PGRAPH_DEBUG_1, 0x00118700); + NV_WRITE(NV04_PGRAPH_DEBUG_3, 0xF20E0431); + NV_WRITE(NV10_PGRAPH_DEBUG_4, 0x00000000); + NV_WRITE(0x40009C , 0x00000040); + + if (dev_priv->chipset >= 0x25) { + NV_WRITE(0x400890, 0x00080000); + NV_WRITE(0x400610, 0x304B1FB6); + NV_WRITE(0x400B80, 0x18B82880); + NV_WRITE(0x400B84, 0x44000000); + NV_WRITE(0x400098, 0x40000080); + NV_WRITE(0x400B88, 0x000000ff); + } else { + NV_WRITE(0x400880, 0x00080000); + NV_WRITE(0x400094, 0x00000005); + NV_WRITE(0x400B80, 0x45CAA208); + NV_WRITE(0x400B84, 0x24000000); + NV_WRITE(0x400098, 0x00000040); + NV_WRITE(NV10_PGRAPH_RDI_INDEX, 0x00E00038); + NV_WRITE(NV10_PGRAPH_RDI_DATA , 0x00000030); + NV_WRITE(NV10_PGRAPH_RDI_INDEX, 0x00E10038); + NV_WRITE(NV10_PGRAPH_RDI_DATA , 0x00000030); + } + + /* copy tile info from PFB */ + for (i=0; i + +#include +#include + +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +/* + * This is obviously not the correct size. + */ +#define NV30_GRCTX_SIZE (23840) + +/*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; + + switch (dev_priv->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); + + 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; +} + +int nv30_graph_init(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + uint32_t vramsz, tmp; + int i; + + NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) & + ~NV_PMC_ENABLE_PGRAPH); + NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) | + NV_PMC_ENABLE_PGRAPH); + + /* 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(NV10_PGRAPH_CHANNEL_CTX_TABLE, nouveau_chip_instance_get(dev, dev_priv->ctx_table)); + + NV_WRITE(NV03_PGRAPH_INTR_EN, 0x00000000); + NV_WRITE(NV03_PGRAPH_INTR , 0xFFFFFFFF); + + NV_WRITE(NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x00000000); + NV_WRITE(NV04_PGRAPH_DEBUG_1, 0x401287c0); + NV_WRITE(0x400890, 0x00140000); + NV_WRITE(NV04_PGRAPH_DEBUG_3, 0xf0de0475); + NV_WRITE(NV10_PGRAPH_DEBUG_4, 0x10008000); + NV_WRITE(NV04_PGRAPH_LIMIT_VIOL_PIX, 0xf04b1f36); + NV_WRITE(0x400B80, 0x1003d888); + NV_WRITE(0x400B84, 0x0c000000); + NV_WRITE(0x400B88, 0x62ff0f7f); + NV_WRITE(0x400098, 0x000000c0); + NV_WRITE(0x40009C, 0x0005dc00); + NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x62ff0f7f); + NV_WRITE(0x4000a0, 0x00000000); + NV_WRITE(0x4000a4, 0x00000008); + + /* copy tile info from PFB */ + for (i=0; i + +#include +#include + +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv40_fb_init(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + uint32_t fb_bar_size, tmp; + int num_tiles; + int i; + + switch (dev_priv->chipset) { + case 0x40: + case 0x45: + tmp = NV_READ(NV10_PFB_CLOSE_PAGE2); + NV_WRITE(NV10_PFB_CLOSE_PAGE2, tmp & ~(1<<15)); + num_tiles = NV10_PFB_TILE__SIZE; + break; + case 0x46: /* G72 */ + case 0x47: /* G70 */ + case 0x49: /* G71 */ + case 0x4b: /* G73 */ + case 0x4c: /* C51 (G7X version) */ + num_tiles = NV40_PFB_TILE__SIZE_1; + break; + default: + num_tiles = NV40_PFB_TILE__SIZE_0; + break; + } + + fb_bar_size = drm_get_resource_len(dev, 0) - 1; + switch (dev_priv->chipset) { + case 0x40: + for (i=0; i + +#include +#include + +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +/* The sizes are taken from the difference between the start of two + * grctx addresses while running the nvidia driver. Probably slightly + * larger than they actually are, because of other objects being created + * between the contexts + */ +#define NV40_GRCTX_SIZE (175*1024) +#define NV43_GRCTX_SIZE (70*1024) +#define NV46_GRCTX_SIZE (70*1024) /* probably ~64KiB */ +#define NV4A_GRCTX_SIZE (64*1024) +#define NV4C_GRCTX_SIZE (25*1024) +#define NV4E_GRCTX_SIZE (25*1024) + +/*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 nv40_graph_context_init(drm_device_t *dev, struct mem_block *ctx) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + int i; + + /* Always has the "instance address" of itself at offset 0 */ + INSTANCE_WR(ctx, 0x00000/4, nouveau_chip_instance_get(dev, ctx)); + /* unknown */ + INSTANCE_WR(ctx, 0x00024/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00028/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00030/4, 0x00000001); + INSTANCE_WR(ctx, 0x0011c/4, 0x20010001); + INSTANCE_WR(ctx, 0x00120/4, 0x0f73ef00); + INSTANCE_WR(ctx, 0x00128/4, 0x02008821); + INSTANCE_WR(ctx, 0x0016c/4, 0x00000040); + INSTANCE_WR(ctx, 0x00170/4, 0x00000040); + INSTANCE_WR(ctx, 0x00174/4, 0x00000040); + INSTANCE_WR(ctx, 0x0017c/4, 0x80000000); + INSTANCE_WR(ctx, 0x00180/4, 0x80000000); + INSTANCE_WR(ctx, 0x00184/4, 0x80000000); + INSTANCE_WR(ctx, 0x00188/4, 0x80000000); + INSTANCE_WR(ctx, 0x0018c/4, 0x80000000); + INSTANCE_WR(ctx, 0x0019c/4, 0x00000040); + INSTANCE_WR(ctx, 0x001a0/4, 0x80000000); + INSTANCE_WR(ctx, 0x001b0/4, 0x80000000); + INSTANCE_WR(ctx, 0x001c0/4, 0x80000000); + INSTANCE_WR(ctx, 0x001d0/4, 0x0b0b0b0c); + INSTANCE_WR(ctx, 0x00340/4, 0x00040000); + INSTANCE_WR(ctx, 0x00350/4, 0x55555555); + INSTANCE_WR(ctx, 0x00354/4, 0x55555555); + INSTANCE_WR(ctx, 0x00358/4, 0x55555555); + INSTANCE_WR(ctx, 0x0035c/4, 0x55555555); + INSTANCE_WR(ctx, 0x00388/4, 0x00000008); + INSTANCE_WR(ctx, 0x0039c/4, 0x00000010); + INSTANCE_WR(ctx, 0x00480/4, 0x00000100); + INSTANCE_WR(ctx, 0x00494/4, 0x00000111); + INSTANCE_WR(ctx, 0x00498/4, 0x00080060); + INSTANCE_WR(ctx, 0x004b4/4, 0x00000080); + INSTANCE_WR(ctx, 0x004b8/4, 0xffff0000); + INSTANCE_WR(ctx, 0x004bc/4, 0x00000001); + INSTANCE_WR(ctx, 0x004d0/4, 0x46400000); + INSTANCE_WR(ctx, 0x004ec/4, 0xffff0000); + INSTANCE_WR(ctx, 0x004f8/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x004fc/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x00504/4, 0x00011100); + for (i=0x00520; i<=0x0055c; i+=4) + INSTANCE_WR(ctx, i/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x00568/4, 0x4b7fffff); + INSTANCE_WR(ctx, 0x00594/4, 0x30201000); + INSTANCE_WR(ctx, 0x00598/4, 0x70605040); + INSTANCE_WR(ctx, 0x0059c/4, 0xb8a89888); + INSTANCE_WR(ctx, 0x005a0/4, 0xf8e8d8c8); + INSTANCE_WR(ctx, 0x005b4/4, 0x40100000); + INSTANCE_WR(ctx, 0x005cc/4, 0x00000004); + INSTANCE_WR(ctx, 0x005d8/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x0060c/4, 0x435185d6); + INSTANCE_WR(ctx, 0x00610/4, 0x2155b699); + INSTANCE_WR(ctx, 0x00614/4, 0xfedcba98); + INSTANCE_WR(ctx, 0x00618/4, 0x00000098); + INSTANCE_WR(ctx, 0x00628/4, 0xffffffff); + INSTANCE_WR(ctx, 0x0062c/4, 0x00ff7000); + INSTANCE_WR(ctx, 0x00630/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00640/4, 0x00ff0000); + INSTANCE_WR(ctx, 0x0067c/4, 0x00ffff00); + /* 0x680-0x6BC - NV30_TCL_PRIMITIVE_3D_TX_ADDRESS_UNIT(0-15) */ + /* 0x6C0-0x6FC - NV30_TCL_PRIMITIVE_3D_TX_FORMAT_UNIT(0-15) */ + for (i=0x006C0; i<=0x006fc; i+=4) + INSTANCE_WR(ctx, i/4, 0x00018488); + /* 0x700-0x73C - NV30_TCL_PRIMITIVE_3D_TX_WRAP_UNIT(0-15) */ + for (i=0x00700; i<=0x0073c; i+=4) + INSTANCE_WR(ctx, i/4, 0x00028202); + /* 0x740-0x77C - NV30_TCL_PRIMITIVE_3D_TX_ENABLE_UNIT(0-15) */ + /* 0x780-0x7BC - NV30_TCL_PRIMITIVE_3D_TX_SWIZZLE_UNIT(0-15) */ + for (i=0x00780; i<=0x007bc; i+=4) + INSTANCE_WR(ctx, i/4, 0x0000aae4); + /* 0x7C0-0x7FC - NV30_TCL_PRIMITIVE_3D_TX_FILTER_UNIT(0-15) */ + for (i=0x007c0; i<=0x007fc; i+=4) + INSTANCE_WR(ctx, i/4, 0x01012000); + /* 0x800-0x83C - NV30_TCL_PRIMITIVE_3D_TX_XY_DIM_UNIT(0-15) */ + for (i=0x00800; i<=0x0083c; i+=4) + INSTANCE_WR(ctx, i/4, 0x00080008); + /* 0x840-0x87C - NV30_TCL_PRIMITIVE_3D_TX_UNK07_UNIT(0-15) */ + /* 0x880-0x8BC - NV30_TCL_PRIMITIVE_3D_TX_DEPTH_UNIT(0-15) */ + for (i=0x00880; i<=0x008bc; i+=4) + INSTANCE_WR(ctx, i/4, 0x00100008); + /* unknown */ + for (i=0x00910; i<=0x0091c; i+=4) + INSTANCE_WR(ctx, i/4, 0x0001bc80); + for (i=0x00920; i<=0x0092c; i+=4) + INSTANCE_WR(ctx, i/4, 0x00000202); + for (i=0x00940; i<=0x0094c; i+=4) + INSTANCE_WR(ctx, i/4, 0x00000008); + for (i=0x00960; i<=0x0096c; i+=4) + INSTANCE_WR(ctx, i/4, 0x00080008); + INSTANCE_WR(ctx, 0x00980/4, 0x00000002); + INSTANCE_WR(ctx, 0x009b4/4, 0x00000001); + INSTANCE_WR(ctx, 0x009c0/4, 0x3e020200); + INSTANCE_WR(ctx, 0x009c4/4, 0x00ffffff); + INSTANCE_WR(ctx, 0x009c8/4, 0x60103f00); + INSTANCE_WR(ctx, 0x009d4/4, 0x00020000); + INSTANCE_WR(ctx, 0x00a08/4, 0x00008100); + INSTANCE_WR(ctx, 0x00aac/4, 0x00000001); + INSTANCE_WR(ctx, 0x00af0/4, 0x00000001); + INSTANCE_WR(ctx, 0x00af8/4, 0x80800001); + INSTANCE_WR(ctx, 0x00bcc/4, 0x00000005); + INSTANCE_WR(ctx, 0x00bf8/4, 0x00005555); + INSTANCE_WR(ctx, 0x00bfc/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c00/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c04/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c08/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c0c/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c44/4, 0x00000001); + for (i=0x03008; i<=0x03080; i+=8) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for (i=0x05288; i<=0x08570; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for (i=0x08628; i<=0x08e18; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for (i=0x0bd28; i<=0x0f010; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for (i=0x0f0c8; i<=0x0f8b8; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for (i=0x127c8; i<=0x15ab0; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for (i=0x15b68; i<=0x16358; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for (i=0x19268; i<=0x1c550; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for (i=0x1c608; i<=0x1cdf8; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for (i=0x1fd08; i<=0x22ff0; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for (i=0x230a8; i<=0x23898; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for (i=0x267a8; i<=0x29a90; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for (i=0x29b48; i<=0x2a338; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); +} + +static void +nv43_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, 0x00000/4, nouveau_chip_instance_get(dev, ctx)); + INSTANCE_WR(ctx, 0x00024/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00028/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00030/4, 0x00000001); + INSTANCE_WR(ctx, 0x0011c/4, 0x20010001); + INSTANCE_WR(ctx, 0x00120/4, 0x0f73ef00); + INSTANCE_WR(ctx, 0x00128/4, 0x02008821); + INSTANCE_WR(ctx, 0x00178/4, 0x00000040); + INSTANCE_WR(ctx, 0x0017c/4, 0x00000040); + INSTANCE_WR(ctx, 0x00180/4, 0x00000040); + INSTANCE_WR(ctx, 0x00188/4, 0x00000040); + INSTANCE_WR(ctx, 0x00194/4, 0x80000000); + INSTANCE_WR(ctx, 0x00198/4, 0x80000000); + INSTANCE_WR(ctx, 0x0019c/4, 0x80000000); + INSTANCE_WR(ctx, 0x001a0/4, 0x80000000); + INSTANCE_WR(ctx, 0x001a4/4, 0x80000000); + INSTANCE_WR(ctx, 0x001a8/4, 0x80000000); + INSTANCE_WR(ctx, 0x001ac/4, 0x80000000); + INSTANCE_WR(ctx, 0x001b0/4, 0x80000000); + INSTANCE_WR(ctx, 0x001d0/4, 0x0b0b0b0c); + INSTANCE_WR(ctx, 0x00340/4, 0x00040000); + INSTANCE_WR(ctx, 0x00350/4, 0x55555555); + INSTANCE_WR(ctx, 0x00354/4, 0x55555555); + INSTANCE_WR(ctx, 0x00358/4, 0x55555555); + INSTANCE_WR(ctx, 0x0035c/4, 0x55555555); + INSTANCE_WR(ctx, 0x00388/4, 0x00000008); + INSTANCE_WR(ctx, 0x0039c/4, 0x00001010); + INSTANCE_WR(ctx, 0x003cc/4, 0x00000111); + INSTANCE_WR(ctx, 0x003d0/4, 0x00080060); + INSTANCE_WR(ctx, 0x003ec/4, 0x00000080); + INSTANCE_WR(ctx, 0x003f0/4, 0xffff0000); + INSTANCE_WR(ctx, 0x003f4/4, 0x00000001); + INSTANCE_WR(ctx, 0x00408/4, 0x46400000); + INSTANCE_WR(ctx, 0x00418/4, 0xffff0000); + INSTANCE_WR(ctx, 0x00424/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x00428/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x00430/4, 0x00011100); + for (i=0x0044c; i<=0x00488; i+=4) + INSTANCE_WR(ctx, i/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x00494/4, 0x4b7fffff); + INSTANCE_WR(ctx, 0x004bc/4, 0x30201000); + INSTANCE_WR(ctx, 0x004c0/4, 0x70605040); + INSTANCE_WR(ctx, 0x004c4/4, 0xb8a89888); + INSTANCE_WR(ctx, 0x004c8/4, 0xf8e8d8c8); + INSTANCE_WR(ctx, 0x004dc/4, 0x40100000); + INSTANCE_WR(ctx, 0x004f8/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x0052c/4, 0x435185d6); + INSTANCE_WR(ctx, 0x00530/4, 0x2155b699); + INSTANCE_WR(ctx, 0x00534/4, 0xfedcba98); + INSTANCE_WR(ctx, 0x00538/4, 0x00000098); + INSTANCE_WR(ctx, 0x00548/4, 0xffffffff); + INSTANCE_WR(ctx, 0x0054c/4, 0x00ff7000); + INSTANCE_WR(ctx, 0x00550/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00560/4, 0x00ff0000); + INSTANCE_WR(ctx, 0x00598/4, 0x00ffff00); + for (i=0x005dc; i<=0x00618; i+=4) + INSTANCE_WR(ctx, i/4, 0x00018488); + for (i=0x0061c; i<=0x00658; i+=4) + INSTANCE_WR(ctx, i/4, 0x00028202); + for (i=0x0069c; i<=0x006d8; i+=4) + INSTANCE_WR(ctx, i/4, 0x0000aae4); + for (i=0x006dc; i<=0x00718; i+=4) + INSTANCE_WR(ctx, i/4, 0x01012000); + for (i=0x0071c; i<=0x00758; i+=4) + INSTANCE_WR(ctx, i/4, 0x00080008); + for (i=0x0079c; i<=0x007d8; i+=4) + INSTANCE_WR(ctx, i/4, 0x00100008); + for (i=0x0082c; i<=0x00838; i+=4) + INSTANCE_WR(ctx, i/4, 0x0001bc80); + for (i=0x0083c; i<=0x00848; i+=4) + INSTANCE_WR(ctx, i/4, 0x00000202); + for (i=0x0085c; i<=0x00868; i+=4) + INSTANCE_WR(ctx, i/4, 0x00000008); + for (i=0x0087c; i<=0x00888; i+=4) + INSTANCE_WR(ctx, i/4, 0x00080008); + INSTANCE_WR(ctx, 0x0089c/4, 0x00000002); + INSTANCE_WR(ctx, 0x008d0/4, 0x00000021); + INSTANCE_WR(ctx, 0x008d4/4, 0x030c30c3); + INSTANCE_WR(ctx, 0x008e0/4, 0x3e020200); + INSTANCE_WR(ctx, 0x008e4/4, 0x00ffffff); + INSTANCE_WR(ctx, 0x008e8/4, 0x0c103f00); + INSTANCE_WR(ctx, 0x008f4/4, 0x00020000); + INSTANCE_WR(ctx, 0x0092c/4, 0x00008100); + INSTANCE_WR(ctx, 0x009b8/4, 0x00000001); + INSTANCE_WR(ctx, 0x009fc/4, 0x00001001); + INSTANCE_WR(ctx, 0x00a04/4, 0x00000003); + INSTANCE_WR(ctx, 0x00a08/4, 0x00888001); + INSTANCE_WR(ctx, 0x00a8c/4, 0x00000005); + INSTANCE_WR(ctx, 0x00a98/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00ab4/4, 0x00005555); + INSTANCE_WR(ctx, 0x00ab8/4, 0x00005555); + INSTANCE_WR(ctx, 0x00abc/4, 0x00005555); + INSTANCE_WR(ctx, 0x00ac0/4, 0x00000001); + INSTANCE_WR(ctx, 0x00af8/4, 0x00000001); + for (i=0x02ec0; i<=0x02f38; i+=8) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for (i=0x04c80; i<=0x06e70; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for (i=0x06e80; i<=0x07270; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for (i=0x096c0; i<=0x0b8b0; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for (i=0x0b8c0; i<=0x0bcb0; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for (i=0x0e100; i<=0x102f0; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for (i=0x10300; i<=0x106f0; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); +}; + +static void nv46_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, 0x00000/4, nouveau_chip_instance_get(dev, ctx)); + INSTANCE_WR(ctx, 0x00040/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00044/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x0004c/4, 0x00000001); + INSTANCE_WR(ctx, 0x00138/4, 0x20010001); + INSTANCE_WR(ctx, 0x0013c/4, 0x0f73ef00); + INSTANCE_WR(ctx, 0x00144/4, 0x02008821); + INSTANCE_WR(ctx, 0x00174/4, 0x00000001); + INSTANCE_WR(ctx, 0x00178/4, 0x00000001); + INSTANCE_WR(ctx, 0x0017c/4, 0x00000001); + INSTANCE_WR(ctx, 0x00180/4, 0x00000001); + INSTANCE_WR(ctx, 0x00184/4, 0x00000001); + INSTANCE_WR(ctx, 0x00188/4, 0x00000001); + INSTANCE_WR(ctx, 0x0018c/4, 0x00000001); + INSTANCE_WR(ctx, 0x00190/4, 0x00000001); + INSTANCE_WR(ctx, 0x00194/4, 0x00000040); + INSTANCE_WR(ctx, 0x00198/4, 0x00000040); + INSTANCE_WR(ctx, 0x0019c/4, 0x00000040); + INSTANCE_WR(ctx, 0x001a4/4, 0x00000040); + INSTANCE_WR(ctx, 0x001ec/4, 0x0b0b0b0c); + INSTANCE_WR(ctx, 0x0035c/4, 0x00040000); + INSTANCE_WR(ctx, 0x0036c/4, 0x55555555); + INSTANCE_WR(ctx, 0x00370/4, 0x55555555); + INSTANCE_WR(ctx, 0x00374/4, 0x55555555); + INSTANCE_WR(ctx, 0x00378/4, 0x55555555); + INSTANCE_WR(ctx, 0x003a4/4, 0x00000008); + INSTANCE_WR(ctx, 0x003b8/4, 0x00003010); + INSTANCE_WR(ctx, 0x003dc/4, 0x00000111); + INSTANCE_WR(ctx, 0x003e0/4, 0x00000111); + INSTANCE_WR(ctx, 0x003e4/4, 0x00000111); + INSTANCE_WR(ctx, 0x003e8/4, 0x00000111); + INSTANCE_WR(ctx, 0x003ec/4, 0x00000111); + INSTANCE_WR(ctx, 0x003f0/4, 0x00000111); + INSTANCE_WR(ctx, 0x003f4/4, 0x00000111); + INSTANCE_WR(ctx, 0x003f8/4, 0x00000111); + INSTANCE_WR(ctx, 0x003fc/4, 0x00000111); + INSTANCE_WR(ctx, 0x00400/4, 0x00000111); + INSTANCE_WR(ctx, 0x00404/4, 0x00000111); + INSTANCE_WR(ctx, 0x00408/4, 0x00000111); + INSTANCE_WR(ctx, 0x0040c/4, 0x00000111); + INSTANCE_WR(ctx, 0x00410/4, 0x00000111); + INSTANCE_WR(ctx, 0x00414/4, 0x00000111); + INSTANCE_WR(ctx, 0x00418/4, 0x00000111); + INSTANCE_WR(ctx, 0x004b0/4, 0x00000111); + INSTANCE_WR(ctx, 0x004b4/4, 0x00080060); + INSTANCE_WR(ctx, 0x004d0/4, 0x00000080); + INSTANCE_WR(ctx, 0x004d4/4, 0xffff0000); + INSTANCE_WR(ctx, 0x004d8/4, 0x00000001); + INSTANCE_WR(ctx, 0x004ec/4, 0x46400000); + INSTANCE_WR(ctx, 0x004fc/4, 0xffff0000); + INSTANCE_WR(ctx, 0x00500/4, 0x88888888); + INSTANCE_WR(ctx, 0x00504/4, 0x88888888); + INSTANCE_WR(ctx, 0x00508/4, 0x88888888); + INSTANCE_WR(ctx, 0x0050c/4, 0x88888888); + INSTANCE_WR(ctx, 0x00510/4, 0x88888888); + INSTANCE_WR(ctx, 0x00514/4, 0x88888888); + INSTANCE_WR(ctx, 0x00518/4, 0x88888888); + INSTANCE_WR(ctx, 0x0051c/4, 0x88888888); + INSTANCE_WR(ctx, 0x00520/4, 0x88888888); + INSTANCE_WR(ctx, 0x00524/4, 0x88888888); + INSTANCE_WR(ctx, 0x00528/4, 0x88888888); + INSTANCE_WR(ctx, 0x0052c/4, 0x88888888); + INSTANCE_WR(ctx, 0x00530/4, 0x88888888); + INSTANCE_WR(ctx, 0x00534/4, 0x88888888); + INSTANCE_WR(ctx, 0x00538/4, 0x88888888); + INSTANCE_WR(ctx, 0x0053c/4, 0x88888888); + INSTANCE_WR(ctx, 0x00550/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x00554/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x0055c/4, 0x00011100); + for (i=0x00578; i<0x005b4; i+=4) + INSTANCE_WR(ctx, i/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005c0/4, 0x4b7fffff); + INSTANCE_WR(ctx, 0x005e8/4, 0x30201000); + INSTANCE_WR(ctx, 0x005ec/4, 0x70605040); + INSTANCE_WR(ctx, 0x005f0/4, 0xb8a89888); + INSTANCE_WR(ctx, 0x005f4/4, 0xf8e8d8c8); + INSTANCE_WR(ctx, 0x00608/4, 0x40100000); + INSTANCE_WR(ctx, 0x00624/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00658/4, 0x435185d6); + INSTANCE_WR(ctx, 0x0065c/4, 0x2155b699); + INSTANCE_WR(ctx, 0x00660/4, 0xfedcba98); + INSTANCE_WR(ctx, 0x00664/4, 0x00000098); + INSTANCE_WR(ctx, 0x00674/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00678/4, 0x00ff7000); + INSTANCE_WR(ctx, 0x0067c/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x0068c/4, 0x00ff0000); + INSTANCE_WR(ctx, 0x006c8/4, 0x00ffff00); + for (i=0x0070c; i<=0x00748; i+=4) + INSTANCE_WR(ctx, i/4, 0x00018488); + for (i=0x0074c; i<=0x00788; i+=4) + INSTANCE_WR(ctx, i/4, 0x00028202); + for (i=0x007cc; i<=0x00808; i+=4) + INSTANCE_WR(ctx, i/4, 0x0000aae4); + for (i=0x0080c; i<=0x00848; i+=4) + INSTANCE_WR(ctx, i/4, 0x01012000); + for (i=0x0084c; i<=0x00888; i+=4) + INSTANCE_WR(ctx, i/4, 0x00080008); + for (i=0x008cc; i<=0x00908; i+=4) + INSTANCE_WR(ctx, i/4, 0x00100008); + for (i=0x0095c; i<=0x00968; i+=4) + INSTANCE_WR(ctx, i/4, 0x0001bc80); + for (i=0x0096c; i<=0x00978; i+=4) + INSTANCE_WR(ctx, i/4, 0x00000202); + for (i=0x0098c; i<=0x00998; i+=4) + INSTANCE_WR(ctx, i/4, 0x00000008); + for (i=0x009ac; i<=0x009b8; i+=4) + INSTANCE_WR(ctx, i/4, 0x00080008); + INSTANCE_WR(ctx, 0x009cc/4, 0x00000002); + INSTANCE_WR(ctx, 0x00a00/4, 0x00000421); + INSTANCE_WR(ctx, 0x00a04/4, 0x030c30c3); + INSTANCE_WR(ctx, 0x00a08/4, 0x00011001); + INSTANCE_WR(ctx, 0x00a14/4, 0x3e020200); + INSTANCE_WR(ctx, 0x00a18/4, 0x00ffffff); + INSTANCE_WR(ctx, 0x00a1c/4, 0x0c103f00); + INSTANCE_WR(ctx, 0x00a28/4, 0x00040000); + INSTANCE_WR(ctx, 0x00a60/4, 0x00008100); + INSTANCE_WR(ctx, 0x00aec/4, 0x00000001); + INSTANCE_WR(ctx, 0x00b30/4, 0x00001001); + INSTANCE_WR(ctx, 0x00b38/4, 0x00000003); + INSTANCE_WR(ctx, 0x00b3c/4, 0x00888001); + INSTANCE_WR(ctx, 0x00bc0/4, 0x00000005); + INSTANCE_WR(ctx, 0x00bcc/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00be8/4, 0x00005555); + INSTANCE_WR(ctx, 0x00bec/4, 0x00005555); + INSTANCE_WR(ctx, 0x00bf0/4, 0x00005555); + INSTANCE_WR(ctx, 0x00bf4/4, 0x00000001); + INSTANCE_WR(ctx, 0x00c2c/4, 0x00000001); + INSTANCE_WR(ctx, 0x00c30/4, 0x08e00001); + INSTANCE_WR(ctx, 0x00c34/4, 0x000e3000); + for (i=0x017f8; i<=0x01870; i+=8) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for (i=0x035b8; i<=0x057a8; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for (i=0x057b8; i<=0x05ba8; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for (i=0x07f38; i<=0x0a128; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for (i=0x0a138; i<=0x0a528; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for (i=0x0c8b8; i<=0x0eaa8; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for (i=0x0eab8; i<=0x0eea8; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); +} + +static void nv4a_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, 0x00000/4, nouveau_chip_instance_get(dev, ctx)); + INSTANCE_WR(ctx, 0x00024/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00028/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00030/4, 0x00000001); + INSTANCE_WR(ctx, 0x0011c/4, 0x20010001); + INSTANCE_WR(ctx, 0x00120/4, 0x0f73ef00); + INSTANCE_WR(ctx, 0x00128/4, 0x02008821); + INSTANCE_WR(ctx, 0x00158/4, 0x00000001); + INSTANCE_WR(ctx, 0x0015c/4, 0x00000001); + INSTANCE_WR(ctx, 0x00160/4, 0x00000001); + INSTANCE_WR(ctx, 0x00164/4, 0x00000001); + INSTANCE_WR(ctx, 0x00168/4, 0x00000001); + INSTANCE_WR(ctx, 0x0016c/4, 0x00000001); + INSTANCE_WR(ctx, 0x00170/4, 0x00000001); + INSTANCE_WR(ctx, 0x00174/4, 0x00000001); + INSTANCE_WR(ctx, 0x00178/4, 0x00000040); + INSTANCE_WR(ctx, 0x0017c/4, 0x00000040); + INSTANCE_WR(ctx, 0x00180/4, 0x00000040); + INSTANCE_WR(ctx, 0x00188/4, 0x00000040); + INSTANCE_WR(ctx, 0x001d0/4, 0x0b0b0b0c); + INSTANCE_WR(ctx, 0x00340/4, 0x00040000); + INSTANCE_WR(ctx, 0x00350/4, 0x55555555); + INSTANCE_WR(ctx, 0x00354/4, 0x55555555); + INSTANCE_WR(ctx, 0x00358/4, 0x55555555); + INSTANCE_WR(ctx, 0x0035c/4, 0x55555555); + INSTANCE_WR(ctx, 0x00388/4, 0x00000008); + INSTANCE_WR(ctx, 0x0039c/4, 0x00003010); + INSTANCE_WR(ctx, 0x003cc/4, 0x00000111); + INSTANCE_WR(ctx, 0x003d0/4, 0x00080060); + INSTANCE_WR(ctx, 0x003ec/4, 0x00000080); + INSTANCE_WR(ctx, 0x003f0/4, 0xffff0000); + INSTANCE_WR(ctx, 0x003f4/4, 0x00000001); + INSTANCE_WR(ctx, 0x00408/4, 0x46400000); + INSTANCE_WR(ctx, 0x00418/4, 0xffff0000); + INSTANCE_WR(ctx, 0x00424/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x00428/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x00430/4, 0x00011100); + for (i=0x0044c; i<=0x00488; i+=4) + INSTANCE_WR(ctx, i/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x00494/4, 0x4b7fffff); + INSTANCE_WR(ctx, 0x004bc/4, 0x30201000); + INSTANCE_WR(ctx, 0x004c0/4, 0x70605040); + INSTANCE_WR(ctx, 0x004c4/4, 0xb8a89888); + INSTANCE_WR(ctx, 0x004c8/4, 0xf8e8d8c8); + INSTANCE_WR(ctx, 0x004dc/4, 0x40100000); + INSTANCE_WR(ctx, 0x004f8/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x0052c/4, 0x435185d6); + INSTANCE_WR(ctx, 0x00530/4, 0x2155b699); + INSTANCE_WR(ctx, 0x00534/4, 0xfedcba98); + INSTANCE_WR(ctx, 0x00538/4, 0x00000098); + INSTANCE_WR(ctx, 0x00548/4, 0xffffffff); + INSTANCE_WR(ctx, 0x0054c/4, 0x00ff7000); + INSTANCE_WR(ctx, 0x00550/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x0055c/4, 0x00ff0000); + INSTANCE_WR(ctx, 0x00594/4, 0x00ffff00); + for (i=0x005d8; i<=0x00614; i+=4) + INSTANCE_WR(ctx, i/4, 0x00018488); + for (i=0x00618; i<=0x00654; i+=4) + INSTANCE_WR(ctx, i/4, 0x00028202); + for (i=0x00698; i<=0x006d4; i+=4) + INSTANCE_WR(ctx, i/4, 0x0000aae4); + for (i=0x006d8; i<=0x00714; i+=4) + INSTANCE_WR(ctx, i/4, 0x01012000); + for (i=0x00718; i<=0x00754; i+=4) + INSTANCE_WR(ctx, i/4, 0x00080008); + for (i=0x00798; i<=0x007d4; i+=4) + INSTANCE_WR(ctx, i/4, 0x00100008); + for (i=0x00828; i<=0x00834; i+=4) + INSTANCE_WR(ctx, i/4, 0x0001bc80); + for (i=0x00838; i<=0x00844; i+=4) + INSTANCE_WR(ctx, i/4, 0x00000202); + for (i=0x00858; i<=0x00864; i+=4) + INSTANCE_WR(ctx, i/4, 0x00000008); + for (i=0x00878; i<=0x00884; i+=4) + INSTANCE_WR(ctx, i/4, 0x00080008); + INSTANCE_WR(ctx, 0x00898/4, 0x00000002); + INSTANCE_WR(ctx, 0x008cc/4, 0x00000021); + INSTANCE_WR(ctx, 0x008d0/4, 0x030c30c3); + INSTANCE_WR(ctx, 0x008d4/4, 0x00011001); + INSTANCE_WR(ctx, 0x008e0/4, 0x3e020200); + INSTANCE_WR(ctx, 0x008e4/4, 0x00ffffff); + INSTANCE_WR(ctx, 0x008e8/4, 0x0c103f00); + INSTANCE_WR(ctx, 0x008f4/4, 0x00040000); + INSTANCE_WR(ctx, 0x0092c/4, 0x00008100); + INSTANCE_WR(ctx, 0x009b8/4, 0x00000001); + INSTANCE_WR(ctx, 0x009fc/4, 0x00001001); + INSTANCE_WR(ctx, 0x00a04/4, 0x00000003); + INSTANCE_WR(ctx, 0x00a08/4, 0x00888001); + INSTANCE_WR(ctx, 0x00a8c/4, 0x00000005); + INSTANCE_WR(ctx, 0x00a98/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00ab4/4, 0x00005555); + INSTANCE_WR(ctx, 0x00ab8/4, 0x00005555); + INSTANCE_WR(ctx, 0x00abc/4, 0x00005555); + INSTANCE_WR(ctx, 0x00ac0/4, 0x00000001); + INSTANCE_WR(ctx, 0x00af8/4, 0x00000001); + for (i=0x016c0; i<=0x01738; i+=8) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for (i=0x03840; i<=0x05670; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for (i=0x05680; i<=0x05a70; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for (i=0x07e00; i<=0x09ff0; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for (i=0x0a000; i<=0x0a3f0; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for (i=0x0c780; i<=0x0e970; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for (i=0x0e980; i<=0x0ed70; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); +} + + +static void nv4c_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, 0x00000/4, nouveau_chip_instance_get(dev, ctx)); + INSTANCE_WR(ctx, 0x00024/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00028/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00030/4, 0x00000001); + INSTANCE_WR(ctx, 0x0011c/4, 0x20010001); + INSTANCE_WR(ctx, 0x00120/4, 0x0f73ef00); + INSTANCE_WR(ctx, 0x00128/4, 0x02008821); + INSTANCE_WR(ctx, 0x00158/4, 0x00000001); + INSTANCE_WR(ctx, 0x0015c/4, 0x00000001); + INSTANCE_WR(ctx, 0x00160/4, 0x00000001); + INSTANCE_WR(ctx, 0x00164/4, 0x00000001); + INSTANCE_WR(ctx, 0x00168/4, 0x00000001); + INSTANCE_WR(ctx, 0x0016c/4, 0x00000001); + INSTANCE_WR(ctx, 0x00170/4, 0x00000001); + INSTANCE_WR(ctx, 0x00174/4, 0x00000001); + INSTANCE_WR(ctx, 0x00178/4, 0x00000040); + INSTANCE_WR(ctx, 0x0017c/4, 0x00000040); + INSTANCE_WR(ctx, 0x00180/4, 0x00000040); + INSTANCE_WR(ctx, 0x00188/4, 0x00000040); + INSTANCE_WR(ctx, 0x001d0/4, 0x0b0b0b0c); + INSTANCE_WR(ctx, 0x00340/4, 0x00040000); + INSTANCE_WR(ctx, 0x00350/4, 0x55555555); + INSTANCE_WR(ctx, 0x00354/4, 0x55555555); + INSTANCE_WR(ctx, 0x00358/4, 0x55555555); + INSTANCE_WR(ctx, 0x0035c/4, 0x55555555); + INSTANCE_WR(ctx, 0x00388/4, 0x00000008); + INSTANCE_WR(ctx, 0x0039c/4, 0x00001010); + INSTANCE_WR(ctx, 0x003d0/4, 0x00000111); + INSTANCE_WR(ctx, 0x003d4/4, 0x00080060); + INSTANCE_WR(ctx, 0x003f0/4, 0x00000080); + INSTANCE_WR(ctx, 0x003f4/4, 0xffff0000); + INSTANCE_WR(ctx, 0x003f8/4, 0x00000001); + INSTANCE_WR(ctx, 0x0040c/4, 0x46400000); + INSTANCE_WR(ctx, 0x0041c/4, 0xffff0000); + INSTANCE_WR(ctx, 0x00428/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x0042c/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x00434/4, 0x00011100); + for (i=0x00450; i<0x0048c; i+=4) + INSTANCE_WR(ctx, i/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x00498/4, 0x4b7fffff); + INSTANCE_WR(ctx, 0x004c0/4, 0x30201000); + INSTANCE_WR(ctx, 0x004c4/4, 0x70605040); + INSTANCE_WR(ctx, 0x004c8/4, 0xb8a89888); + INSTANCE_WR(ctx, 0x004cc/4, 0xf8e8d8c8); + INSTANCE_WR(ctx, 0x004e0/4, 0x40100000); + INSTANCE_WR(ctx, 0x004fc/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00530/4, 0x435185d6); + INSTANCE_WR(ctx, 0x00534/4, 0x2155b699); + INSTANCE_WR(ctx, 0x00538/4, 0xfedcba98); + INSTANCE_WR(ctx, 0x0053c/4, 0x00000098); + INSTANCE_WR(ctx, 0x0054c/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00550/4, 0x00ff7000); + INSTANCE_WR(ctx, 0x00554/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00564/4, 0x00ff0000); + INSTANCE_WR(ctx, 0x0059c/4, 0x00ffff00); + for (i=0x005e0; i<=0x0061c; i+=4) + INSTANCE_WR(ctx, i/4, 0x00018488); + for (i=0x00620; i<=0x0065c; i+=4) + INSTANCE_WR(ctx, i/4, 0x00028202); + for (i=0x006a0; i<=0x006dc; i+=4) + INSTANCE_WR(ctx, i/4, 0x0000aae4); + for (i=0x006e0; i<=0x0071c; i+=4) + INSTANCE_WR(ctx, i/4, 0x01012000); + for (i=0x00720; i<=0x0075c; i+=4) + INSTANCE_WR(ctx, i/4, 0x00080008); + for (i=0x007a0; i<=0x007dc; i+=4) + INSTANCE_WR(ctx, i/4, 0x00100008); + for (i=0x00830; i<=0x0083c; i+=4) + INSTANCE_WR(ctx, i/4, 0x0001bc80); + for (i=0x00840; i<=0x0084c; i+=4) + INSTANCE_WR(ctx, i/4, 0x00000202); + for (i=0x00860; i<=0x0086c; i+=4) + INSTANCE_WR(ctx, i/4, 0x00000008); + for (i=0x00880; i<=0x0088c; i+=4) + INSTANCE_WR(ctx, i/4, 0x00080008); + INSTANCE_WR(ctx, 0x008a0/4, 0x00000002); + INSTANCE_WR(ctx, 0x008d4/4, 0x00000020); + INSTANCE_WR(ctx, 0x008d8/4, 0x030c30c3); + INSTANCE_WR(ctx, 0x008dc/4, 0x00011001); + INSTANCE_WR(ctx, 0x008e8/4, 0x3e020200); + INSTANCE_WR(ctx, 0x008ec/4, 0x00ffffff); + INSTANCE_WR(ctx, 0x008f0/4, 0x0c103f00); + INSTANCE_WR(ctx, 0x008fc/4, 0x00040000); + INSTANCE_WR(ctx, 0x00934/4, 0x00008100); + INSTANCE_WR(ctx, 0x009c0/4, 0x00000001); + INSTANCE_WR(ctx, 0x00a04/4, 0x00001001); + INSTANCE_WR(ctx, 0x00a0c/4, 0x00000003); + INSTANCE_WR(ctx, 0x00a10/4, 0x00888001); + INSTANCE_WR(ctx, 0x00a74/4, 0x00000005); + INSTANCE_WR(ctx, 0x00a80/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00a9c/4, 0x00005555); + INSTANCE_WR(ctx, 0x00aa0/4, 0x00000001); + INSTANCE_WR(ctx, 0x00ad8/4, 0x00000001); + for (i=0x016a0; i<0x01718; i+=8) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for (i=0x03460; i<0x05650; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for (i=0x05660; i<0x05a50; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); +} + +static void nv4e_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, 0x00000/4, nouveau_chip_instance_get(dev, ctx)); + INSTANCE_WR(ctx, 0x00024/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00028/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00030/4, 0x00000001); + INSTANCE_WR(ctx, 0x0011c/4, 0x20010001); + INSTANCE_WR(ctx, 0x00120/4, 0x0f73ef00); + INSTANCE_WR(ctx, 0x00128/4, 0x02008821); + INSTANCE_WR(ctx, 0x00158/4, 0x00000001); + INSTANCE_WR(ctx, 0x0015c/4, 0x00000001); + INSTANCE_WR(ctx, 0x00160/4, 0x00000001); + INSTANCE_WR(ctx, 0x00164/4, 0x00000001); + INSTANCE_WR(ctx, 0x00168/4, 0x00000001); + INSTANCE_WR(ctx, 0x0016c/4, 0x00000001); + INSTANCE_WR(ctx, 0x00170/4, 0x00000001); + INSTANCE_WR(ctx, 0x00174/4, 0x00000001); + INSTANCE_WR(ctx, 0x00178/4, 0x00000040); + INSTANCE_WR(ctx, 0x0017c/4, 0x00000040); + INSTANCE_WR(ctx, 0x00180/4, 0x00000040); + INSTANCE_WR(ctx, 0x00188/4, 0x00000040); + INSTANCE_WR(ctx, 0x001d0/4, 0x0b0b0b0c); + INSTANCE_WR(ctx, 0x00340/4, 0x00040000); + INSTANCE_WR(ctx, 0x00350/4, 0x55555555); + INSTANCE_WR(ctx, 0x00354/4, 0x55555555); + INSTANCE_WR(ctx, 0x00358/4, 0x55555555); + INSTANCE_WR(ctx, 0x0035c/4, 0x55555555); + INSTANCE_WR(ctx, 0x00388/4, 0x00000008); + INSTANCE_WR(ctx, 0x0039c/4, 0x00001010); + INSTANCE_WR(ctx, 0x003cc/4, 0x00000111); + INSTANCE_WR(ctx, 0x003d0/4, 0x00080060); + INSTANCE_WR(ctx, 0x003ec/4, 0x00000080); + INSTANCE_WR(ctx, 0x003f0/4, 0xffff0000); + INSTANCE_WR(ctx, 0x003f4/4, 0x00000001); + INSTANCE_WR(ctx, 0x00408/4, 0x46400000); + INSTANCE_WR(ctx, 0x00418/4, 0xffff0000); + INSTANCE_WR(ctx, 0x00424/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x00428/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x00430/4, 0x00011100); + for (i=0x0044c; i<=0x00488; i+=4) + INSTANCE_WR(ctx, i/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x00494/4, 0x4b7fffff); + INSTANCE_WR(ctx, 0x004bc/4, 0x30201000); + INSTANCE_WR(ctx, 0x004c0/4, 0x70605040); + INSTANCE_WR(ctx, 0x004c4/4, 0xb8a89888); + INSTANCE_WR(ctx, 0x004c8/4, 0xf8e8d8c8); + INSTANCE_WR(ctx, 0x004dc/4, 0x40100000); + INSTANCE_WR(ctx, 0x004f8/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x0052c/4, 0x435185d6); + INSTANCE_WR(ctx, 0x00530/4, 0x2155b699); + INSTANCE_WR(ctx, 0x00534/4, 0xfedcba98); + INSTANCE_WR(ctx, 0x00538/4, 0x00000098); + INSTANCE_WR(ctx, 0x00548/4, 0xffffffff); + INSTANCE_WR(ctx, 0x0054c/4, 0x00ff7000); + INSTANCE_WR(ctx, 0x00550/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x0055c/4, 0x00ff0000); + INSTANCE_WR(ctx, 0x00594/4, 0x00ffff00); + for (i=0x005d8; i<=0x00614; i+=4) + INSTANCE_WR(ctx, i/4, 0x00018488); + for (i=0x00618; i<=0x00654; i+=4) + INSTANCE_WR(ctx, i/4, 0x00028202); + for (i=0x00698; i<=0x006d4; i+=4) + INSTANCE_WR(ctx, i/4, 0x0000aae4); + for (i=0x006d8; i<=0x00714; i+=4) + INSTANCE_WR(ctx, i/4, 0x01012000); + for (i=0x00718; i<=0x00754; i+=4) + INSTANCE_WR(ctx, i/4, 0x00080008); + for (i=0x00798; i<=0x007d4; i+=4) + INSTANCE_WR(ctx, i/4, 0x00100008); + for (i=0x00828; i<=0x00834; i+=4) + INSTANCE_WR(ctx, i/4, 0x0001bc80); + for (i=0x00838; i<=0x00844; i+=4) + INSTANCE_WR(ctx, i/4, 0x00000202); + for (i=0x00858; i<=0x00864; i+=4) + INSTANCE_WR(ctx, i/4, 0x00000008); + for (i=0x00878; i<=0x00884; i+=4) + INSTANCE_WR(ctx, i/4, 0x00080008); + INSTANCE_WR(ctx, 0x00898/4, 0x00000002); + INSTANCE_WR(ctx, 0x008cc/4, 0x00000020); + INSTANCE_WR(ctx, 0x008d0/4, 0x030c30c3); + INSTANCE_WR(ctx, 0x008d4/4, 0x00011001); + INSTANCE_WR(ctx, 0x008e0/4, 0x3e020200); + INSTANCE_WR(ctx, 0x008e4/4, 0x00ffffff); + INSTANCE_WR(ctx, 0x008e8/4, 0x0c103f00); + INSTANCE_WR(ctx, 0x008f4/4, 0x00040000); + INSTANCE_WR(ctx, 0x0092c/4, 0x00008100); + INSTANCE_WR(ctx, 0x009b8/4, 0x00000001); + INSTANCE_WR(ctx, 0x009fc/4, 0x00001001); + INSTANCE_WR(ctx, 0x00a04/4, 0x00000003); + INSTANCE_WR(ctx, 0x00a08/4, 0x00888001); + INSTANCE_WR(ctx, 0x00a6c/4, 0x00000005); + INSTANCE_WR(ctx, 0x00a78/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00a94/4, 0x00005555); + INSTANCE_WR(ctx, 0x00a98/4, 0x00000001); + INSTANCE_WR(ctx, 0x00aa4/4, 0x00000001); + for (i=0x01668; i<=0x016e0; i+=8) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for (i=0x03428; i<=0x05618; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for (i=0x05628; i<=0x05a18; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); +} + +int +nv40_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; + + switch (dev_priv->chipset) { + case 0x40: + ctx_size = NV40_GRCTX_SIZE; + ctx_init = nv40_graph_context_init; + break; + case 0x43: + ctx_size = NV43_GRCTX_SIZE; + ctx_init = nv43_graph_context_init; + break; + case 0x46: + ctx_size = NV46_GRCTX_SIZE; + ctx_init = nv46_graph_context_init; + break; + case 0x4a: + ctx_size = NV4A_GRCTX_SIZE; + ctx_init = nv4a_graph_context_init; + break; + case 0x4c: + ctx_size = NV4C_GRCTX_SIZE; + ctx_init = nv4c_graph_context_init; + break; + case 0x4e: + ctx_size = NV4E_GRCTX_SIZE; + ctx_init = nv4e_graph_context_init; + break; + default: + ctx_size = NV40_GRCTX_SIZE; + ctx_init = nv40_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; +} + +/* 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(NV04_PGRAPH_FIFO, 0); + + instance = NV_READ(0x40032C) & 0xFFFFF; + if (!instance) { + NV_WRITE(NV04_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(NV04_PGRAPH_FIFO, 1); + return; + } + + NV_WRITE(NV04_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(NV04_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(NV04_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(NV04_PGRAPH_FIFO, 1); +} + +/* Some voodoo that makes context switching work without the binary driver + * initialising the card first. + * + * It is possible to effect how the context is saved from PGRAPH into a block + * of instance memory by altering the values in these tables. This may mean + * that the context layout of each chipset is slightly different (at least + * NV40 and C51 are different). It would also be possible for chipsets to + * have an identical context layout, but pull the data from different PGRAPH + * registers. + * + * TODO: decode the meaning of the magic values, may provide clues about the + * differences between the various NV40 chipsets. + * TODO: one we have a better idea of how each chipset differs, perhaps think + * about unifying these instead of providing a separate table for each + * chip. + * + * mmio-trace dumps from other nv4x/g7x/c5x cards very welcome :) + */ +static uint32_t nv40_ctx_voodoo[] = { + 0x00400889, 0x00200000, 0x0060000a, 0x00200000, 0x00300000, 0x00800001, + 0x00700009, 0x0060000e, 0x00400d64, 0x00400d05, 0x00408f65, 0x00409406, + 0x0040a268, 0x00200000, 0x0060000a, 0x00700000, 0x00106000, 0x00700080, + 0x004014e6, 0x007000a0, 0x00401a84, 0x00700082, 0x00600001, 0x00500061, + 0x00600002, 0x00401b68, 0x00500060, 0x00200001, 0x0060000a, 0x0011814d, + 0x00110158, 0x00105401, 0x0020003a, 0x00100051, 0x001040c5, 0x0010c1c4, + 0x001041c9, 0x0010c1dc, 0x00110205, 0x0011420a, 0x00114210, 0x00110216, + 0x0012421b, 0x00120270, 0x001242c0, 0x00200040, 0x00100280, 0x00128100, + 0x00128120, 0x00128143, 0x0011415f, 0x0010815c, 0x0010c140, 0x00104029, + 0x00110400, 0x00104d10, 0x00500060, 0x00403b87, 0x0060000d, 0x004076e6, + 0x002000f0, 0x0060000a, 0x00200045, 0x00100620, 0x00108668, 0x0011466b, + 0x00120682, 0x0011068b, 0x00168691, 0x0010c6ae, 0x001206b4, 0x0020002a, + 0x001006c4, 0x001246f0, 0x002000c0, 0x00100700, 0x0010c3d7, 0x001043e1, + 0x00500060, 0x00405600, 0x00405684, 0x00600003, 0x00500067, 0x00600008, + 0x00500060, 0x00700082, 0x0020026c, 0x0060000a, 0x00104800, 0x00104901, + 0x00120920, 0x00200035, 0x00100940, 0x00148a00, 0x00104a14, 0x00200038, + 0x00100b00, 0x00138d00, 0x00104e00, 0x0012d600, 0x00105c00, 0x00104f06, + 0x0020031a, 0x0060000a, 0x00300000, 0x00200680, 0x00406c00, 0x00200684, + 0x00800001, 0x00200b62, 0x0060000a, 0x0020a0b0, 0x0040728a, 0x00201b68, + 0x00800041, 0x00407684, 0x00203e60, 0x00800002, 0x00408700, 0x00600006, + 0x00700003, 0x004080e6, 0x00700080, 0x0020031a, 0x0060000a, 0x00200004, + 0x00800001, 0x00700000, 0x00200000, 0x0060000a, 0x00106002, 0x0040a284, + 0x00700002, 0x00600004, 0x0040a268, 0x00700000, 0x00200000, 0x0060000a, + 0x00106002, 0x00700080, 0x00400a84, 0x00700002, 0x00400a68, 0x00500060, + 0x00600007, 0x00409388, 0x0060000f, 0x00000000, 0x00500060, 0x00200000, + 0x0060000a, 0x00700000, 0x00106001, 0x00700083, 0x00910880, 0x00901ffe, + 0x00940400, 0x00200020, 0x0060000b, 0x00500069, 0x0060000c, 0x00401b68, + 0x0040a406, 0x0040a505, 0x00600009, 0x00700005, 0x00700006, 0x0060000e, + ~0 +}; + +static uint32_t nv43_ctx_voodoo[] = { + 0x00400889, 0x00200000, 0x0060000a, 0x00200000, 0x00300000, 0x00800001, + 0x00700009, 0x0060000e, 0x00400d64, 0x00400d05, 0x00409565, 0x00409a06, + 0x0040a868, 0x00200000, 0x0060000a, 0x00700000, 0x00106000, 0x00700080, + 0x004014e6, 0x007000a0, 0x00401a84, 0x00700082, 0x00600001, 0x00500061, + 0x00600002, 0x00401b68, 0x00500060, 0x00200001, 0x0060000a, 0x0011814d, + 0x00110158, 0x00105401, 0x0020003a, 0x00100051, 0x001040c5, 0x0010c1c4, + 0x001041c9, 0x0010c1dc, 0x00150210, 0x0012c225, 0x00108238, 0x0010823e, + 0x001242c0, 0x00200040, 0x00100280, 0x00128100, 0x00128120, 0x00128143, + 0x0011415f, 0x0010815c, 0x0010c140, 0x00104029, 0x00110400, 0x00104d10, + 0x001046ec, 0x00500060, 0x00403a87, 0x0060000d, 0x00407ce6, 0x002000f1, + 0x0060000a, 0x00148653, 0x00104668, 0x0010c66d, 0x00120682, 0x0011068b, + 0x00168691, 0x001046ae, 0x001046b0, 0x001206b4, 0x001046c4, 0x001146c6, + 0x00200020, 0x001006cc, 0x001046ed, 0x001246f0, 0x002000c0, 0x00100700, + 0x0010c3d7, 0x001043e1, 0x00500060, 0x00405800, 0x00405884, 0x00600003, + 0x00500067, 0x00600008, 0x00500060, 0x00700082, 0x00200233, 0x0060000a, + 0x00104800, 0x00108901, 0x00124920, 0x0020001f, 0x00100940, 0x00140965, + 0x00148a00, 0x00108a14, 0x00160b00, 0x00134b2c, 0x0010cd00, 0x0010cd04, + 0x0010cd08, 0x00104d80, 0x00104e00, 0x0012d600, 0x00105c00, 0x00104f06, + 0x002002c8, 0x0060000a, 0x00300000, 0x00200680, 0x00407200, 0x00200684, + 0x00800001, 0x00200b10, 0x0060000a, 0x00203870, 0x0040788a, 0x00201350, + 0x00800041, 0x00407c84, 0x00201560, 0x00800002, 0x00408d00, 0x00600006, + 0x00700003, 0x004086e6, 0x00700080, 0x002002c8, 0x0060000a, 0x00200004, + 0x00800001, 0x00700000, 0x00200000, 0x0060000a, 0x00106002, 0x0040a884, + 0x00700002, 0x00600004, 0x0040a868, 0x00700000, 0x00200000, 0x0060000a, + 0x00106002, 0x00700080, 0x00400a84, 0x00700002, 0x00400a68, 0x00500060, + 0x00600007, 0x00409988, 0x0060000f, 0x00000000, 0x00500060, 0x00200000, + 0x0060000a, 0x00700000, 0x00106001, 0x00700083, 0x00910880, 0x00901ffe, + 0x00940400, 0x00200020, 0x0060000b, 0x00500069, 0x0060000c, 0x00401b68, + 0x0040aa06, 0x0040ab05, 0x00600009, 0x00700005, 0x00700006, 0x0060000e, + ~0 +}; + +static uint32_t nv46_ctx_voodoo[] = { + 0x00400889, 0x00200000, 0x0060000a, 0x00200000, 0x00300000, 0x00800001, + 0x00700009, 0x0060000e, 0x00400d64, 0x00400d05, 0x00408f65, 0x00409306, + 0x0040a068, 0x0040198f, 0x00200001, 0x0060000a, 0x00700080, 0x00104042, + 0x00200001, 0x0060000a, 0x00700000, 0x001040c5, 0x00401826, 0x00401968, + 0x0060000d, 0x00200000, 0x0060000a, 0x00700000, 0x00106000, 0x00700080, + 0x004020e6, 0x007000a0, 0x00500060, 0x00200008, 0x0060000a, 0x0011814d, + 0x00110158, 0x00105401, 0x0020003a, 0x00100051, 0x001040c5, 0x0010c1c4, + 0x001041c9, 0x0010c1dc, 0x00150210, 0x0012c225, 0x00108238, 0x0010823e, + 0x001242c0, 0x00200040, 0x00100280, 0x00128100, 0x00128120, 0x00128143, + 0x0011415f, 0x0010815c, 0x0010c140, 0x00104029, 0x00110400, 0x00104d10, + 0x00500060, 0x00403f87, 0x0060000d, 0x004079e6, 0x002000f7, 0x0060000a, + 0x00200045, 0x00100620, 0x00104668, 0x0017466d, 0x0011068b, 0x00168691, + 0x001046ae, 0x001046b0, 0x001206b4, 0x001046c4, 0x001146c6, 0x00200022, + 0x001006cc, 0x001246f0, 0x002000c0, 0x00100700, 0x0010c3d7, 0x001043e1, + 0x00500060, 0x0020027f, 0x0060000a, 0x00104800, 0x00108901, 0x00104910, + 0x00124920, 0x0020001f, 0x00100940, 0x00140965, 0x00148a00, 0x00108a14, + 0x00160b00, 0x00134b2c, 0x0010cd00, 0x0010cd04, 0x0010cd08, 0x00104d80, + 0x00104e00, 0x0012d600, 0x00105c00, 0x00104f06, 0x00105406, 0x00105709, + 0x00200316, 0x0060000a, 0x00300000, 0x00200080, 0x00407200, 0x00200084, + 0x00800001, 0x0020055e, 0x0060000a, 0x002037e0, 0x0040788a, 0x00201320, + 0x00800029, 0x00408900, 0x00600006, 0x004085e6, 0x00700080, 0x00200081, + 0x0060000a, 0x00104280, 0x00200316, 0x0060000a, 0x00200004, 0x00800001, + 0x00700000, 0x00200000, 0x0060000a, 0x00106002, 0x0040a068, 0x00700000, + 0x00200000, 0x0060000a, 0x00106002, 0x00700080, 0x00400a68, 0x00500060, + 0x00600007, 0x00409388, 0x0060000f, 0x00500060, 0x00200000, 0x0060000a, + 0x00700000, 0x00106001, 0x00910880, 0x00901ffe, 0x01940000, 0x00200020, + 0x0060000b, 0x00500069, 0x0060000c, 0x00402168, 0x0040a206, 0x0040a305, + 0x00600009, 0x00700005, 0x00700006, 0x0060000e, ~0 +}; + +static uint32_t nv4a_ctx_voodoo[] = { + 0x00400889, 0x00200000, 0x0060000a, 0x00200000, 0x00300000, 0x00800001, + 0x00700009, 0x0060000e, 0x00400d64, 0x00400d05, 0x00409965, 0x00409e06, + 0x0040ac68, 0x00200000, 0x0060000a, 0x00700000, 0x00106000, 0x00700080, + 0x004014e6, 0x007000a0, 0x00401a84, 0x00700082, 0x00600001, 0x00500061, + 0x00600002, 0x00401b68, 0x00500060, 0x00200001, 0x0060000a, 0x0011814d, + 0x00110158, 0x00105401, 0x0020003a, 0x00100051, 0x001040c5, 0x0010c1c4, + 0x001041c9, 0x0010c1dc, 0x00150210, 0x0012c225, 0x00108238, 0x0010823e, + 0x001242c0, 0x00200040, 0x00100280, 0x00128100, 0x00128120, 0x00128143, + 0x0011415f, 0x0010815c, 0x0010c140, 0x00104029, 0x00110400, 0x00104d10, + 0x001046ec, 0x00500060, 0x00403a87, 0x0060000d, 0x00407de6, 0x002000f1, + 0x0060000a, 0x00148653, 0x00104668, 0x0010c66d, 0x00120682, 0x0011068b, + 0x00168691, 0x001046ae, 0x001046b0, 0x001206b4, 0x001046c4, 0x001146c6, + 0x001646cc, 0x001186e6, 0x001046ed, 0x001246f0, 0x002000c0, 0x00100700, + 0x0010c3d7, 0x001043e1, 0x00500060, 0x00405800, 0x00405884, 0x00600003, + 0x00500067, 0x00600008, 0x00500060, 0x00700082, 0x00200232, 0x0060000a, + 0x00104800, 0x00108901, 0x00104910, 0x00124920, 0x0020001f, 0x00100940, + 0x00140965, 0x00148a00, 0x00108a14, 0x00160b00, 0x00134b2c, 0x0010cd00, + 0x0010cd04, 0x0010cd08, 0x00104d80, 0x00104e00, 0x0012d600, 0x00105c00, + 0x00104f06, 0x002002c8, 0x0060000a, 0x00300000, 0x00200080, 0x00407300, + 0x00200084, 0x00800001, 0x00200510, 0x0060000a, 0x002037e0, 0x0040798a, + 0x00201320, 0x00800029, 0x00407d84, 0x00201560, 0x00800002, 0x00409100, + 0x00600006, 0x00700003, 0x00408ae6, 0x00700080, 0x0020007a, 0x0060000a, + 0x00104280, 0x002002c8, 0x0060000a, 0x00200004, 0x00800001, 0x00700000, + 0x00200000, 0x0060000a, 0x00106002, 0x0040ac84, 0x00700002, 0x00600004, + 0x0040ac68, 0x00700000, 0x00200000, 0x0060000a, 0x00106002, 0x00700080, + 0x00400a84, 0x00700002, 0x00400a68, 0x00500060, 0x00600007, 0x00409d88, + 0x0060000f, 0x00000000, 0x00500060, 0x00200000, 0x0060000a, 0x00700000, + 0x00106001, 0x00700083, 0x00910880, 0x00901ffe, 0x01940000, 0x00200020, + 0x0060000b, 0x00500069, 0x0060000c, 0x00401b68, 0x0040ae06, 0x0040af05, + 0x00600009, 0x00700005, 0x00700006, 0x0060000e, ~0 +}; + +static uint32_t nv4e_ctx_voodoo[] = { + 0x00400889, 0x00200000, 0x0060000a, 0x00200000, 0x00300000, 0x00800001, + 0x00700009, 0x0060000e, 0x00400d64, 0x00400d05, 0x00409565, 0x00409a06, + 0x0040a868, 0x00200000, 0x0060000a, 0x00700000, 0x00106000, 0x00700080, + 0x004014e6, 0x007000a0, 0x00401a84, 0x00700082, 0x00600001, 0x00500061, + 0x00600002, 0x00401b68, 0x00500060, 0x00200001, 0x0060000a, 0x0011814d, + 0x00110158, 0x00105401, 0x0020003a, 0x00100051, 0x001040c5, 0x0010c1c4, + 0x001041c9, 0x0010c1dc, 0x00150210, 0x0012c225, 0x00108238, 0x0010823e, + 0x001242c0, 0x00200040, 0x00100280, 0x00128100, 0x00128120, 0x00128143, + 0x0011415f, 0x0010815c, 0x0010c140, 0x00104029, 0x00110400, 0x00104d10, + 0x001046ec, 0x00500060, 0x00403a87, 0x0060000d, 0x00407ce6, 0x002000f1, + 0x0060000a, 0x00148653, 0x00104668, 0x0010c66d, 0x00120682, 0x0011068b, + 0x00168691, 0x001046ae, 0x001046b0, 0x001206b4, 0x001046c4, 0x001146c6, + 0x001646cc, 0x001186e6, 0x001046ed, 0x001246f0, 0x002000c0, 0x00100700, + 0x0010c3d7, 0x001043e1, 0x00500060, 0x00405800, 0x00405884, 0x00600003, + 0x00500067, 0x00600008, 0x00500060, 0x00700082, 0x00200232, 0x0060000a, + 0x00104800, 0x00108901, 0x00104910, 0x00124920, 0x0020001f, 0x00100940, + 0x00140965, 0x00148a00, 0x00108a14, 0x00140b00, 0x00134b2c, 0x0010cd00, + 0x0010cd04, 0x00104d08, 0x00104d80, 0x00104e00, 0x00105c00, 0x00104f06, + 0x002002b2, 0x0060000a, 0x00300000, 0x00200080, 0x00407200, 0x00200084, + 0x00800001, 0x002004fa, 0x0060000a, 0x00201320, 0x0040788a, 0xfffffb06, + 0x00800029, 0x00407c84, 0x00200b20, 0x00800002, 0x00408d00, 0x00600006, + 0x00700003, 0x004086e6, 0x00700080, 0x002002b2, 0x0060000a, 0x00200004, + 0x00800001, 0x00700000, 0x00200000, 0x0060000a, 0x00106002, 0x0040a884, + 0x00700002, 0x00600004, 0x0040a868, 0x00700000, 0x00200000, 0x0060000a, + 0x00106002, 0x00700080, 0x00400a84, 0x00700002, 0x00400a68, 0x00500060, + 0x00600007, 0x00409988, 0x0060000f, 0x00000000, 0x00500060, 0x00200000, + 0x0060000a, 0x00700000, 0x00106001, 0x00700083, 0x00910880, 0x00901ffe, + 0x01940000, 0x00200020, 0x0060000b, 0x00500069, 0x0060000c, 0x00401b68, + 0x0040aa06, 0x0040ab05, 0x00600009, 0x00700005, 0x00700006, 0x0060000e, + ~0 +}; + +/* + * G70 0x47 + * G71 0x49 + * NV45 0x48 + * G72[M] 0x46 + * G73 0x4b + * C51_G7X 0x4c + * C51 0x4e + */ +int +nv40_graph_init(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = + (drm_nouveau_private_t *)dev->dev_private; + uint32_t *ctx_voodoo; + uint32_t vramsz, tmp; + int i, j; + + NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) & + ~NV_PMC_ENABLE_PGRAPH); + NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) | + NV_PMC_ENABLE_PGRAPH); + + switch (dev_priv->chipset) { + case 0x40: ctx_voodoo = nv40_ctx_voodoo; break; + case 0x43: ctx_voodoo = nv43_ctx_voodoo; break; + case 0x46: ctx_voodoo = nv46_ctx_voodoo; break; + case 0x4a: ctx_voodoo = nv4a_ctx_voodoo; break; + case 0x4e: ctx_voodoo = nv4e_ctx_voodoo; break; + default: + DRM_ERROR("Unknown ctx_voodoo for chipset 0x%02x\n", + dev_priv->chipset); + ctx_voodoo = NULL; + break; + } + + /* Load the context voodoo onto the card */ + if (ctx_voodoo) { + DRM_DEBUG("Loading context-switch voodoo\n"); + i = 0; + + NV_WRITE(0x400324, 0); + while (ctx_voodoo[i] != ~0) { + NV_WRITE(0x400328, ctx_voodoo[i]); + i++; + } + } + + /* No context present currently */ + NV_WRITE(0x40032C, 0x00000000); + + NV_WRITE(NV03_PGRAPH_INTR_EN, 0x00000000); + NV_WRITE(NV03_PGRAPH_INTR , 0xFFFFFFFF); + + NV_WRITE(NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); + NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x00000000); + NV_WRITE(NV04_PGRAPH_DEBUG_1, 0x401287c0); + NV_WRITE(NV04_PGRAPH_DEBUG_3, 0xe0de8055); + NV_WRITE(NV10_PGRAPH_DEBUG_4, 0x00008000); + NV_WRITE(NV04_PGRAPH_LIMIT_VIOL_PIX, 0x00be3c5f); + + NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100); + NV_WRITE(NV10_PGRAPH_STATE , 0xFFFFFFFF); + NV_WRITE(NV04_PGRAPH_FIFO , 0x00000001); + + j = NV_READ(0x1540) & 0xff; + if (j) { + for (i=0; !(j&1); j>>=1, i++); + NV_WRITE(0x405000, i); + } + + if (dev_priv->chipset == 0x40) { + NV_WRITE(0x4009b0, 0x83280fff); + NV_WRITE(0x4009b4, 0x000000a0); + } else { + NV_WRITE(0x400820, 0x83280eff); + NV_WRITE(0x400824, 0x000000a0); + } + + switch (dev_priv->chipset) { + case 0x40: + case 0x45: + NV_WRITE(0x4009b8, 0x0078e366); + NV_WRITE(0x4009bc, 0x0000014c); + break; + case 0x41: + case 0x42: /* pciid also 0x00Cx */ +// case 0x0120: //XXX (pciid) + NV_WRITE(0x400828, 0x007596ff); + NV_WRITE(0x40082c, 0x00000108); + break; + case 0x43: + NV_WRITE(0x400828, 0x0072cb77); + NV_WRITE(0x40082c, 0x00000108); + break; + case 0x44: + case 0x46: /* G72 */ + case 0x4a: + case 0x4c: /* G7x-based C51 */ + case 0x4e: + NV_WRITE(0x400860, 0); + NV_WRITE(0x400864, 0); + break; + case 0x47: /* G70 */ + case 0x49: /* G71 */ + case 0x4b: /* G73 */ + NV_WRITE(0x400828, 0x07830610); + NV_WRITE(0x40082c, 0x0000016A); + break; + default: + break; + } + + NV_WRITE(0x400b38, 0x2ffff800); + NV_WRITE(0x400b3c, 0x00006000); + + /* copy tile info from PFB */ + switch (dev_priv->chipset) { + case 0x40: /* vanilla NV40 */ + for (i=0; ichipset) { + case 0x40: + NV_WRITE(0x4009A4, NV_READ(NV04_PFB_CFG0)); + NV_WRITE(0x4009A8, NV_READ(NV04_PFB_CFG1)); + NV_WRITE(0x4069A4, NV_READ(NV04_PFB_CFG0)); + NV_WRITE(0x4069A8, NV_READ(NV04_PFB_CFG1)); + NV_WRITE(0x400820, 0); + NV_WRITE(0x400824, 0); + NV_WRITE(0x400864, vramsz); + NV_WRITE(0x400868, vramsz); + break; + default: + switch (dev_priv->chipset) { + case 0x46: + case 0x47: + case 0x49: + case 0x4b: + NV_WRITE(0x400DF0, NV_READ(NV04_PFB_CFG0)); + NV_WRITE(0x400DF4, NV_READ(NV04_PFB_CFG1)); + break; + default: + NV_WRITE(0x4009F0, NV_READ(NV04_PFB_CFG0)); + NV_WRITE(0x4009F4, NV_READ(NV04_PFB_CFG1)); + break; + } + NV_WRITE(0x4069F0, NV_READ(NV04_PFB_CFG0)); + NV_WRITE(0x4069F4, NV_READ(NV04_PFB_CFG1)); + NV_WRITE(0x400840, 0); + NV_WRITE(0x400844, 0); + NV_WRITE(0x4008A0, vramsz); + NV_WRITE(0x4008A4, vramsz); + break; + } + + /* per-context state, doesn't belong here */ + NV_WRITE(0x400B20, 0x00000000); + NV_WRITE(0x400B04, 0xFFFFFFFF); + + tmp = NV_READ(NV10_PGRAPH_SURFACE) & 0x0007ff00; + NV_WRITE(NV10_PGRAPH_SURFACE, tmp); + tmp = NV_READ(NV10_PGRAPH_SURFACE) | 0x00020100; + NV_WRITE(NV10_PGRAPH_SURFACE, tmp); + + NV_WRITE(NV03_PGRAPH_ABS_UCLIP_XMIN, 0); + NV_WRITE(NV03_PGRAPH_ABS_UCLIP_YMIN, 0); + NV_WRITE(NV03_PGRAPH_ABS_UCLIP_XMAX, 0x7fff); + NV_WRITE(NV03_PGRAPH_ABS_UCLIP_YMAX, 0x7fff); + + return 0; +} + +void nv40_graph_takedown(drm_device_t *dev) +{ +} + Index: dev/pci/drm/nv40_mc.c =================================================================== RCS file: dev/pci/drm/nv40_mc.c diff -N dev/pci/drm/nv40_mc.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/pci/drm/nv40_mc.c 24 Apr 2007 21:56:02 -0000 @@ -0,0 +1,44 @@ +#include + +#include +#include + +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv40_mc_init(drm_device_t *dev) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + uint32_t tmp; + + /* Power up everything, resetting each individual unit will + * be done later if needed. + */ + NV_WRITE(NV03_PMC_ENABLE, 0xFFFFFFFF); + + NV_WRITE(NV03_PMC_INTR_EN_0, 0); + + switch (dev_priv->chipset) { + case 0x44: + case 0x46: /* G72 */ + case 0x4e: + case 0x4c: /* C51_G7X */ + tmp = NV_READ(NV40_PFB_020C); + NV_WRITE(NV40_PMC_1700, tmp); + NV_WRITE(NV40_PMC_1704, 0); + NV_WRITE(NV40_PMC_1708, 0); + NV_WRITE(NV40_PMC_170C, tmp); + break; + default: + break; + } + + return 0; +} + +void +nv40_mc_takedown(drm_device_t *dev) +{ +} +