Deblobbed. Mark as depending on NONFREE in Kconfig. Replace all voodoo blobs with /*(DEBLOBBED)*/. From cbdc72a3e2b6c9ea95900beb7d42165b1b15365b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 22 May 2008 11:50:25 +1000 Subject: [PATCH] F8 nouveau rebase onto 2.6.25 --- drivers/char/drm/Kconfig | 7 + drivers/char/drm/Makefile | 12 + drivers/char/drm/drmP.h | 4 +- drivers/char/drm/drm_bufs.c | 6 +- drivers/char/drm/drm_irq.c | 3 +- drivers/char/drm/drm_pciids.h | 264 ++++ drivers/char/drm/nouveau_dma.c | 177 +++ drivers/char/drm/nouveau_dma.h | 98 ++ drivers/char/drm/nouveau_drm.h | 166 ++ drivers/char/drm/nouveau_drv.c | 96 ++ drivers/char/drm/nouveau_drv.h | 584 +++++++ drivers/char/drm/nouveau_fifo.c | 557 +++++++ drivers/char/drm/nouveau_ioc32.c | 72 + drivers/char/drm/nouveau_irq.c | 430 ++++++ drivers/char/drm/nouveau_mem.c | 616 ++++++++ drivers/char/drm/nouveau_notifier.c | 173 +++ drivers/char/drm/nouveau_object.c | 1148 ++++++++++++++ drivers/char/drm/nouveau_reg.h | 538 +++++++ drivers/char/drm/nouveau_sgdma.c | 311 ++++ drivers/char/drm/nouveau_state.c | 569 +++++++ drivers/char/drm/nv04_fb.c | 24 + drivers/char/drm/nv04_fifo.c | 129 ++ drivers/char/drm/nv04_graph.c | 415 +++++ drivers/char/drm/nv04_instmem.c | 160 ++ drivers/char/drm/nv04_mc.c | 23 + drivers/char/drm/nv04_timer.c | 45 + drivers/char/drm/nv10_fb.c | 26 + drivers/char/drm/nv10_fifo.c | 160 ++ drivers/char/drm/nv10_graph.c | 777 ++++++++++ drivers/char/drm/nv20_graph.c | 249 +++ drivers/char/drm/nv30_graph.c | 2911 +++++++++++++++++++++++++++++++++++ drivers/char/drm/nv40_fb.c | 56 + drivers/char/drm/nv40_fifo.c | 208 +++ drivers/char/drm/nv40_graph.c | 1906 +++++++++++++++++++++++ drivers/char/drm/nv40_mc.c | 39 + drivers/char/drm/nv50_fifo.c | 327 ++++ drivers/char/drm/nv50_graph.c | 316 ++++ drivers/char/drm/nv50_instmem.c | 320 ++++ drivers/char/drm/nv50_mc.c | 43 + 39 files changed, 13961 insertions(+), 4 deletions(-) create mode 100644 drivers/char/drm/nouveau_dma.c create mode 100644 drivers/char/drm/nouveau_dma.h create mode 100644 drivers/char/drm/nouveau_drm.h create mode 100644 drivers/char/drm/nouveau_drv.c create mode 100644 drivers/char/drm/nouveau_drv.h create mode 100644 drivers/char/drm/nouveau_fifo.c create mode 100644 drivers/char/drm/nouveau_ioc32.c create mode 100644 drivers/char/drm/nouveau_irq.c create mode 100644 drivers/char/drm/nouveau_mem.c create mode 100644 drivers/char/drm/nouveau_notifier.c create mode 100644 drivers/char/drm/nouveau_object.c create mode 100644 drivers/char/drm/nouveau_reg.h create mode 100644 drivers/char/drm/nouveau_sgdma.c create mode 100644 drivers/char/drm/nouveau_state.c create mode 100644 drivers/char/drm/nv04_fb.c create mode 100644 drivers/char/drm/nv04_fifo.c create mode 100644 drivers/char/drm/nv04_graph.c create mode 100644 drivers/char/drm/nv04_instmem.c create mode 100644 drivers/char/drm/nv04_mc.c create mode 100644 drivers/char/drm/nv04_timer.c create mode 100644 drivers/char/drm/nv10_fb.c create mode 100644 drivers/char/drm/nv10_fifo.c create mode 100644 drivers/char/drm/nv10_graph.c create mode 100644 drivers/char/drm/nv20_graph.c create mode 100644 drivers/char/drm/nv30_graph.c create mode 100644 drivers/char/drm/nv40_fb.c create mode 100644 drivers/char/drm/nv40_fifo.c create mode 100644 drivers/char/drm/nv40_graph.c create mode 100644 drivers/char/drm/nv40_mc.c create mode 100644 drivers/char/drm/nv50_fifo.c create mode 100644 drivers/char/drm/nv50_graph.c create mode 100644 drivers/char/drm/nv50_instmem.c create mode 100644 drivers/char/drm/nv50_mc.c diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig index 610d6fd..6f55e75 100644 --- a/drivers/char/drm/Kconfig +++ b/drivers/char/drm/Kconfig @@ -105,3 +105,11 @@ config DRM_SAVAGE help Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister chipset. If M is selected the module will be called savage. + +config DRM_NOUVEAU +depends on NONFREE + tristate "Nvidia video cards" + depends on DRM + help + Choose this for nvidia open source 3d driver + diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile index 1283ded..7b372eb 100644 --- a/drivers/char/drm/Makefile +++ b/drivers/char/drm/Makefile @@ -14,6 +14,16 @@ mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o i810-objs := i810_drv.o i810_dma.o i830-objs := i830_drv.o i830_dma.o i830_irq.o i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o +nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \ + nouveau_object.o nouveau_irq.o nouveau_notifier.o \ + nouveau_sgdma.o nouveau_dma.o \ + nv04_timer.o \ + nv04_mc.o nv40_mc.o nv50_mc.o \ + nv04_fb.o nv10_fb.o nv40_fb.o \ + nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \ + nv04_graph.o nv10_graph.o nv20_graph.o nv30_graph.o \ + nv40_graph.o nv50_graph.o \ + nv04_instmem.o nv50_instmem.o radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o sis-objs := sis_drv.o sis_mm.o savage-objs := savage_drv.o savage_bci.o savage_state.o @@ -25,6 +35,7 @@ radeon-objs += radeon_ioc32.o mga-objs += mga_ioc32.o r128-objs += r128_ioc32.o i915-objs += i915_ioc32.o +nouveau-objs += nouveau_ioc32.o endif obj-$(CONFIG_DRM) += drm.o @@ -35,6 +46,7 @@ obj-$(CONFIG_DRM_MGA) += mga.o obj-$(CONFIG_DRM_I810) += i810.o obj-$(CONFIG_DRM_I830) += i830.o obj-$(CONFIG_DRM_I915) += i915.o +obj-$(CONFIG_DRM_NOUVEAU) += nouveau.o obj-$(CONFIG_DRM_SIS) += sis.o obj-$(CONFIG_DRM_SAVAGE)+= savage.o obj-$(CONFIG_DRM_VIA) +=via.o diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 8ea9dd1..49ee12e 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -973,7 +973,8 @@ extern unsigned long drm_get_resource_start(struct drm_device *dev, unsigned int resource); extern unsigned long drm_get_resource_len(struct drm_device *dev, unsigned int resource); - +struct drm_map_list *drm_find_matching_map(struct drm_device *dev, + drm_local_map_t *map); /* DMA support (drm_dma.h) */ extern int drm_dma_setup(struct drm_device *dev); extern void drm_dma_takedown(struct drm_device *dev); @@ -985,6 +986,7 @@ extern void drm_core_reclaim_buffers(struct drm_device *dev, extern int drm_control(struct drm_device *dev, void *data, struct drm_file *file_priv); extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS); +extern int drm_irq_install(struct drm_device * dev); extern int drm_irq_uninstall(struct drm_device *dev); extern void drm_driver_irq_preinstall(struct drm_device *dev); extern void drm_driver_irq_postinstall(struct drm_device *dev); diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index bde64b8..3a0545c 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c @@ -49,8 +49,8 @@ unsigned long drm_get_resource_len(struct drm_device *dev, unsigned int resource EXPORT_SYMBOL(drm_get_resource_len); -static struct drm_map_list *drm_find_matching_map(struct drm_device *dev, - drm_local_map_t *map) +struct drm_map_list *drm_find_matching_map(struct drm_device *dev, + drm_local_map_t *map) { struct drm_map_list *entry; list_for_each_entry(entry, &dev->maplist, head) { @@ -63,6 +63,7 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev, return NULL; } +EXPORT_SYMBOL(drm_find_matching_map); static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash, unsigned long user_token, int hashed_handle) diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c index 089c015..29206c7 100644 --- a/drivers/char/drm/drm_irq.c +++ b/drivers/char/drm/drm_irq.c @@ -81,7 +81,7 @@ int drm_irq_by_busid(struct drm_device *dev, void *data, * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions * before and after the installation. */ -static int drm_irq_install(struct drm_device * dev) +int drm_irq_install(struct drm_device * dev) { int ret; unsigned long sh_flags = 0; @@ -141,6 +141,7 @@ static int drm_irq_install(struct drm_device * dev) return 0; } +EXPORT_SYMBOL(drm_irq_install); /** * Uninstall the IRQ handler. diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index a6a499f..4f253ab 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h @@ -412,3 +412,267 @@ {0x8086, 0x2a12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x8086, 0x2a42, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0, 0, 0} + + +#define nouveau_PCI_IDS \ + {0x10de, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_03}, \ + {0x10de, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_03}, \ + {0x10de, 0x0010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_03}, \ + {0x10de, 0x0020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_04}, \ + {0x10de, 0x0028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_04}, \ + {0x10de, 0x0029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_04}, \ + {0x10de, 0x002a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_04}, \ + {0x10de, 0x002b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_04}, \ + {0x10de, 0x002c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_04}, \ + {0x10de, 0x002d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_04}, \ + {0x10de, 0x002e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_04}, \ + {0x10de, 0x002f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_04}, \ + {0x10de, 0x0040, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0041, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0042, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0044, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0045, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0046, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0047, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0048, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0049, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x004d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x004e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0090, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0091, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0092, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0093, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0095, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0098, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0099, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x009d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00a0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_04}, \ + {0x10de, 0x00c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00c1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00c2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00c3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00c8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00c9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00cc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00cd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00ce, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00f0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00f1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00f2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00f3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00f4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00f5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00f6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00f8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00f9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x00fa, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x00fb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x00fc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x00fd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x00fe, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x00ff, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x0100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_10}, \ + {0x10de, 0x0101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_10}, \ + {0x10de, 0x0103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_10}, \ + {0x10de, 0x0110, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_11}, \ + {0x10de, 0x0111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_11}, \ + {0x10de, 0x0112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_11}, \ + {0x10de, 0x0113, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_11}, \ + {0x10de, 0x0140, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0141, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0142, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0143, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x014a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x014c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x014d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x014e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x014f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_15}, \ + {0x10de, 0x0151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_15}, \ + {0x10de, 0x0152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_15}, \ + {0x10de, 0x0153, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_15}, \ + {0x10de, 0x0160, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x0161, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x0162, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x0163, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x0164, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x0165, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x0166, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x0167, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x0168, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x0169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x0170, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x0171, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x0172, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x0173, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x0174, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x0175, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x0176, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x0177, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x0178, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x0179, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x017a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x017b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x017c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x017d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x0181, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x0182, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x0183, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x0185, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x0186, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x0187, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x0188, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x018a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x018b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x018c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x018d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17}, \ + {0x10de, 0x0191, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_50}, \ + {0x10de, 0x0193, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_50}, \ + {0x10de, 0x0194, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_50}, \ + {0x10de, 0x019d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_50}, \ + {0x10de, 0x019e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_50}, \ + {0x10de, 0x01a0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_11|NV_NFORCE}, \ + {0x10de, 0x01d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x01d3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x01d6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x01d7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x01d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x01d9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x01da, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x01db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x01dc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x01dd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x01de, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x01df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x01f0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_17|NV_NFORCE2}, \ + {0x10de, 0x0200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_20}, \ + {0x10de, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_20}, \ + {0x10de, 0x0202, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_20}, \ + {0x10de, 0x0203, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_20}, \ + {0x10de, 0x0211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0212, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0215, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0218, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0221, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x0222, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x0244, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x0247, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x0250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_25}, \ + {0x10de, 0x0251, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_25}, \ + {0x10de, 0x0252, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_25}, \ + {0x10de, 0x0253, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_25}, \ + {0x10de, 0x0258, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_25}, \ + {0x10de, 0x0259, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_25}, \ + {0x10de, 0x025b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_25}, \ + {0x10de, 0x0280, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_25}, \ + {0x10de, 0x0281, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_25}, \ + {0x10de, 0x0282, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_25}, \ + {0x10de, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_25}, \ + {0x10de, 0x0288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_25}, \ + {0x10de, 0x0289, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_25}, \ + {0x10de, 0x028c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_25}, \ + {0x10de, 0x0290, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0291, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0292, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0298, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0299, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x029a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x029b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x029c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x029d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x029e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x029f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x02a0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_20}, \ + {0x10de, 0x02e1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0308, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0309, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0313, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0314, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0316, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0317, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x031a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x031b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x031d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x031e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x031f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_34}, \ + {0x10de, 0x0321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_34}, \ + {0x10de, 0x0322, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_34}, \ + {0x10de, 0x0323, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_34}, \ + {0x10de, 0x0324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_34}, \ + {0x10de, 0x0325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_34}, \ + {0x10de, 0x0326, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_34}, \ + {0x10de, 0x0327, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_34}, \ + {0x10de, 0x0328, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_34}, \ + {0x10de, 0x0329, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_34}, \ + {0x10de, 0x032a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_34}, \ + {0x10de, 0x032b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_34}, \ + {0x10de, 0x032c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_34}, \ + {0x10de, 0x032d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_34}, \ + {0x10de, 0x032f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_34}, \ + {0x10de, 0x0330, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0331, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0332, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0333, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0334, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0338, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x033f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0341, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0342, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0343, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0344, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0345, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0347, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0348, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0349, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x034b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x034c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x034e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x034f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_30}, \ + {0x10de, 0x0391, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0392, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0393, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0394, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0395, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0397, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0398, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x0399, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x039a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x039b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x039c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x039e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_40}, \ + {0x10de, 0x03d0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x03d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x03d2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x03d5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_44}, \ + {0x10de, 0x0400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_50}, \ + {0x10de, 0x0402, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_50}, \ + {0x10de, 0x0421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_50}, \ + {0x10de, 0x0422, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_50}, \ + {0x10de, 0x0423, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_50}, \ + {0x12d2, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_03}, \ + {0x12d2, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_03}, \ + {0x12d2, 0x0018, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_03}, \ + {0x12d2, 0x0019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_03}, \ + {0x12d2, 0x0020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_04}, \ + {0x12d2, 0x0028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_04}, \ + {0x12d2, 0x0029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_04}, \ + {0x12d2, 0x002c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_04}, \ + {0x12d2, 0x00a0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NV_04}, \ + {0, 0, 0} + diff --git a/drivers/char/drm/nouveau_dma.c b/drivers/char/drm/nouveau_dma.c new file mode 100644 index 0000000..ab502e6 --- /dev/null +++ b/drivers/char/drm/nouveau_dma.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2007 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_dma.h" + +#define SKIPS 8 + +int +nouveau_dma_channel_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm_channel *dchan = &dev_priv->channel; + struct nouveau_gpuobj *gpuobj = NULL; + struct mem_block *pushbuf; + int grclass, ret, i; + + DRM_DEBUG("\n"); + + pushbuf = nouveau_mem_alloc(dev, 0, 0x8000, + NOUVEAU_MEM_FB | NOUVEAU_MEM_MAPPED, + (struct drm_file *)-2); + if (!pushbuf) { + DRM_ERROR("Failed to allocate DMA push buffer\n"); + return -ENOMEM; + } + + /* Allocate channel */ + ret = nouveau_fifo_alloc(dev, &dchan->chan, (struct drm_file *)-2, + pushbuf, NvDmaFB, NvDmaTT); + if (ret) { + DRM_ERROR("Error allocating GPU channel: %d\n", ret); + return ret; + } + DRM_DEBUG("Using FIFO channel %d\n", dchan->chan->id); + + /* Map push buffer */ + drm_core_ioremap(dchan->chan->pushbuf_mem->map, dev); + if (!dchan->chan->pushbuf_mem->map->handle) { + DRM_ERROR("Failed to ioremap push buffer\n"); + return -EINVAL; + } + dchan->pushbuf = (void*)dchan->chan->pushbuf_mem->map->handle; + + /* Initialise DMA vars */ + dchan->max = (dchan->chan->pushbuf_mem->size >> 2) - 2; + dchan->put = dchan->chan->pushbuf_base >> 2; + dchan->cur = dchan->put; + dchan->free = dchan->max - dchan->cur; + + /* Insert NOPS for SKIPS */ + dchan->free -= SKIPS; + dchan->push_free = SKIPS; + for (i=0; ichan, NvNotify0, 1, + &dchan->notify0_offset))) { + DRM_ERROR("Error allocating NvNotify0: %d\n", ret); + return ret; + } + + /* We use NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */ + if (dev_priv->card_type < NV_50) grclass = NV_MEMORY_TO_MEMORY_FORMAT; + else grclass = NV50_MEMORY_TO_MEMORY_FORMAT; + if ((ret = nouveau_gpuobj_gr_new(dchan->chan, grclass, &gpuobj))) { + DRM_ERROR("Error creating NvM2MF: %d\n", ret); + return ret; + } + + if ((ret = nouveau_gpuobj_ref_add(dev, dchan->chan, NvM2MF, + gpuobj, NULL))) { + DRM_ERROR("Error referencing NvM2MF: %d\n", ret); + return ret; + } + dchan->m2mf_dma_source = NvDmaFB; + dchan->m2mf_dma_destin = NvDmaFB; + + BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1); + OUT_RING (NvM2MF); + BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_NOTIFY, 1); + OUT_RING (NvNotify0); + BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_SOURCE, 2); + OUT_RING (dchan->m2mf_dma_source); + OUT_RING (dchan->m2mf_dma_destin); + FIRE_RING(); + + return 0; +} + +void +nouveau_dma_channel_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm_channel *dchan = &dev_priv->channel; + + DRM_DEBUG("\n"); + + if (dchan->chan) { + nouveau_fifo_free(dchan->chan); + dchan->chan = NULL; + } +} + +#define RING_SKIPS 8 + +#define READ_GET() ((NV_READ(NV03_FIFO_REGS_DMAGET(dchan->chan->id)) - \ + dchan->chan->pushbuf_base) >> 2) +#define WRITE_PUT(val) do { \ + NV_WRITE(NV03_FIFO_REGS_DMAPUT(dchan->chan->id), \ + ((val) << 2) + dchan->chan->pushbuf_base); \ +} while(0) + +int +nouveau_dma_wait(struct drm_device *dev, int size) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm_channel *dchan = &dev_priv->channel; + uint32_t get; + + while (dchan->free < size) { + get = READ_GET(); + + if (dchan->put >= get) { + dchan->free = dchan->max - dchan->cur; + + if (dchan->free < size) { + dchan->push_free = 1; + OUT_RING(0x20000000|dchan->chan->pushbuf_base); + if (get <= RING_SKIPS) { + /*corner case - will be idle*/ + if (dchan->put <= RING_SKIPS) + WRITE_PUT(RING_SKIPS + 1); + + do { + get = READ_GET(); + } while (get <= RING_SKIPS); + } + + WRITE_PUT(RING_SKIPS); + dchan->cur = dchan->put = RING_SKIPS; + dchan->free = get - (RING_SKIPS + 1); + } + } else { + dchan->free = get - dchan->cur - 1; + } + } + + return 0; +} + diff --git a/drivers/char/drm/nouveau_dma.h b/drivers/char/drm/nouveau_dma.h new file mode 100644 index 0000000..5e51c1c --- /dev/null +++ b/drivers/char/drm/nouveau_dma.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2007 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. + * + */ + +#ifndef __NOUVEAU_DMA_H__ +#define __NOUVEAU_DMA_H__ + +typedef enum { + NvSubM2MF = 0, +} nouveau_subchannel_id_t; + +typedef enum { + NvM2MF = 0x80039001, + NvDmaFB = 0x8003d001, + NvDmaTT = 0x8003d002, + NvNotify0 = 0x8003d003 +} nouveau_object_handle_t; + +#define NV_MEMORY_TO_MEMORY_FORMAT 0x00000039 +#define NV_MEMORY_TO_MEMORY_FORMAT_NAME 0x00000000 +#define NV_MEMORY_TO_MEMORY_FORMAT_SET_REF 0x00000050 +#define NV_MEMORY_TO_MEMORY_FORMAT_NOP 0x00000100 +#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY 0x00000104 +#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY_STYLE_WRITE 0x00000000 +#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY_STYLE_WRITE_LE_AWAKEN 0x00000001 +#define NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_NOTIFY 0x00000180 +#define NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_SOURCE 0x00000184 +#define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN 0x0000030c + +#define NV50_MEMORY_TO_MEMORY_FORMAT 0x00005039 +#define NV50_MEMORY_TO_MEMORY_FORMAT_UNK200 0x00000200 +#define NV50_MEMORY_TO_MEMORY_FORMAT_UNK21C 0x0000021c +#define NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH 0x00000238 +#define NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_OUT_HIGH 0x0000023c + +#define BEGIN_RING(subc, mthd, cnt) do { \ + int push_size = (cnt) + 1; \ + if (dchan->push_free) { \ + DRM_ERROR("prior packet incomplete: %d\n", dchan->push_free); \ + break; \ + } \ + if (dchan->free < push_size) { \ + if (nouveau_dma_wait(dev, push_size)) { \ + DRM_ERROR("FIFO timeout\n"); \ + break; \ + } \ + } \ + dchan->free -= push_size; \ + dchan->push_free = push_size; \ + OUT_RING(((cnt)<<18) | ((subc)<<15) | mthd); \ +} while(0) + +#define OUT_RING(data) do { \ + if (dchan->push_free == 0) { \ + DRM_ERROR("no space left in packet\n"); \ + break; \ + } \ + dchan->pushbuf[dchan->cur++] = (data); \ + dchan->push_free--; \ +} while(0) + +#define FIRE_RING() do { \ + if (dchan->push_free) { \ + DRM_ERROR("packet incomplete: %d\n", dchan->push_free); \ + break; \ + } \ + if (dchan->cur != dchan->put) { \ + DRM_MEMORYBARRIER(); \ + dchan->put = dchan->cur; \ + NV_WRITE(NV03_FIFO_REGS_DMAPUT(dchan->chan->id), \ + (dchan->put<<2)); \ + } \ +} while(0) + +#endif + diff --git a/drivers/char/drm/nouveau_drm.h b/drivers/char/drm/nouveau_drm.h new file mode 100644 index 0000000..bfc9bd4 --- /dev/null +++ b/drivers/char/drm/nouveau_drm.h @@ -0,0 +1,166 @@ +/* + * 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 10 + +struct drm_nouveau_channel_alloc { + uint32_t fb_ctxdma_handle; + uint32_t tt_ctxdma_handle; + + 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; + /* Notifier memory */ + drm_handle_t notifier; + int notifier_size; +}; + +struct drm_nouveau_channel_free { + int channel; +}; + +struct drm_nouveau_grobj_alloc { + int channel; + uint32_t handle; + int class; +}; + +#define NOUVEAU_MEM_ACCESS_RO 1 +#define NOUVEAU_MEM_ACCESS_WO 2 +#define NOUVEAU_MEM_ACCESS_RW 3 +struct drm_nouveau_notifierobj_alloc { + int channel; + uint32_t handle; + int count; + + uint32_t offset; +}; + +struct drm_nouveau_gpuobj_free { + int channel; + uint32_t handle; +}; + +#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_PCI 0x00000010 +#define NOUVEAU_MEM_PCI_ACCEPTABLE 0x00000020 +#define NOUVEAU_MEM_PINNED 0x00000040 +#define NOUVEAU_MEM_USER_BACKED 0x00000080 +#define NOUVEAU_MEM_MAPPED 0x00000100 +#define NOUVEAU_MEM_INSTANCE 0x00000200 /* internal */ +#define NOUVEAU_MEM_NOTIFIER 0x00000400 /* internal */ + +struct drm_nouveau_mem_alloc { + int flags; + int alignment; + uint64_t size; // in bytes + uint64_t offset; + drm_handle_t map_handle; +}; + +struct drm_nouveau_mem_free { + uint64_t offset; + int flags; +}; + +/* 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 +#define NOUVEAU_GETPARAM_PCI_PHYSICAL 10 +#define NOUVEAU_GETPARAM_CHIPSET_ID 11 +struct drm_nouveau_getparam { + uint64_t param; + uint64_t value; +}; + +#define NOUVEAU_SETPARAM_CMDBUF_LOCATION 1 +#define NOUVEAU_SETPARAM_CMDBUF_SIZE 2 +struct drm_nouveau_setparam { + uint64_t param; + uint64_t value; +}; + +enum nouveau_card_type { + NV_UNKNOWN =0, + NV_01 =1, + NV_03 =3, + NV_04 =4, + NV_05 =5, + NV_10 =10, + NV_11 =11, + NV_15 =11, + NV_17 =17, + 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 + +struct drm_nouveau_sarea { + /* the cliprects */ + struct drm_clip_rect boxes[NOUVEAU_MAX_SAREA_CLIPRECTS]; + unsigned int nbox; +}; + +#define DRM_NOUVEAU_CARD_INIT 0x00 +#define DRM_NOUVEAU_GETPARAM 0x01 +#define DRM_NOUVEAU_SETPARAM 0x02 +#define DRM_NOUVEAU_CHANNEL_ALLOC 0x03 +#define DRM_NOUVEAU_CHANNEL_FREE 0x04 +#define DRM_NOUVEAU_GROBJ_ALLOC 0x05 +#define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x06 +#define DRM_NOUVEAU_GPUOBJ_FREE 0x07 +#define DRM_NOUVEAU_MEM_ALLOC 0x08 +#define DRM_NOUVEAU_MEM_FREE 0x09 + +#endif /* __NOUVEAU_DRM_H__ */ + diff --git a/drivers/char/drm/nouveau_drv.c b/drivers/char/drm/nouveau_drv.c new file mode 100644 index 0000000..387e3d6 --- /dev/null +++ b/drivers/char/drm/nouveau_drv.c @@ -0,0 +1,96 @@ +/* + * 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 "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +#include "drm_pciids.h" + +static struct pci_device_id pciidlist[] = { + nouveau_PCI_IDS +}; + +extern struct drm_ioctl_desc nouveau_ioctls[]; +extern int nouveau_max_ioctl; + +static struct drm_driver driver = { + .driver_features = + DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG | + DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, + .load = nouveau_load, + .firstopen = nouveau_firstopen, + .lastclose = nouveau_lastclose, + .unload = nouveau_unload, + .preclose = nouveau_preclose, + .irq_preinstall = nouveau_irq_preinstall, + .irq_postinstall = nouveau_irq_postinstall, + .irq_uninstall = nouveau_irq_uninstall, + .irq_handler = nouveau_irq_handler, + .reclaim_buffers = drm_core_reclaim_buffers, + .get_map_ofs = drm_core_get_map_ofs, + .get_reg_ofs = drm_core_get_reg_ofs, + .ioctls = nouveau_ioctls, + .fops = { + .owner = THIS_MODULE, + .open = drm_open, + .release = drm_release, + .ioctl = drm_ioctl, + .mmap = drm_mmap, + .poll = drm_poll, + .fasync = drm_fasync, +#ifdef CONFIG_COMPAT + .compat_ioctl = nouveau_compat_ioctl, +#endif + }, + .pci_driver = { + .name = DRIVER_NAME, + .id_table = pciidlist, + }, + + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCHLEVEL, +}; + +static int __init nouveau_init(void) +{ + driver.num_ioctls = nouveau_max_ioctl; + return drm_init(&driver); +} + +static void __exit nouveau_exit(void) +{ + drm_exit(&driver); +} + +module_init(nouveau_init); +module_exit(nouveau_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/char/drm/nouveau_drv.h b/drivers/char/drm/nouveau_drv.h new file mode 100644 index 0000000..2a16d3b --- /dev/null +++ b/drivers/char/drm/nouveau_drv.h @@ -0,0 +1,584 @@ +/* + * 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 10 + +#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; + struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */ + int flags; + drm_local_map_t *map; + drm_handle_t map_handle; +}; + +enum nouveau_flags { + NV_NFORCE =0x10000000, + NV_NFORCE2 =0x20000000 +}; + +#define NVOBJ_ENGINE_SW 0 +#define NVOBJ_ENGINE_GR 1 +#define NVOBJ_ENGINE_INT 0xdeadbeef + +#define NVOBJ_FLAG_ALLOW_NO_REFS (1 << 0) +#define NVOBJ_FLAG_ZERO_ALLOC (1 << 1) +#define NVOBJ_FLAG_ZERO_FREE (1 << 2) +#define NVOBJ_FLAG_FAKE (1 << 3) +struct nouveau_gpuobj { + struct list_head list; + + int im_channel; + struct mem_block *im_pramin; + struct mem_block *im_backing; + int im_bound; + + uint32_t flags; + int refcount; + + uint32_t engine; + uint32_t class; + + void (*dtor)(struct drm_device *, struct nouveau_gpuobj *); + void *priv; +}; + +struct nouveau_gpuobj_ref { + struct list_head list; + + struct nouveau_gpuobj *gpuobj; + uint32_t instance; + + int channel; + int handle; +}; + +struct nouveau_channel +{ + struct drm_device *dev; + int id; + + /* owner of this fifo */ + struct drm_file *file_priv; + /* mapping of the fifo itself */ + drm_local_map_t *map; + /* mapping of the regs controling the fifo */ + drm_local_map_t *regs; + + /* DMA push buffer */ + struct nouveau_gpuobj_ref *pushbuf; + struct mem_block *pushbuf_mem; + uint32_t pushbuf_base; + + /* Notifier memory */ + struct mem_block *notifier_block; + struct mem_block *notifier_heap; + drm_local_map_t *notifier_map; + + /* PFIFO context */ + struct nouveau_gpuobj_ref *ramfc; + + /* PGRAPH context */ + struct nouveau_gpuobj_ref *ramin_grctx; + uint32_t pgraph_ctx [340]; /* XXX dynamic alloc ? */ + + /* NV50 VM */ + struct nouveau_gpuobj *vm_pd; + struct nouveau_gpuobj_ref *vm_gart_pt; + + /* Objects */ + struct nouveau_gpuobj_ref *ramin; /* Private instmem */ + struct mem_block *ramin_heap; /* Private PRAMIN heap */ + struct nouveau_gpuobj_ref *ramht; /* Hash table */ + struct list_head ramht_refs; /* Objects referenced by RAMHT */ +}; + +struct nouveau_drm_channel { + struct nouveau_channel *chan; + + /* DMA state */ + int max, put, cur, free; + int push_free; + volatile uint32_t *pushbuf; + + /* Notifiers */ + uint32_t notify0_offset; + + /* Buffer moves */ + uint32_t m2mf_dma_source; + uint32_t m2mf_dma_destin; +}; + +struct nouveau_config { + struct { + int location; + int size; + } cmdbuf; +}; + +struct nouveau_instmem_engine { + void *priv; + + int (*init)(struct drm_device *dev); + void (*takedown)(struct drm_device *dev); + + int (*populate)(struct drm_device *, struct nouveau_gpuobj *, + uint32_t *size); + void (*clear)(struct drm_device *, struct nouveau_gpuobj *); + int (*bind)(struct drm_device *, struct nouveau_gpuobj *); + int (*unbind)(struct drm_device *, struct nouveau_gpuobj *); +}; + +struct nouveau_mc_engine { + int (*init)(struct drm_device *dev); + void (*takedown)(struct drm_device *dev); +}; + +struct nouveau_timer_engine { + int (*init)(struct drm_device *dev); + void (*takedown)(struct drm_device *dev); + uint64_t (*read)(struct drm_device *dev); +}; + +struct nouveau_fb_engine { + int (*init)(struct drm_device *dev); + void (*takedown)(struct drm_device *dev); +}; + +struct nouveau_fifo_engine { + void *priv; + + int (*init)(struct drm_device *); + void (*takedown)(struct drm_device *); + + int (*create_context)(struct nouveau_channel *); + void (*destroy_context)(struct nouveau_channel *); + int (*load_context)(struct nouveau_channel *); + int (*save_context)(struct nouveau_channel *); +}; + +struct nouveau_pgraph_engine { + int (*init)(struct drm_device *); + void (*takedown)(struct drm_device *); + + int (*create_context)(struct nouveau_channel *); + void (*destroy_context)(struct nouveau_channel *); + int (*load_context)(struct nouveau_channel *); + int (*save_context)(struct nouveau_channel *); +}; + +struct nouveau_engine { + struct nouveau_instmem_engine instmem; + struct nouveau_mc_engine mc; + struct nouveau_timer_engine timer; + struct nouveau_fb_engine fb; + struct nouveau_pgraph_engine graph; + struct nouveau_fifo_engine fifo; +}; + +struct drm_nouveau_private { + enum { + NOUVEAU_CARD_INIT_DOWN, + NOUVEAU_CARD_INIT_DONE, + NOUVEAU_CARD_INIT_FAILED + } init_state; + + /* 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_channel *fifos[NV_MAX_FIFO_NUMBER]; + + struct nouveau_engine Engine; + struct nouveau_drm_channel channel; + + /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */ + struct nouveau_gpuobj *ramht; + uint32_t ramin_rsvd_vram; + 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; + + struct { + enum { + NOUVEAU_GART_NONE = 0, + NOUVEAU_GART_AGP, + NOUVEAU_GART_SGDMA + } type; + uint64_t aper_base; + uint64_t aper_size; + + struct nouveau_gpuobj *sg_ctxdma; + struct page *sg_dummy_page; + dma_addr_t sg_dummy_bus; + + /* nottm hack */ + struct drm_ttm_backend *sg_be; + unsigned long sg_handle; + } gart_info; + + /* 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; + struct mem_block *pci_heap; + + /* context table pointed to be NV_PGRAPH_CHANNEL_CTX_TABLE (0x400780) */ + uint32_t ctx_table_size; + struct nouveau_gpuobj_ref *ctx_table; + + struct nouveau_config config; + + struct list_head gpuobj_list; +}; + +#define NOUVEAU_CHECK_INITIALISED_WITH_RETURN do { \ + struct drm_nouveau_private *nv = dev->dev_private; \ + if (nv->init_state != NOUVEAU_CARD_INIT_DONE) { \ + DRM_ERROR("called without init\n"); \ + return -EINVAL; \ + } \ +} while(0) + +#define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id,cl,ch) do { \ + struct drm_nouveau_private *nv = dev->dev_private; \ + if (!nouveau_fifo_owner(dev, (cl), (id))) { \ + DRM_ERROR("pid %d doesn't own channel %d\n", \ + DRM_CURRENTPID, (id)); \ + return -EPERM; \ + } \ + (ch) = nv->fifos[(id)]; \ +} while(0) + +/* nouveau_state.c */ +extern void nouveau_preclose(struct drm_device *dev, struct drm_file *); +extern int nouveau_load(struct drm_device *, unsigned long flags); +extern int nouveau_firstopen(struct drm_device *); +extern void nouveau_lastclose(struct drm_device *); +extern int nouveau_unload(struct drm_device *); +extern int nouveau_ioctl_getparam(struct drm_device *, void *data, + struct drm_file *); +extern int nouveau_ioctl_setparam(struct drm_device *, void *data, + struct drm_file *); +extern void nouveau_wait_for_idle(struct drm_device *); +extern int nouveau_card_init(struct drm_device *); +extern int nouveau_ioctl_card_init(struct drm_device *, void *data, + struct drm_file *); + +/* nouveau_mem.c */ +extern int nouveau_mem_init_heap(struct mem_block **, uint64_t start, + uint64_t size); +extern struct mem_block *nouveau_mem_alloc_block(struct mem_block *, + uint64_t size, int align2, + struct drm_file *); +extern void nouveau_mem_takedown(struct mem_block **heap); +extern void nouveau_mem_free_block(struct mem_block *); +extern uint64_t nouveau_mem_fb_amount(struct drm_device *); +extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap); +extern int nouveau_ioctl_mem_alloc(struct drm_device *, void *data, + struct drm_file *); +extern int nouveau_ioctl_mem_free(struct drm_device *, void *data, + struct drm_file *); +extern struct mem_block* nouveau_mem_alloc(struct drm_device *, + int alignment, uint64_t size, + int flags, struct drm_file *); +extern void nouveau_mem_free(struct drm_device *dev, struct mem_block*); +extern int nouveau_mem_init(struct drm_device *); +extern void nouveau_mem_close(struct drm_device *); + +/* nouveau_notifier.c */ +extern int nouveau_notifier_init_channel(struct nouveau_channel *); +extern void nouveau_notifier_takedown_channel(struct nouveau_channel *); +extern int nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle, + int cout, uint32_t *offset); +extern int nouveau_ioctl_notifier_alloc(struct drm_device *, void *data, + struct drm_file *); +extern int nouveau_ioctl_notifier_free(struct drm_device *, void *data, + struct drm_file *); + +/* nouveau_fifo.c */ +extern int nouveau_fifo_init(struct drm_device *); +extern int nouveau_fifo_number(struct drm_device *); +extern int nouveau_fifo_ctx_size(struct drm_device *); +extern void nouveau_fifo_cleanup(struct drm_device *, struct drm_file *); +extern int nouveau_fifo_owner(struct drm_device *, struct drm_file *, + int channel); +extern int nouveau_fifo_alloc(struct drm_device *dev, + struct nouveau_channel **chan, + struct drm_file *file_priv, + struct mem_block *pushbuf, + uint32_t fb_ctxdma, uint32_t tt_ctxdma); +extern void nouveau_fifo_free(struct nouveau_channel *); + +/* nouveau_object.c */ +extern int nouveau_gpuobj_early_init(struct drm_device *); +extern int nouveau_gpuobj_init(struct drm_device *); +extern void nouveau_gpuobj_takedown(struct drm_device *); +extern void nouveau_gpuobj_late_takedown(struct drm_device *); +extern int nouveau_gpuobj_channel_init(struct nouveau_channel *, + uint32_t vram_h, uint32_t tt_h); +extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *); +extern int nouveau_gpuobj_new(struct drm_device *, struct nouveau_channel *, + int size, int align, uint32_t flags, + struct nouveau_gpuobj **); +extern int nouveau_gpuobj_del(struct drm_device *, struct nouveau_gpuobj **); +extern int nouveau_gpuobj_ref_add(struct drm_device *, struct nouveau_channel *, + uint32_t handle, struct nouveau_gpuobj *, + struct nouveau_gpuobj_ref **); +extern int nouveau_gpuobj_ref_del(struct drm_device *, + struct nouveau_gpuobj_ref **); +extern int nouveau_gpuobj_ref_find(struct nouveau_channel *, uint32_t handle, + struct nouveau_gpuobj_ref **ref_ret); +extern int nouveau_gpuobj_new_ref(struct drm_device *, + struct nouveau_channel *alloc_chan, + struct nouveau_channel *ref_chan, + uint32_t handle, int size, int align, + uint32_t flags, struct nouveau_gpuobj_ref **); +extern int nouveau_gpuobj_new_fake(struct drm_device *, + uint32_t p_offset, uint32_t b_offset, + uint32_t size, uint32_t flags, + struct nouveau_gpuobj **, + struct nouveau_gpuobj_ref**); +extern int nouveau_gpuobj_dma_new(struct nouveau_channel *, int class, + uint64_t offset, uint64_t size, int access, + int target, struct nouveau_gpuobj **); +extern int nouveau_gpuobj_gart_dma_new(struct nouveau_channel *, + uint64_t offset, uint64_t size, + int access, struct nouveau_gpuobj **, + uint32_t *o_ret); +extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class, + struct nouveau_gpuobj **); +extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data, + struct drm_file *); +extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data, + struct drm_file *); + +/* nouveau_irq.c */ +extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS); +extern void nouveau_irq_preinstall(struct drm_device *); +extern void nouveau_irq_postinstall(struct drm_device *); +extern void nouveau_irq_uninstall(struct drm_device *); + +/* nouveau_sgdma.c */ +extern int nouveau_sgdma_init(struct drm_device *); +extern void nouveau_sgdma_takedown(struct drm_device *); +extern int nouveau_sgdma_get_page(struct drm_device *, uint32_t offset, + uint32_t *page); +//extern struct ^ *nouveau_sgdma_init_ttm(struct drm_device *); +extern int nouveau_sgdma_nottm_hack_init(struct drm_device *); +extern void nouveau_sgdma_nottm_hack_takedown(struct drm_device *); + +/* nouveau_dma.c */ +extern int nouveau_dma_channel_init(struct drm_device *); +extern void nouveau_dma_channel_takedown(struct drm_device *); +extern int nouveau_dma_wait(struct drm_device *, int size); + +/* nv04_fb.c */ +extern int nv04_fb_init(struct drm_device *); +extern void nv04_fb_takedown(struct drm_device *); + +/* nv10_fb.c */ +extern int nv10_fb_init(struct drm_device *); +extern void nv10_fb_takedown(struct drm_device *); + +/* nv40_fb.c */ +extern int nv40_fb_init(struct drm_device *); +extern void nv40_fb_takedown(struct drm_device *); + +/* nv04_fifo.c */ +extern int nv04_fifo_create_context(struct nouveau_channel *); +extern void nv04_fifo_destroy_context(struct nouveau_channel *); +extern int nv04_fifo_load_context(struct nouveau_channel *); +extern int nv04_fifo_save_context(struct nouveau_channel *); + +/* nv10_fifo.c */ +extern int nv10_fifo_create_context(struct nouveau_channel *); +extern void nv10_fifo_destroy_context(struct nouveau_channel *); +extern int nv10_fifo_load_context(struct nouveau_channel *); +extern int nv10_fifo_save_context(struct nouveau_channel *); + +/* nv40_fifo.c */ +extern int nv40_fifo_init(struct drm_device *); +extern int nv40_fifo_create_context(struct nouveau_channel *); +extern void nv40_fifo_destroy_context(struct nouveau_channel *); +extern int nv40_fifo_load_context(struct nouveau_channel *); +extern int nv40_fifo_save_context(struct nouveau_channel *); + +/* nv50_fifo.c */ +extern int nv50_fifo_init(struct drm_device *); +extern void nv50_fifo_takedown(struct drm_device *); +extern int nv50_fifo_create_context(struct nouveau_channel *); +extern void nv50_fifo_destroy_context(struct nouveau_channel *); +extern int nv50_fifo_load_context(struct nouveau_channel *); +extern int nv50_fifo_save_context(struct nouveau_channel *); + +/* nv04_graph.c */ +extern void nouveau_nv04_context_switch(struct drm_device *); +extern int nv04_graph_init(struct drm_device *); +extern void nv04_graph_takedown(struct drm_device *); +extern int nv04_graph_create_context(struct nouveau_channel *); +extern void nv04_graph_destroy_context(struct nouveau_channel *); +extern int nv04_graph_load_context(struct nouveau_channel *); +extern int nv04_graph_save_context(struct nouveau_channel *); + +/* nv10_graph.c */ +extern void nouveau_nv10_context_switch(struct drm_device *); +extern int nv10_graph_init(struct drm_device *); +extern void nv10_graph_takedown(struct drm_device *); +extern int nv10_graph_create_context(struct nouveau_channel *); +extern void nv10_graph_destroy_context(struct nouveau_channel *); +extern int nv10_graph_load_context(struct nouveau_channel *); +extern int nv10_graph_save_context(struct nouveau_channel *); + +/* nv20_graph.c */ +extern void nouveau_nv20_context_switch(struct drm_device *); +extern int nv20_graph_init(struct drm_device *); +extern void nv20_graph_takedown(struct drm_device *); +extern int nv20_graph_create_context(struct nouveau_channel *); +extern void nv20_graph_destroy_context(struct nouveau_channel *); +extern int nv20_graph_load_context(struct nouveau_channel *); +extern int nv20_graph_save_context(struct nouveau_channel *); + +/* nv30_graph.c */ +extern int nv30_graph_init(struct drm_device *); +extern void nv30_graph_takedown(struct drm_device *); +extern int nv30_graph_create_context(struct nouveau_channel *); +extern void nv30_graph_destroy_context(struct nouveau_channel *); +extern int nv30_graph_load_context(struct nouveau_channel *); +extern int nv30_graph_save_context(struct nouveau_channel *); + +/* nv40_graph.c */ +extern int nv40_graph_init(struct drm_device *); +extern void nv40_graph_takedown(struct drm_device *); +extern int nv40_graph_create_context(struct nouveau_channel *); +extern void nv40_graph_destroy_context(struct nouveau_channel *); +extern int nv40_graph_load_context(struct nouveau_channel *); +extern int nv40_graph_save_context(struct nouveau_channel *); + +/* nv50_graph.c */ +extern int nv50_graph_init(struct drm_device *); +extern void nv50_graph_takedown(struct drm_device *); +extern int nv50_graph_create_context(struct nouveau_channel *); +extern void nv50_graph_destroy_context(struct nouveau_channel *); +extern int nv50_graph_load_context(struct nouveau_channel *); +extern int nv50_graph_save_context(struct nouveau_channel *); + +/* nv04_instmem.c */ +extern int nv04_instmem_init(struct drm_device *); +extern void nv04_instmem_takedown(struct drm_device *); +extern int nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, + uint32_t *size); +extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); +extern int nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); +extern int nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); + +/* nv50_instmem.c */ +extern int nv50_instmem_init(struct drm_device *); +extern void nv50_instmem_takedown(struct drm_device *); +extern int nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, + uint32_t *size); +extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); +extern int nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); +extern int nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); + +/* nv04_mc.c */ +extern int nv04_mc_init(struct drm_device *); +extern void nv04_mc_takedown(struct drm_device *); + +/* nv40_mc.c */ +extern int nv40_mc_init(struct drm_device *); +extern void nv40_mc_takedown(struct drm_device *); + +/* nv50_mc.c */ +extern int nv50_mc_init(struct drm_device *); +extern void nv50_mc_takedown(struct drm_device *); + +/* nv04_timer.c */ +extern int nv04_timer_init(struct drm_device *); +extern uint64_t nv04_timer_read(struct drm_device *); +extern void nv04_timer_takedown(struct drm_device *); + +extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg); + +#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 + +/* PRAMIN access */ +#if defined(__powerpc__) +#define NV_RI32(o) in_be32((void __iomem *)(dev_priv->ramin)->handle+(o)) +#define NV_WI32(o,v) out_be32((void __iomem*)(dev_priv->ramin)->handle+(o), (v)) +#else +#define NV_RI32(o) DRM_READ32(dev_priv->ramin, (o)) +#define NV_WI32(o,v) DRM_WRITE32(dev_priv->ramin, (o), (v)) +#endif + +#define INSTANCE_RD(o,i) NV_RI32((o)->im_pramin->start + ((i)<<2)) +#define INSTANCE_WR(o,i,v) NV_WI32((o)->im_pramin->start + ((i)<<2), (v)) + +#endif /* __NOUVEAU_DRV_H__ */ + diff --git a/drivers/char/drm/nouveau_fifo.c b/drivers/char/drm/nouveau_fifo.c new file mode 100644 index 0000000..1aa724f --- /dev/null +++ b/drivers/char/drm/nouveau_fifo.c @@ -0,0 +1,557 @@ +/* + * Copyright 2005-2006 Stephane Marchesin + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + + +/* returns the number of hw fifos */ +int nouveau_fifo_number(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv=dev->dev_private; + switch(dev_priv->card_type) + { + case NV_03: + return 8; + case NV_04: + case NV_05: + return 16; + case NV_50: + return 128; + default: + return 32; + } +} + +/* returns the size of fifo context */ +int nouveau_fifo_ctx_size(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv=dev->dev_private; + + if (dev_priv->card_type >= NV_40) + return 128; + else if (dev_priv->card_type >= NV_17) + 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(struct drm_device *dev) +{ + struct drm_nouveau_private *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: + switch (dev_priv->chipset) { + case 0x47: + case 0x49: + case 0x4b: + NV_WRITE(0x2230, 1); + break; + default: + break; + } + 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_17: + NV_WRITE(NV03_PFIFO_RAMFC, (dev_priv->ramfc_offset>>8) | + (1 << 16) /* 64 Bytes entry*/); + /* XXX nvidia blob set bit 18, 21,23 for nv20 & nv30 */ + break; + case NV_11: + case NV_10: + case NV_04: + case NV_03: + NV_WRITE(NV03_PFIFO_RAMFC, dev_priv->ramfc_offset>>8); + break; + } + + return 0; +} + +int nouveau_fifo_init(struct drm_device *dev) +{ + struct drm_nouveau_private *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); + + /* Enable PFIFO error reporting */ + NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF); + NV_WRITE(NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF); + + 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_pushbuf_ctxdma_init(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct mem_block *pb = chan->pushbuf_mem; + struct nouveau_gpuobj *pushbuf = NULL; + int ret; + + if (pb->flags & NOUVEAU_MEM_AGP) { + ret = nouveau_gpuobj_gart_dma_new(chan, pb->start, pb->size, + NV_DMA_ACCESS_RO, + &pushbuf, + &chan->pushbuf_base); + } else + if (pb->flags & NOUVEAU_MEM_PCI) { + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, + pb->start, pb->size, + NV_DMA_ACCESS_RO, + NV_DMA_TARGET_PCI_NONLINEAR, + &pushbuf); + chan->pushbuf_base = 0; + } else if (dev_priv->card_type != NV_04) { + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, + pb->start, pb->size, + NV_DMA_ACCESS_RO, + NV_DMA_TARGET_VIDMEM, &pushbuf); + chan->pushbuf_base = 0; + } else { + /* NV04 cmdbuf hack, from original ddx.. not sure of it's + * exact reason for existing :) PCI access to cmdbuf in + * VRAM. + */ + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, + pb->start + + drm_get_resource_start(dev, 1), + pb->size, NV_DMA_ACCESS_RO, + NV_DMA_TARGET_PCI, &pushbuf); + chan->pushbuf_base = 0; + } + + if ((ret = nouveau_gpuobj_ref_add(dev, chan, 0, pushbuf, + &chan->pushbuf))) { + DRM_ERROR("Error referencing push buffer ctxdma: %d\n", ret); + if (pushbuf != dev_priv->gart_info.sg_ctxdma) + nouveau_gpuobj_del(dev, &pushbuf); + return ret; + } + + return 0; +} + +static struct mem_block * +nouveau_fifo_user_pushbuf_alloc(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_config *config = &dev_priv->config; + struct mem_block *pb; + int pb_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 < pb_min_size) + config->cmdbuf.size = pb_min_size; + + pb = nouveau_mem_alloc(dev, 0, config->cmdbuf.size, + config->cmdbuf.location | NOUVEAU_MEM_MAPPED, + (struct drm_file *)-2); + if (!pb) + DRM_ERROR("Couldn't allocate DMA push buffer.\n"); + + return pb; +} + +/* allocates and initializes a fifo for user space consumption */ +int +nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, + struct drm_file *file_priv, struct mem_block *pushbuf, + uint32_t vram_handle, uint32_t tt_handle) +{ + int ret; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->Engine; + struct nouveau_channel *chan; + 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] == NULL) + break; + } + /* no more fifos. you lost. */ + if (channel==nouveau_fifo_number(dev)) + return -EINVAL; + + dev_priv->fifos[channel] = drm_calloc(1, sizeof(struct nouveau_channel), + DRM_MEM_DRIVER); + if (!dev_priv->fifos[channel]) + return -ENOMEM; + dev_priv->fifo_alloc_count++; + chan = dev_priv->fifos[channel]; + chan->dev = dev; + chan->id = channel; + chan->file_priv = file_priv; + chan->pushbuf_mem = pushbuf; + + DRM_INFO("Allocating FIFO number %d\n", channel); + + /* Allocate space for per-channel fixed notifier memory */ + ret = nouveau_notifier_init_channel(chan); + if (ret) { + nouveau_fifo_free(chan); + return ret; + } + + /* Setup channel's default objects */ + ret = nouveau_gpuobj_channel_init(chan, vram_handle, tt_handle); + if (ret) { + nouveau_fifo_free(chan); + return ret; + } + + /* Create a dma object for the push buffer */ + ret = nouveau_fifo_pushbuf_ctxdma_init(chan); + if (ret) { + nouveau_fifo_free(chan); + return ret; + } + + 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); + + /* Create a graphics context for new channel */ + ret = engine->graph.create_context(chan); + if (ret) { + nouveau_fifo_free(chan); + return ret; + } + + /* Construct inital RAMFC for new channel */ + ret = engine->fifo.create_context(chan); + if (ret) { + nouveau_fifo_free(chan); + return ret; + } + + /* setup channel's default get/put values */ + if (dev_priv->card_type < NV_50) { + NV_WRITE(NV03_FIFO_REGS_DMAPUT(channel), chan->pushbuf_base); + NV_WRITE(NV03_FIFO_REGS_DMAGET(channel), chan->pushbuf_base); + } else { + NV_WRITE(NV50_FIFO_REGS_DMAPUT(channel), chan->pushbuf_base); + NV_WRITE(NV50_FIFO_REGS_DMAGET(channel), chan->pushbuf_base); + } + + /* If this is the first channel, setup PFIFO ourselves. For any + * other case, the GPU will handle this when it switches contexts. + */ + if (dev_priv->fifo_alloc_count == 1) { + ret = engine->fifo.load_context(chan); + if (ret) { + nouveau_fifo_free(chan); + return ret; + } + + ret = engine->graph.load_context(chan); + if (ret) { + nouveau_fifo_free(chan); + return ret; + } + } + + NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH, + NV_READ(NV04_PFIFO_CACHE1_DMA_PUSH) | 1); + 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, 1); + + DRM_INFO("%s: initialised FIFO %d\n", __func__, channel); + *chan_ret = chan; + return 0; +} + +/* stops a fifo */ +void nouveau_fifo_free(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->Engine; + + DRM_INFO("%s: freeing fifo %d\n", __func__, chan->id); + + /* disable the fifo caches */ + NV_WRITE(NV03_PFIFO_CACHES, 0x00000000); + + // FIXME XXX needs more code + + engine->fifo.destroy_context(chan); + + /* Cleanup PGRAPH state */ + engine->graph.destroy_context(chan); + + /* reenable the fifo caches */ + NV_WRITE(NV03_PFIFO_CACHES, 0x00000001); + + /* Deallocate push buffer */ + nouveau_gpuobj_ref_del(dev, &chan->pushbuf); + if (chan->pushbuf_mem) { + nouveau_mem_free(dev, chan->pushbuf_mem); + chan->pushbuf_mem = NULL; + } + + /* Destroy objects belonging to the channel */ + nouveau_gpuobj_channel_takedown(chan); + + nouveau_notifier_takedown_channel(chan); + + dev_priv->fifos[chan->id] = NULL; + dev_priv->fifo_alloc_count--; + drm_free(chan, sizeof(*chan), DRM_MEM_DRIVER); +} + +/* cleanups all the fifos from file_priv */ +void nouveau_fifo_cleanup(struct drm_device *dev, struct drm_file *file_priv) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i; + + DRM_DEBUG("clearing FIFO enables from file_priv\n"); + for(i = 0; i < nouveau_fifo_number(dev); i++) { + struct nouveau_channel *chan = dev_priv->fifos[i]; + + if (chan && chan->file_priv == file_priv) + nouveau_fifo_free(chan); + } +} + +int +nouveau_fifo_owner(struct drm_device *dev, struct drm_file *file_priv, + int channel) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (channel >= nouveau_fifo_number(dev)) + return 0; + if (dev_priv->fifos[channel] == NULL) + return 0; + return (dev_priv->fifos[channel]->file_priv == file_priv); +} + +/*********************************** + * ioctls wrapping the functions + ***********************************/ + +static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_channel_alloc *init = data; + struct drm_map_list *entry; + struct nouveau_channel *chan; + struct mem_block *pushbuf; + int res; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + + if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) + return -EINVAL; + + pushbuf = nouveau_fifo_user_pushbuf_alloc(dev); + if (!pushbuf) + return -ENOMEM; + + res = nouveau_fifo_alloc(dev, &chan, file_priv, pushbuf, + init->fb_ctxdma_handle, + init->tt_ctxdma_handle); + if (res) + return res; + init->channel = chan->id; + init->put_base = chan->pushbuf_base; + + /* make the fifo available to user space */ + /* first, the fifo control regs */ + init->ctrl = dev_priv->mmio->offset; + if (dev_priv->card_type < NV_50) { + init->ctrl += NV03_FIFO_REGS(init->channel); + init->ctrl_size = NV03_FIFO_REGS_SIZE; + } else { + init->ctrl += NV50_FIFO_REGS(init->channel); + init->ctrl_size = NV50_FIFO_REGS_SIZE; + } + res = drm_addmap(dev, init->ctrl, init->ctrl_size, _DRM_REGISTERS, + 0, &chan->regs); + if (res != 0) + return res; + + entry = drm_find_matching_map(dev, chan->regs); + if (!entry) + return -EINVAL; + init->ctrl = entry->user_token; + + /* pass back FIFO map info to the caller */ + init->cmdbuf = chan->pushbuf_mem->map_handle; + init->cmdbuf_size = chan->pushbuf_mem->size; + + /* and the notifier block */ + init->notifier = chan->notifier_block->map_handle; + init->notifier_size = chan->notifier_block->size; + + return 0; +} + +static int nouveau_ioctl_fifo_free(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_channel_free *cfree = data; + struct nouveau_channel *chan; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan); + + nouveau_fifo_free(chan); + return 0; +} + +/*********************************** + * finally, the ioctl table + ***********************************/ + +struct drm_ioctl_desc nouveau_ioctls[] = { + DRM_IOCTL_DEF(DRM_NOUVEAU_CARD_INIT, nouveau_ioctl_card_init, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_ALLOC, nouveau_ioctl_mem_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_FREE, nouveau_ioctl_mem_free, DRM_AUTH), +}; + +int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls); diff --git a/drivers/char/drm/nouveau_ioc32.c b/drivers/char/drm/nouveau_ioc32.c new file mode 100644 index 0000000..f55ae7a --- /dev/null +++ b/drivers/char/drm/nouveau_ioc32.c @@ -0,0 +1,72 @@ +/** + * \file mga_ioc32.c + * + * 32-bit ioctl compatibility routines for the MGA DRM. + * + * \author Dave Airlie with code from patches by Egbert Eich + * + * + * Copyright (C) Paul Mackerras 2005 + * Copyright (C) Egbert Eich 2003,2004 + * Copyright (C) Dave Airlie 2005 + * 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 AUTHOR 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 "drmP.h" +#include "drm.h" + +#include "nouveau_drm.h" + +/** + * Called whenever a 32-bit process running under a 64-bit kernel + * performs an ioctl on /dev/dri/card. + * + * \param filp file pointer. + * \param cmd command. + * \param arg user argument. + * \return zero on success or negative number on failure. + */ +long nouveau_compat_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + unsigned int nr = DRM_IOCTL_NR(cmd); + drm_ioctl_compat_t *fn = NULL; + int ret; + + if (nr < DRM_COMMAND_BASE) + return drm_compat_ioctl(filp, cmd, arg); + +#if 0 + if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(mga_compat_ioctls)) + fn = nouveau_compat_ioctls[nr - DRM_COMMAND_BASE]; +#endif + lock_kernel(); /* XXX for now */ + if (fn != NULL) + ret = (*fn)(filp, cmd, arg); + else + ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + unlock_kernel(); + + return ret; +} diff --git a/drivers/char/drm/nouveau_irq.c b/drivers/char/drm/nouveau_irq.c new file mode 100644 index 0000000..e64677e --- /dev/null +++ b/drivers/char/drm/nouveau_irq.c @@ -0,0 +1,430 @@ +/* + * 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 "drmP.h" +#include "drm.h" +#include "nouveau_drm.h" +#include "nouveau_drv.h" +#include "nouveau_reg.h" + +void nouveau_irq_preinstall(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + /* Master disable */ + NV_WRITE(NV03_PMC_INTR_EN_0, 0); +} + +void nouveau_irq_postinstall(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + /* Master enable */ + NV_WRITE(NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE); +} + +void nouveau_irq_uninstall(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + /* Master disable */ + NV_WRITE(NV03_PMC_INTR_EN_0, 0); +} + +static void nouveau_fifo_irq_handler(struct drm_device *dev) +{ + uint32_t status, chmode, chstat, channel; + struct drm_nouveau_private *dev_priv = dev->dev_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); + + if (status & NV_PFIFO_INTR_CACHE_ERROR) { + uint32_t c1get, c1method, c1data; + + DRM_ERROR("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("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_ERROR("PFIFO DMA pusher interrupt: ch%d, 0x%08x\n", + channel, NV_READ(NV04_PFIFO_CACHE1_DMA_GET)); + + 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_ERROR("Unhandled 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(struct drm_device *dev) +{ + struct drm_nouveau_private *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 + + +struct nouveau_bitfield_names +{ + uint32_t mask; + const char * name; +}; + +static struct nouveau_bitfield_names nouveau_nstatus_names[] = +{ + { NV03_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, + { NV03_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, + { NV03_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, + { NV03_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" } +}; + +static struct nouveau_bitfield_names nouveau_nsource_names[] = +{ + { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" }, + { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" }, + { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" }, + { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION, "RANGE_EXCEPTION" }, + { NV03_PGRAPH_NSOURCE_LIMIT_COLOR, "LIMIT_COLOR" }, + { NV03_PGRAPH_NSOURCE_LIMIT_ZETA, "LIMIT_ZETA" }, + { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD, "ILLEGAL_MTHD" }, + { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION, "DMA_R_PROTECTION" }, + { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION, "DMA_W_PROTECTION" }, + { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION, "FORMAT_EXCEPTION" }, + { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION, "PATCH_EXCEPTION" }, + { NV03_PGRAPH_NSOURCE_STATE_INVALID, "STATE_INVALID" }, + { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY, "DOUBLE_NOTIFY" }, + { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE, "NOTIFY_IN_USE" }, + { NV03_PGRAPH_NSOURCE_METHOD_CNT, "METHOD_CNT" }, + { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION, "BFR_NOTIFICATION" }, + { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" }, + { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A, "DMA_WIDTH_A" }, + { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B, "DMA_WIDTH_B" }, +}; + +static void +nouveau_print_bitfield_names(uint32_t value, + const struct nouveau_bitfield_names *namelist, + const int namelist_len) +{ + int i; + for(i=0; idev_private; + int channel; + + if (dev_priv->card_type < NV_10) { + channel = (NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0xf; + } else if (dev_priv->card_type < NV_40) { + channel = (NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; + } else + if (dev_priv->card_type < NV_50) { + uint32_t cur_grctx = (NV_READ(0x40032C) & 0xfffff) << 4; + + /* 0x400704 *sometimes* contains a sensible channel ID, but + * mostly not.. for now lookup which channel owns the active + * PGRAPH context. Probably a better way, but this'll do + * for now. + */ + for (channel = 0; channel < 32; channel++) { + if (dev_priv->fifos[channel] == NULL) + continue; + if (cur_grctx == + dev_priv->fifos[channel]->ramin_grctx->instance) + break; + } + if (channel == 32) { + DRM_ERROR("AIII, unable to determine active channel " + "from PGRAPH context 0x%08x\n", cur_grctx); + return -EINVAL; + } + } else { + uint32_t cur_grctx = (NV_READ(0x40032C) & 0xfffff) << 12; + + for (channel = 0; channel < 128; channel++) { + if (dev_priv->fifos[channel] == NULL) + continue; + if (cur_grctx == + dev_priv->fifos[channel]->ramin_grctx->instance) + break; + } + if (channel == 128) { + DRM_ERROR("AIII, unable to determine active channel " + "from PGRAPH context 0x%08x\n", cur_grctx); + return -EINVAL; + } + } + + if (channel > nouveau_fifo_number(dev) || + dev_priv->fifos[channel] == NULL) { + DRM_ERROR("AIII, invalid/inactive channel id %d\n", channel); + return -EINVAL; + } + + *channel_ret = channel; + return 0; +} + +static void +nouveau_graph_dump_trap_info(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t address; + uint32_t channel, class; + uint32_t method, subc, data, data2; + uint32_t nsource, nstatus; + + if (nouveau_graph_trapped_channel(dev, &channel)) + channel = -1; + + data = NV_READ(NV04_PGRAPH_TRAPPED_DATA); + address = NV_READ(NV04_PGRAPH_TRAPPED_ADDR); + method = address & 0x1FFC; + if (dev_priv->card_type < NV_10) { + subc = (address >> 13) & 0x7; + data2= 0; + } else { + subc = (address >> 16) & 0x7; + data2= NV_READ(NV10_PGRAPH_TRAPPED_DATA_HIGH); + } + nsource = NV_READ(NV03_PGRAPH_NSOURCE); + nstatus = NV_READ(NV03_PGRAPH_NSTATUS); + if (dev_priv->card_type < NV_50) { + class = NV_READ(0x400160 + subc*4) & 0xFFFF; + } else { + class = NV_READ(0x400814); + } + + DRM_ERROR("nSource:"); + nouveau_print_bitfield_names(nsource, nouveau_nsource_names, + ARRAY_SIZE(nouveau_nsource_names)); + printk(", nStatus:"); + nouveau_print_bitfield_names(nstatus, nouveau_nstatus_names, + ARRAY_SIZE(nouveau_nstatus_names)); + printk("\n"); + + DRM_ERROR("Channel %d/%d (class 0x%04x) - Method 0x%04x, Data 0x%08x:0x%08x\n", + channel, subc, class, method, data2, data); +} + +static void nouveau_pgraph_irq_handler(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t status, nsource; + + status = NV_READ(NV03_PGRAPH_INTR); + if (!status) + return; + nsource = NV_READ(NV03_PGRAPH_NSOURCE); + + if (status & NV_PGRAPH_INTR_NOTIFY) { + DRM_DEBUG("PGRAPH notify interrupt\n"); + + nouveau_graph_dump_trap_info(dev); + + status &= ~NV_PGRAPH_INTR_NOTIFY; + NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY); + } + + if (status & NV_PGRAPH_INTR_ERROR) { + DRM_ERROR("PGRAPH error interrupt\n"); + + 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_DEBUG("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: + case NV_11: + case NV_17: + nouveau_nv10_context_switch(dev); + break; + case NV_20: + case NV_30: + nouveau_nv20_context_switch(dev); + break; + default: + DRM_ERROR("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_ERROR("Unhandled 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(struct drm_device *dev, int crtc) +{ + struct drm_nouveau_private *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) +{ + struct drm_device *dev = (struct drm_device*)arg; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t status; + + status = NV_READ(NV03_PMC_INTR_0); + if (!status) + return IRQ_NONE; + + 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; +} + diff --git a/drivers/char/drm/nouveau_mem.c b/drivers/char/drm/nouveau_mem.c new file mode 100644 index 0000000..1394df5 --- /dev/null +++ b/drivers/char/drm/nouveau_mem.c @@ -0,0 +1,616 @@ +/* + * 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 "drmP.h" +#include "drm.h" +#include "drm_sarea.h" +#include "nouveau_drv.h" + +static struct mem_block *split_block(struct mem_block *p, uint64_t start, uint64_t size, + struct drm_file *file_priv) +{ + /* 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->file_priv = 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->file_priv = 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->file_priv = file_priv; + return p; +} + +struct mem_block *nouveau_mem_alloc_block(struct mem_block *heap, + uint64_t size, + int align2, + struct drm_file *file_priv) +{ + 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->file_priv == 0 && start + size <= p->start + p->size) + return split_block(p, start, size, file_priv); + } + + 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; +} + +void nouveau_mem_free_block(struct mem_block *p) +{ + p->file_priv = NULL; + + /* Assumes a single contiguous range. Needs a special file_priv in + * 'heap' to stop it being subsumed. + */ + if (p->next->file_priv == 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->file_priv == 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? + */ +int nouveau_mem_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 -ENOMEM; + + *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS); + if (!*heap) { + drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFS); + return -ENOMEM; + } + + blocks->start = start; + blocks->size = size; + blocks->file_priv = NULL; + blocks->next = blocks->prev = *heap; + + memset(*heap, 0, sizeof(**heap)); + (*heap)->file_priv = (struct drm_file *) - 1; + (*heap)->next = (*heap)->prev = blocks; + return 0; +} + +/* + * Free all blocks associated with the releasing file_priv + */ +void nouveau_mem_release(struct drm_file *file_priv, struct mem_block *heap) +{ + struct mem_block *p; + + if (!heap || !heap->next) + return; + + list_for_each(p, heap) { + if (p->file_priv == file_priv) + p->file_priv = NULL; + } + + /* Assumes a single contiguous range. Needs a special file_priv in + * 'heap' to stop it being subsumed. + */ + list_for_each(p, heap) { + while ((p->file_priv == 0) && (p->next->file_priv == 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 + */ +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) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + nouveau_mem_takedown(&dev_priv->agp_heap); + nouveau_mem_takedown(&dev_priv->fb_heap); + if (dev_priv->pci_heap) + nouveau_mem_takedown(&dev_priv->pci_heap); +} + +/*XXX won't work on BSD because of pci_read_config_dword */ +static uint32_t +nouveau_mem_fb_amount_igp(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct pci_dev *bridge; + uint32_t mem; + + bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0,1)); + if (!bridge) { + DRM_ERROR("no bridge device\n"); + return 0; + } + + if (dev_priv->flags&NV_NFORCE) { + pci_read_config_dword(bridge, 0x7C, &mem); + return (uint64_t)(((mem >> 6) & 31) + 1)*1024*1024; + } else + if(dev_priv->flags&NV_NFORCE2) { + pci_read_config_dword(bridge, 0x84, &mem); + return (uint64_t)(((mem >> 4) & 127) + 1)*1024*1024; + } + + DRM_ERROR("impossible!\n"); + + return 0; +} + +/* returns the amount of FB ram in bytes */ +uint64_t nouveau_mem_fb_amount(struct drm_device *dev) +{ + struct drm_nouveau_private *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_11: + case NV_17: + case NV_20: + case NV_30: + case NV_40: + case NV_44: + case NV_50: + default: + if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) { + return nouveau_mem_fb_amount_igp(dev); + } 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; +} + +static int +nouveau_mem_init_agp(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_agp_info info; + struct drm_agp_mode mode; + struct drm_agp_buffer agp_req; + struct drm_agp_binding bind_req; + int ret; + + ret = drm_agp_acquire(dev); + if (ret) { + DRM_ERROR("Unable to acquire AGP: %d\n", ret); + return ret; + } + + ret = drm_agp_info(dev, &info); + if (ret) { + DRM_ERROR("Unable to get AGP info: %d\n", ret); + return ret; + } + + /* see agp.h for the AGPSTAT_* modes available */ + mode.mode = info.mode; + ret = drm_agp_enable(dev, mode); + if (ret) { + DRM_ERROR("Unable to enable AGP: %d\n", ret); + return ret; + } + + agp_req.size = info.aperture_size; + agp_req.type = 0; + ret = drm_agp_alloc(dev, &agp_req); + if (ret) { + DRM_ERROR("Unable to alloc AGP: %d\n", ret); + return ret; + } + + bind_req.handle = agp_req.handle; + bind_req.offset = 0; + ret = drm_agp_bind(dev, &bind_req); + if (ret) { + DRM_ERROR("Unable to bind AGP: %d\n", ret); + return ret; + } + + dev_priv->gart_info.type = NOUVEAU_GART_AGP; + dev_priv->gart_info.aper_base = info.aperture_base; + dev_priv->gart_info.aper_size = info.aperture_size; + return 0; +} + +int nouveau_mem_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t fb_size; + int ret = 0; + + dev_priv->agp_heap = dev_priv->pci_heap = dev_priv->fb_heap = NULL; + dev_priv->fb_phys = 0; + dev_priv->gart_info.type = NOUVEAU_GART_NONE; + + /* 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_rsvd_vram; + 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 (nouveau_mem_init_heap(&dev_priv->fb_heap, + 0, 256*1024*1024)) + return -ENOMEM; + if (nouveau_mem_init_heap(&dev_priv->fb_nomap_heap, + 256*1024*1024, fb_size-256*1024*1024)) + return -ENOMEM; + } else { + if (nouveau_mem_init_heap(&dev_priv->fb_heap, 0, fb_size)) + return -ENOMEM; + dev_priv->fb_nomap_heap=NULL; + } + + /* Init AGP / NV50 PCIEGART */ + if (drm_device_is_agp(dev) && dev->agp) { + if ((ret = nouveau_mem_init_agp(dev))) + DRM_ERROR("Error initialising AGP: %d\n", ret); + } + + /*Note: this is *not* just NV50 code, but only used on NV50 for now */ + if (dev_priv->gart_info.type == NOUVEAU_GART_NONE && + dev_priv->card_type >= NV_50) { + ret = nouveau_sgdma_init(dev); + if (!ret) { + ret = nouveau_sgdma_nottm_hack_init(dev); + if (ret) + nouveau_sgdma_takedown(dev); + } + + if (ret) + DRM_ERROR("Error initialising SG DMA: %d\n", ret); + } + + if (dev_priv->gart_info.type != NOUVEAU_GART_NONE) { + if (nouveau_mem_init_heap(&dev_priv->agp_heap, + 0, dev_priv->gart_info.aper_size)) { + if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA) { + nouveau_sgdma_nottm_hack_takedown(dev); + nouveau_sgdma_takedown(dev); + } + } + } + + /* NV04-NV40 PCIEGART */ + if (!dev_priv->agp_heap && dev_priv->card_type < NV_50) { + struct drm_scatter_gather sgreq; + + DRM_DEBUG("Allocating sg memory for PCI DMA\n"); + sgreq.size = 16 << 20; //16MB of PCI scatter-gather zone + + if (drm_sg_alloc(dev, &sgreq)) { + DRM_ERROR("Unable to allocate %dMB of scatter-gather" + " pages for PCI DMA!",sgreq.size>>20); + } else { + if (nouveau_mem_init_heap(&dev_priv->pci_heap, 0, + dev->sg->pages * PAGE_SIZE)) { + DRM_ERROR("Unable to initialize pci_heap!"); + } + } + } + + return 0; +} + +struct mem_block* nouveau_mem_alloc(struct drm_device *dev, int alignment, + uint64_t size, int flags, + struct drm_file *file_priv) +{ + struct mem_block *block; + int type; + struct drm_nouveau_private *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; + + +#define NOUVEAU_MEM_ALLOC_AGP {\ + type=NOUVEAU_MEM_AGP;\ + block = nouveau_mem_alloc_block(dev_priv->agp_heap, size,\ + alignment, file_priv); \ + if (block) goto alloc_ok;\ + } + +#define NOUVEAU_MEM_ALLOC_PCI {\ + type = NOUVEAU_MEM_PCI;\ + block = nouveau_mem_alloc_block(dev_priv->pci_heap, size, \ + alignment, file_priv); \ + if ( block ) goto alloc_ok;\ + } + +#define NOUVEAU_MEM_ALLOC_FB {\ + type=NOUVEAU_MEM_FB;\ + if (!(flags&NOUVEAU_MEM_MAPPED)) {\ + block = nouveau_mem_alloc_block(dev_priv->fb_nomap_heap,\ + size, alignment, \ + file_priv); \ + if (block) goto alloc_ok;\ + }\ + block = nouveau_mem_alloc_block(dev_priv->fb_heap, size,\ + alignment, file_priv);\ + if (block) goto alloc_ok;\ + } + + + if (flags&NOUVEAU_MEM_FB) NOUVEAU_MEM_ALLOC_FB + if (flags&NOUVEAU_MEM_AGP) NOUVEAU_MEM_ALLOC_AGP + if (flags&NOUVEAU_MEM_PCI) NOUVEAU_MEM_ALLOC_PCI + if (flags&NOUVEAU_MEM_FB_ACCEPTABLE) NOUVEAU_MEM_ALLOC_FB + if (flags&NOUVEAU_MEM_AGP_ACCEPTABLE) NOUVEAU_MEM_ALLOC_AGP + if (flags&NOUVEAU_MEM_PCI_ACCEPTABLE) NOUVEAU_MEM_ALLOC_PCI + + + return NULL; + +alloc_ok: + block->flags=type; + + if (flags&NOUVEAU_MEM_MAPPED) + { + struct drm_map_list *entry; + int ret = 0; + block->flags|=NOUVEAU_MEM_MAPPED; + + if (type == NOUVEAU_MEM_AGP) { + if (dev_priv->gart_info.type != NOUVEAU_GART_SGDMA) + ret = drm_addmap(dev, block->start, block->size, + _DRM_AGP, 0, &block->map); + else + ret = drm_addmap(dev, block->start, block->size, + _DRM_SCATTER_GATHER, 0, &block->map); + } + else if (type == NOUVEAU_MEM_FB) + ret = drm_addmap(dev, block->start + dev_priv->fb_phys, + block->size, _DRM_FRAME_BUFFER, + 0, &block->map); + else if (type == NOUVEAU_MEM_PCI) + ret = drm_addmap(dev, block->start, block->size, + _DRM_SCATTER_GATHER, 0, &block->map); + + if (ret) { + nouveau_mem_free_block(block); + return NULL; + } + + entry = drm_find_matching_map(dev, block->map); + if (!entry) { + nouveau_mem_free_block(block); + return NULL; + } + block->map_handle = entry->user_token; + } + + DRM_DEBUG("allocated 0x%llx type=0x%08x\n", block->start, block->flags); + return block; +} + +void nouveau_mem_free(struct drm_device* dev, struct mem_block* block) +{ + DRM_DEBUG("freeing 0x%llx type=0x%08x\n", block->start, block->flags); + if (block->flags&NOUVEAU_MEM_MAPPED) + drm_rmmap(dev, block->map); + nouveau_mem_free_block(block); +} + +/* + * Ioctls + */ + +int nouveau_ioctl_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + struct drm_nouveau_mem_alloc *alloc = data; + struct mem_block *block; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + + block=nouveau_mem_alloc(dev, alloc->alignment, alloc->size, + alloc->flags, file_priv); + if (!block) + return -ENOMEM; + alloc->map_handle=block->map_handle; + alloc->offset=block->start; + alloc->flags=block->flags; + + return 0; +} + +int nouveau_ioctl_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_mem_free *memfree = data; + struct mem_block *block; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + + block=NULL; + if (memfree->flags & NOUVEAU_MEM_FB) + block = find_block(dev_priv->fb_heap, memfree->offset); + else if (memfree->flags & NOUVEAU_MEM_AGP) + block = find_block(dev_priv->agp_heap, memfree->offset); + else if (memfree->flags & NOUVEAU_MEM_PCI) + block = find_block(dev_priv->pci_heap, memfree->offset); + if (!block) + return -EFAULT; + if (block->file_priv != file_priv) + return -EPERM; + + nouveau_mem_free(dev, block); + return 0; +} + + diff --git a/drivers/char/drm/nouveau_notifier.c b/drivers/char/drm/nouveau_notifier.c new file mode 100644 index 0000000..71b8cbe --- /dev/null +++ b/drivers/char/drm/nouveau_notifier.c @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2007 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +int +nouveau_notifier_init_channel(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int flags, ret; + + /*TODO: PCI notifier blocks */ + if (dev_priv->agp_heap) + flags = NOUVEAU_MEM_AGP; + else if (dev_priv->pci_heap) + flags = NOUVEAU_MEM_PCI; + else + flags = NOUVEAU_MEM_FB; + flags |= (NOUVEAU_MEM_MAPPED | NOUVEAU_MEM_FB_ACCEPTABLE); + + chan->notifier_block = nouveau_mem_alloc(dev, 0, PAGE_SIZE, flags, + (struct drm_file *)-2); + if (!chan->notifier_block) + return -ENOMEM; + DRM_DEBUG("Allocated notifier block in 0x%08x\n", + chan->notifier_block->flags); + + ret = nouveau_mem_init_heap(&chan->notifier_heap, + 0, chan->notifier_block->size); + if (ret) + return ret; + + return 0; +} + +void +nouveau_notifier_takedown_channel(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + + if (chan->notifier_block) { + nouveau_mem_free(dev, chan->notifier_block); + chan->notifier_block = NULL; + } + + nouveau_mem_takedown(&chan->notifier_heap); +} + +static void +nouveau_notifier_gpuobj_dtor(struct drm_device *dev, + struct nouveau_gpuobj *gpuobj) +{ + DRM_DEBUG("\n"); + + if (gpuobj->priv) + nouveau_mem_free_block(gpuobj->priv); +} + +int +nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, + int count, uint32_t *b_offset) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *nobj = NULL; + struct mem_block *mem; + uint32_t offset; + int target, ret; + + if (!chan->notifier_heap) { + DRM_ERROR("Channel %d doesn't have a notifier heap!\n", + chan->id); + return -EINVAL; + } + + mem = nouveau_mem_alloc_block(chan->notifier_heap, count*32, 0, + (struct drm_file *)-2); + if (!mem) { + DRM_ERROR("Channel %d notifier block full\n", chan->id); + return -ENOMEM; + } + mem->flags = NOUVEAU_MEM_NOTIFIER; + + offset = chan->notifier_block->start; + if (chan->notifier_block->flags & NOUVEAU_MEM_FB) { + target = NV_DMA_TARGET_VIDMEM; + } else + if (chan->notifier_block->flags & NOUVEAU_MEM_AGP) { + if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA && + dev_priv->card_type < NV_50) { + ret = nouveau_sgdma_get_page(dev, offset, &offset); + if (ret) + return ret; + target = NV_DMA_TARGET_PCI; + } else { + target = NV_DMA_TARGET_AGP; + } + } else + if (chan->notifier_block->flags & NOUVEAU_MEM_PCI) { + target = NV_DMA_TARGET_PCI_NONLINEAR; + } else { + DRM_ERROR("Bad DMA target, flags 0x%08x!\n", + chan->notifier_block->flags); + return -EINVAL; + } + offset += mem->start; + + if ((ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, + offset, mem->size, + NV_DMA_ACCESS_RW, target, &nobj))) { + nouveau_mem_free_block(mem); + DRM_ERROR("Error creating notifier ctxdma: %d\n", ret); + return ret; + } + nobj->dtor = nouveau_notifier_gpuobj_dtor; + nobj->priv = mem; + + if ((ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL))) { + nouveau_gpuobj_del(dev, &nobj); + nouveau_mem_free_block(mem); + DRM_ERROR("Error referencing notifier ctxdma: %d\n", ret); + return ret; + } + + *b_offset = mem->start; + return 0; +} + +int +nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_notifierobj_alloc *na = data; + struct nouveau_channel *chan; + int ret; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan); + + ret = nouveau_notifier_alloc(chan, na->handle, na->count, &na->offset); + if (ret) + return ret; + + return 0; +} + diff --git a/drivers/char/drm/nouveau_object.c b/drivers/char/drm/nouveau_object.c new file mode 100644 index 0000000..fbce770 --- /dev/null +++ b/drivers/char/drm/nouveau_object.c @@ -0,0 +1,1148 @@ +/* + * 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 "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +/* 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_ramht_hash_handle(struct drm_device *dev, int channel, uint32_t handle) +{ + struct drm_nouveau_private *dev_priv=dev->dev_private; + uint32_t hash = 0; + int i; + + DRM_DEBUG("ch%d handle=0x%08x\n", channel, handle); + + for (i=32;i>0;i-=dev_priv->ramht_bits) { + hash ^= (handle & ((1 << dev_priv->ramht_bits) - 1)); + handle >>= dev_priv->ramht_bits; + } + if (dev_priv->card_type < NV_50) + hash ^= channel << (dev_priv->ramht_bits - 4); + hash <<= 3; + + DRM_DEBUG("hash=0x%08x\n", hash); + return hash; +} + +static int +nouveau_ramht_entry_valid(struct drm_device *dev, struct nouveau_gpuobj *ramht, + uint32_t offset) +{ + struct drm_nouveau_private *dev_priv=dev->dev_private; + uint32_t ctx = INSTANCE_RD(ramht, (offset + 4)/4); + + if (dev_priv->card_type < NV_40) + return ((ctx & NV_RAMHT_CONTEXT_VALID) != 0); + return (ctx != 0); +} + +static int +nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) +{ + struct drm_nouveau_private *dev_priv=dev->dev_private; + struct nouveau_channel *chan = dev_priv->fifos[ref->channel]; + struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL; + struct nouveau_gpuobj *gpuobj = ref->gpuobj; + uint32_t ctx, co, ho; + + if (!ramht) { + DRM_ERROR("No hash table!\n"); + return -EINVAL; + } + + if (dev_priv->card_type < NV_40) { + ctx = NV_RAMHT_CONTEXT_VALID | (ref->instance >> 4) | + (ref->channel << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) | + (gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT); + } else + if (dev_priv->card_type < NV_50) { + ctx = (ref->instance >> 4) | + (ref->channel << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) | + (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); + } else { + ctx = (ref->instance >> 4) | + (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); + } + + co = ho = nouveau_ramht_hash_handle(dev, ref->channel, ref->handle); + do { + if (!nouveau_ramht_entry_valid(dev, ramht, co)) { + DRM_DEBUG("insert ch%d 0x%08x: h=0x%08x, c=0x%08x\n", + ref->channel, co, ref->handle, ctx); + INSTANCE_WR(ramht, (co + 0)/4, ref->handle); + INSTANCE_WR(ramht, (co + 4)/4, ctx); + + list_add_tail(&ref->list, &chan->ramht_refs); + return 0; + } + DRM_DEBUG("collision ch%d 0x%08x: h=0x%08x\n", + ref->channel, co, INSTANCE_RD(ramht, co/4)); + + co += 8; + if (co >= dev_priv->ramht_size) { + DRM_INFO("no space left after collision\n"); + co = 0; + /* exit as it seems to cause crash with nouveau_demo and + * 0xdead0001 object */ + break; + } + } while (co != ho); + + DRM_ERROR("RAMHT space exhausted. ch=%d\n", ref->channel); + return -ENOMEM; +} + +static void +nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = dev_priv->fifos[ref->channel]; + struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL; + uint32_t co, ho; + + if (!ramht) { + DRM_ERROR("No hash table!\n"); + return; + } + + co = ho = nouveau_ramht_hash_handle(dev, ref->channel, ref->handle); + do { + if (nouveau_ramht_entry_valid(dev, ramht, co) && + (ref->handle == INSTANCE_RD(ramht, (co/4)))) { + DRM_DEBUG("remove ch%d 0x%08x: h=0x%08x, c=0x%08x\n", + ref->channel, co, ref->handle, + INSTANCE_RD(ramht, (co + 4))); + INSTANCE_WR(ramht, (co + 0)/4, 0x00000000); + INSTANCE_WR(ramht, (co + 4)/4, 0x00000000); + + list_del(&ref->list); + return; + } + + co += 8; + if (co >= dev_priv->ramht_size) + co = 0; + } while (co != ho); + + DRM_ERROR("RAMHT entry not found. ch=%d, handle=0x%08x\n", + ref->channel, ref->handle); +} + +int +nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, + int size, int align, uint32_t flags, + struct nouveau_gpuobj **gpuobj_ret) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->Engine; + struct nouveau_gpuobj *gpuobj; + struct mem_block *pramin = NULL; + int ret; + + DRM_DEBUG("ch%d size=%d align=%d flags=0x%08x\n", + chan ? chan->id : -1, size, align, flags); + + if (!dev_priv || !gpuobj_ret || *gpuobj_ret != NULL) + return -EINVAL; + + gpuobj = drm_calloc(1, sizeof(*gpuobj), DRM_MEM_DRIVER); + if (!gpuobj) + return -ENOMEM; + DRM_DEBUG("gpuobj %p\n", gpuobj); + gpuobj->flags = flags; + gpuobj->im_channel = chan ? chan->id : -1; + + list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); + + /* Choose between global instmem heap, and per-channel private + * instmem heap. On ramin_heap) { + DRM_DEBUG("private heap\n"); + pramin = chan->ramin_heap; + } else + if (dev_priv->card_type < NV_50) { + DRM_DEBUG("global heap fallback\n"); + pramin = dev_priv->ramin_heap; + } + } else { + DRM_DEBUG("global heap\n"); + pramin = dev_priv->ramin_heap; + } + + if (!pramin) { + DRM_ERROR("No PRAMIN heap!\n"); + return -EINVAL; + } + + if (!chan && (ret = engine->instmem.populate(dev, gpuobj, &size))) { + nouveau_gpuobj_del(dev, &gpuobj); + return ret; + } + + /* Allocate a chunk of the PRAMIN aperture */ + gpuobj->im_pramin = nouveau_mem_alloc_block(pramin, size, + drm_order(align), + (struct drm_file *)-2); + if (!gpuobj->im_pramin) { + nouveau_gpuobj_del(dev, &gpuobj); + return -ENOMEM; + } + gpuobj->im_pramin->flags = NOUVEAU_MEM_INSTANCE; + + if (!chan && (ret = engine->instmem.bind(dev, gpuobj))) { + nouveau_gpuobj_del(dev, &gpuobj); + return ret; + } + + if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { + int i; + + for (i = 0; i < gpuobj->im_pramin->size; i += 4) + INSTANCE_WR(gpuobj, i/4, 0); + } + + *gpuobj_ret = gpuobj; + return 0; +} + +int +nouveau_gpuobj_early_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + DRM_DEBUG("\n"); + + INIT_LIST_HEAD(&dev_priv->gpuobj_list); + + return 0; +} + +int +nouveau_gpuobj_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + + DRM_DEBUG("\n"); + + if (dev_priv->card_type < NV_50) { + if ((ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramht_offset, + ~0, dev_priv->ramht_size, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ALLOW_NO_REFS, + &dev_priv->ramht, NULL))) + return ret; + } + + return 0; +} + +void +nouveau_gpuobj_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + DRM_DEBUG("\n"); + + nouveau_gpuobj_del(dev, &dev_priv->ramht); +} + +void +nouveau_gpuobj_late_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj = NULL; + struct list_head *entry, *tmp; + + DRM_DEBUG("\n"); + + list_for_each_safe(entry, tmp, &dev_priv->gpuobj_list) { + gpuobj = list_entry(entry, struct nouveau_gpuobj, list); + + DRM_ERROR("gpuobj %p still exists at takedown, refs=%d\n", + gpuobj, gpuobj->refcount); + gpuobj->refcount = 0; + nouveau_gpuobj_del(dev, &gpuobj); + } +} + +int +nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->Engine; + struct nouveau_gpuobj *gpuobj; + + DRM_DEBUG("gpuobj %p\n", pgpuobj ? *pgpuobj : NULL); + + if (!dev_priv || !pgpuobj || !(*pgpuobj)) + return -EINVAL; + gpuobj = *pgpuobj; + + if (gpuobj->refcount != 0) { + DRM_ERROR("gpuobj refcount is %d\n", gpuobj->refcount); + return -EINVAL; + } + + if (gpuobj->dtor) + gpuobj->dtor(dev, gpuobj); + + if (gpuobj->im_backing) { + if (gpuobj->flags & NVOBJ_FLAG_FAKE) + drm_free(gpuobj->im_backing, + sizeof(*gpuobj->im_backing), DRM_MEM_DRIVER); + else + engine->instmem.clear(dev, gpuobj); + } + + if (gpuobj->im_pramin) { + if (gpuobj->flags & NVOBJ_FLAG_FAKE) + drm_free(gpuobj->im_pramin, sizeof(*gpuobj->im_pramin), + DRM_MEM_DRIVER); + else + nouveau_mem_free_block(gpuobj->im_pramin); + } + + list_del(&gpuobj->list); + + *pgpuobj = NULL; + drm_free(gpuobj, sizeof(*gpuobj), DRM_MEM_DRIVER); + return 0; +} + +static int +nouveau_gpuobj_instance_get(struct drm_device *dev, + struct nouveau_channel *chan, + struct nouveau_gpuobj *gpuobj, uint32_t *inst) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *cpramin; + + /* card_type < NV_50) { + *inst = gpuobj->im_pramin->start; + return 0; + } + + if (chan && gpuobj->im_channel != chan->id) { + DRM_ERROR("Channel mismatch: obj %d, ref %d\n", + gpuobj->im_channel, chan->id); + return -EINVAL; + } + + /* NV50 channel-local instance */ + if (chan > 0) { + cpramin = chan->ramin->gpuobj; + *inst = gpuobj->im_pramin->start - cpramin->im_pramin->start; + return 0; + } + + /* NV50 global (VRAM) instance */ + if (gpuobj->im_channel < 0) { + /* ...from global heap */ + if (!gpuobj->im_backing) { + DRM_ERROR("AII, no VRAM backing gpuobj\n"); + return -EINVAL; + } + *inst = gpuobj->im_backing->start; + return 0; + } else { + /* ...from local heap */ + cpramin = dev_priv->fifos[gpuobj->im_channel]->ramin->gpuobj; + *inst = cpramin->im_backing->start + + (gpuobj->im_pramin->start - cpramin->im_pramin->start); + return 0; + } + + return -EINVAL; +} + +int +nouveau_gpuobj_ref_add(struct drm_device *dev, struct nouveau_channel *chan, + uint32_t handle, struct nouveau_gpuobj *gpuobj, + struct nouveau_gpuobj_ref **ref_ret) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj_ref *ref; + uint32_t instance; + int ret; + + DRM_DEBUG("ch%d h=0x%08x gpuobj=%p\n", + chan ? chan->id : -1, handle, gpuobj); + + if (!dev_priv || !gpuobj || (ref_ret && *ref_ret != NULL)) + return -EINVAL; + + if (!chan && !ref_ret) + return -EINVAL; + + ret = nouveau_gpuobj_instance_get(dev, chan, gpuobj, &instance); + if (ret) + return ret; + + ref = drm_calloc(1, sizeof(*ref), DRM_MEM_DRIVER); + if (!ref) + return -ENOMEM; + ref->gpuobj = gpuobj; + ref->channel = chan ? chan->id : -1; + ref->instance = instance; + + if (!ref_ret) { + ref->handle = handle; + + ret = nouveau_ramht_insert(dev, ref); + if (ret) { + drm_free(ref, sizeof(*ref), DRM_MEM_DRIVER); + return ret; + } + } else { + ref->handle = ~0; + *ref_ret = ref; + } + + ref->gpuobj->refcount++; + return 0; +} + +int nouveau_gpuobj_ref_del(struct drm_device *dev, struct nouveau_gpuobj_ref **pref) +{ + struct nouveau_gpuobj_ref *ref; + + DRM_DEBUG("ref %p\n", pref ? *pref : NULL); + + if (!dev || !pref || *pref == NULL) + return -EINVAL; + ref = *pref; + + if (ref->handle != ~0) + nouveau_ramht_remove(dev, ref); + + if (ref->gpuobj) { + ref->gpuobj->refcount--; + + if (ref->gpuobj->refcount == 0) { + if (!(ref->gpuobj->flags & NVOBJ_FLAG_ALLOW_NO_REFS)) + nouveau_gpuobj_del(dev, &ref->gpuobj); + } + } + + *pref = NULL; + drm_free(ref, sizeof(ref), DRM_MEM_DRIVER); + return 0; +} + +int +nouveau_gpuobj_new_ref(struct drm_device *dev, + struct nouveau_channel *oc, struct nouveau_channel *rc, + uint32_t handle, int size, int align, uint32_t flags, + struct nouveau_gpuobj_ref **ref) +{ + struct nouveau_gpuobj *gpuobj = NULL; + int ret; + + if ((ret = nouveau_gpuobj_new(dev, oc, size, align, flags, &gpuobj))) + return ret; + + if ((ret = nouveau_gpuobj_ref_add(dev, rc, handle, gpuobj, ref))) { + nouveau_gpuobj_del(dev, &gpuobj); + return ret; + } + + return 0; +} + +int +nouveau_gpuobj_ref_find(struct nouveau_channel *chan, uint32_t handle, + struct nouveau_gpuobj_ref **ref_ret) +{ + struct nouveau_gpuobj_ref *ref; + struct list_head *entry, *tmp; + + list_for_each_safe(entry, tmp, &chan->ramht_refs) { + ref = list_entry(entry, struct nouveau_gpuobj_ref, list); + + if (ref->handle == handle) { + if (ref_ret) + *ref_ret = ref; + return 0; + } + } + + return -EINVAL; +} + +int +nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset, + uint32_t b_offset, uint32_t size, + uint32_t flags, struct nouveau_gpuobj **pgpuobj, + struct nouveau_gpuobj_ref **pref) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj = NULL; + int i; + + DRM_DEBUG("p_offset=0x%08x b_offset=0x%08x size=0x%08x flags=0x%08x\n", + p_offset, b_offset, size, flags); + + gpuobj = drm_calloc(1, sizeof(*gpuobj), DRM_MEM_DRIVER); + if (!gpuobj) + return -ENOMEM; + DRM_DEBUG("gpuobj %p\n", gpuobj); + gpuobj->im_channel = -1; + gpuobj->flags = flags | NVOBJ_FLAG_FAKE; + + list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); + + if (p_offset != ~0) { + gpuobj->im_pramin = drm_calloc(1, sizeof(struct mem_block), + DRM_MEM_DRIVER); + if (!gpuobj->im_pramin) { + nouveau_gpuobj_del(dev, &gpuobj); + return -ENOMEM; + } + gpuobj->im_pramin->start = p_offset; + gpuobj->im_pramin->size = size; + } + + if (b_offset != ~0) { + gpuobj->im_backing = drm_calloc(1, sizeof(struct mem_block), + DRM_MEM_DRIVER); + if (!gpuobj->im_backing) { + nouveau_gpuobj_del(dev, &gpuobj); + return -ENOMEM; + } + gpuobj->im_backing->start = b_offset; + gpuobj->im_backing->size = size; + } + + if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { + for (i = 0; i < gpuobj->im_pramin->size; i += 4) + INSTANCE_WR(gpuobj, i/4, 0); + } + + if (pref) { + if ((i = nouveau_gpuobj_ref_add(dev, NULL, 0, gpuobj, pref))) { + nouveau_gpuobj_del(dev, &gpuobj); + return i; + } + } + + if (pgpuobj) + *pgpuobj = gpuobj; + return 0; +} + + +static int +nouveau_gpuobj_class_instmem_size(struct drm_device *dev, int class) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + /*XXX: dodgy hack for now */ + if (dev_priv->card_type >= NV_50) + return 24; + if (dev_priv->card_type >= NV_40) + return 32; + return 16; +} + +/* + 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 (size of transfer) + entry[X] + 1 0 readonly, 1 readwrite + 31:12 dma frame address of the page (bits 12-31 of the address) + entry[N] + page table terminator, same value as the first pte, as does nvidia + rivatv uses 0xffffffff + + Non linear page tables 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. +*/ +int +nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, + uint64_t offset, uint64_t size, int access, + int target, struct nouveau_gpuobj **gpuobj) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + uint32_t is_scatter_gather = 0; + + /* Total number of pages covered by the request. + */ + const unsigned int page_count = (size + PAGE_SIZE - 1) / PAGE_SIZE; + + + DRM_DEBUG("ch%d class=0x%04x offset=0x%llx size=0x%llx\n", + chan->id, class, offset, size); + DRM_DEBUG("access=%d target=%d\n", access, target); + + switch (target) { + case NV_DMA_TARGET_AGP: + offset += dev_priv->gart_info.aper_base; + break; + case NV_DMA_TARGET_PCI_NONLINEAR: + /*assume the "offset" is a virtual memory address*/ + is_scatter_gather = 1; + /*put back the right value*/ + target = NV_DMA_TARGET_PCI; + break; + default: + break; + } + + ret = nouveau_gpuobj_new(dev, chan, + is_scatter_gather ? ((page_count << 2) + 12) : nouveau_gpuobj_class_instmem_size(dev, class), + 16, + NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, + gpuobj); + if (ret) { + DRM_ERROR("Error creating gpuobj: %d\n", ret); + return ret; + } + + if (dev_priv->card_type < NV_50) { + uint32_t frame, adjust, pte_flags = 0; + adjust = offset & 0x00000fff; + if (access != NV_DMA_ACCESS_RO) + pte_flags |= (1<<1); + + if ( ! is_scatter_gather ) + { + frame = offset & ~0x00000fff; + + INSTANCE_WR(*gpuobj, 0, ((1<<12) | (1<<13) | + (adjust << 20) | + (access << 14) | + (target << 16) | + class)); + INSTANCE_WR(*gpuobj, 1, size - 1); + INSTANCE_WR(*gpuobj, 2, frame | pte_flags); + INSTANCE_WR(*gpuobj, 3, frame | pte_flags); + } + else + { + /* Intial page entry in the scatter-gather area that + * corresponds to the base offset + */ + unsigned int idx = offset / PAGE_SIZE; + + uint32_t instance_offset; + unsigned int i; + + if ((idx + page_count) > dev->sg->pages) { + DRM_ERROR("Requested page range exceedes " + "allocated scatter-gather range!"); + return -E2BIG; + } + + DRM_DEBUG("Creating PCI DMA object using virtual zone starting at %#llx, size %d\n", offset, (uint32_t)size); + INSTANCE_WR(*gpuobj, 0, ((1<<12) | (0<<13) | + (adjust << 20) | + (access << 14) | + (target << 16) | + class)); + INSTANCE_WR(*gpuobj, 1, (uint32_t) size-1); + + + /*write starting at the third dword*/ + instance_offset = 2; + + /*for each PAGE, get its bus address, fill in the page table entry, and advance*/ + for (i = 0; i < page_count; i++) { + if (dev->sg->busaddr[idx] == 0) { + dev->sg->busaddr[idx] = + pci_map_page(dev->pdev, + dev->sg->pagelist[idx], + 0, + PAGE_SIZE, + DMA_BIDIRECTIONAL); + + if (dma_mapping_error(dev->sg->busaddr[idx])) { + return -ENOMEM; + } + } + + frame = (uint32_t) dev->sg->busaddr[idx]; + INSTANCE_WR(*gpuobj, instance_offset, + frame | pte_flags); + + idx++; + instance_offset ++; + } + } + } else { + uint32_t flags0, flags5; + + if (target == NV_DMA_TARGET_VIDMEM) { + flags0 = 0x00190000; + flags5 = 0x00010000; + } else { + flags0 = 0x7fc00000; + flags5 = 0x00080000; + } + + INSTANCE_WR(*gpuobj, 0, flags0 | class); + INSTANCE_WR(*gpuobj, 1, offset + size - 1); + INSTANCE_WR(*gpuobj, 2, offset); + INSTANCE_WR(*gpuobj, 5, flags5); + } + + (*gpuobj)->engine = NVOBJ_ENGINE_SW; + (*gpuobj)->class = class; + return 0; +} + +int +nouveau_gpuobj_gart_dma_new(struct nouveau_channel *chan, + uint64_t offset, uint64_t size, int access, + struct nouveau_gpuobj **gpuobj, + uint32_t *o_ret) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + + if (dev_priv->gart_info.type == NOUVEAU_GART_AGP || + (dev_priv->card_type >= NV_50 && + dev_priv->gart_info.type == NOUVEAU_GART_SGDMA)) { + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, + offset, size, access, + NV_DMA_TARGET_AGP, gpuobj); + if (o_ret) + *o_ret = 0; + } else + if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA) { + *gpuobj = dev_priv->gart_info.sg_ctxdma; + if (offset & ~0xffffffffULL) { + DRM_ERROR("obj offset exceeds 32-bits\n"); + return -EINVAL; + } + if (o_ret) + *o_ret = (uint32_t)offset; + ret = (*gpuobj != NULL) ? 0 : -EINVAL; + } else { + DRM_ERROR("Invalid GART type %d\n", dev_priv->gart_info.type); + return -EINVAL; + } + + return ret; +} + +/* 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? +*/ +int +nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, + struct nouveau_gpuobj **gpuobj) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + + DRM_DEBUG("ch%d class=0x%04x\n", chan->id, class); + + ret = nouveau_gpuobj_new(dev, chan, + nouveau_gpuobj_class_instmem_size(dev, class), + 16, + NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, + gpuobj); + if (ret) { + DRM_ERROR("Error creating gpuobj: %d\n", ret); + return ret; + } + + if (dev_priv->card_type >= NV_50) { + INSTANCE_WR(*gpuobj, 0, class); + INSTANCE_WR(*gpuobj, 5, 0x00010000); + } else { + switch (class) { + case NV_CLASS_NULL: + INSTANCE_WR(*gpuobj, 0, 0x00001030); + INSTANCE_WR(*gpuobj, 1, 0xFFFFFFFF); + break; + default: + if (dev_priv->card_type >= NV_40) { + INSTANCE_WR(*gpuobj, 0, class); +#ifdef __BIG_ENDIAN + INSTANCE_WR(*gpuobj, 2, 0x01000000); +#endif + } else { +#ifdef __BIG_ENDIAN + INSTANCE_WR(*gpuobj, 0, class | 0x00080000); +#else + INSTANCE_WR(*gpuobj, 0, class); +#endif + } + } + } + + (*gpuobj)->engine = NVOBJ_ENGINE_GR; + (*gpuobj)->class = class; + return 0; +} + +static int +nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *pramin = NULL; + int size, base, ret; + + DRM_DEBUG("ch%d\n", chan->id); + + /* Base amount for object storage (4KiB enough?) */ + size = 0x1000; + base = 0; + + /* PGRAPH context */ + + if (dev_priv->card_type == NV_50) { + /* Various fixed table thingos */ + size += 0x1400; /* mostly unknown stuff */ + size += 0x4000; /* vm pd */ + base = 0x6000; + /* RAMHT, not sure about setting size yet, 32KiB to be safe */ + size += 0x8000; + /* RAMFC */ + size += 0x1000; + /* PGRAPH context */ + size += 0x60000; + } + + DRM_DEBUG("ch%d PRAMIN size: 0x%08x bytes, base alloc=0x%08x\n", + chan->id, size, base); + ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, size, 0x1000, 0, + &chan->ramin); + if (ret) { + DRM_ERROR("Error allocating channel PRAMIN: %d\n", ret); + return ret; + } + pramin = chan->ramin->gpuobj; + + ret = nouveau_mem_init_heap(&chan->ramin_heap, + pramin->im_pramin->start + base, size); + if (ret) { + DRM_ERROR("Error creating PRAMIN heap: %d\n", ret); + nouveau_gpuobj_ref_del(dev, &chan->ramin); + return ret; + } + + return 0; +} + +int +nouveau_gpuobj_channel_init(struct nouveau_channel *chan, + uint32_t vram_h, uint32_t tt_h) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *vram = NULL, *tt = NULL; + int ret, i; + + INIT_LIST_HEAD(&chan->ramht_refs); + + DRM_DEBUG("ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); + + /* Reserve a block of PRAMIN for the channel + *XXX: maybe on card_type == NV_50) { + ret = nouveau_gpuobj_channel_init_pramin(chan); + if (ret) + return ret; + } + + /* NV50 VM, point offset 0-512MiB at shared PCIEGART table */ + if (dev_priv->card_type >= NV_50) { + uint32_t vm_offset; + + vm_offset = (dev_priv->chipset & 0xf0) == 0x50 ? 0x1400 : 0x200; + vm_offset += chan->ramin->gpuobj->im_pramin->start; + if ((ret = nouveau_gpuobj_new_fake(dev, vm_offset, ~0, 0x4000, + 0, &chan->vm_pd, NULL))) + return ret; + for (i=0; i<0x4000; i+=8) { + INSTANCE_WR(chan->vm_pd, (i+0)/4, 0x00000000); + INSTANCE_WR(chan->vm_pd, (i+4)/4, 0xdeadcafe); + } + + if ((ret = nouveau_gpuobj_ref_add(dev, NULL, 0, + dev_priv->gart_info.sg_ctxdma, + &chan->vm_gart_pt))) + return ret; + INSTANCE_WR(chan->vm_pd, (0+0)/4, + chan->vm_gart_pt->instance | 0x03); + INSTANCE_WR(chan->vm_pd, (0+4)/4, 0x00000000); + } + + /* RAMHT */ + if (dev_priv->card_type < NV_50) { + ret = nouveau_gpuobj_ref_add(dev, NULL, 0, dev_priv->ramht, + &chan->ramht); + if (ret) + return ret; + } else { + ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, + 0x8000, 16, + NVOBJ_FLAG_ZERO_ALLOC, + &chan->ramht); + if (ret) + return ret; + } + + /* VRAM ctxdma */ + if ((ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, + 0, dev_priv->fb_available_size, + NV_DMA_ACCESS_RW, + NV_DMA_TARGET_VIDMEM, &vram))) { + DRM_ERROR("Error creating VRAM ctxdma: %d\n", ret); + return ret; + } + + if ((ret = nouveau_gpuobj_ref_add(dev, chan, vram_h, vram, NULL))) { + DRM_ERROR("Error referencing VRAM ctxdma: %d\n", ret); + return ret; + } + + /* TT memory ctxdma */ + if (dev_priv->gart_info.type != NOUVEAU_GART_NONE) { + ret = nouveau_gpuobj_gart_dma_new(chan, 0, + dev_priv->gart_info.aper_size, + NV_DMA_ACCESS_RW, &tt, NULL); + } else + if (dev_priv->pci_heap) { + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, + 0, dev->sg->pages * PAGE_SIZE, + NV_DMA_ACCESS_RW, + NV_DMA_TARGET_PCI_NONLINEAR, &tt); + } else { + DRM_ERROR("Invalid GART type %d\n", dev_priv->gart_info.type); + ret = -EINVAL; + } + + if (ret) { + DRM_ERROR("Error creating TT ctxdma: %d\n", ret); + return ret; + } + + ret = nouveau_gpuobj_ref_add(dev, chan, tt_h, tt, NULL); + if (ret) { + DRM_ERROR("Error referencing TT ctxdma: %d\n", ret); + return ret; + } + + return 0; +} + +void +nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct list_head *entry, *tmp; + struct nouveau_gpuobj_ref *ref; + + DRM_DEBUG("ch%d\n", chan->id); + + list_for_each_safe(entry, tmp, &chan->ramht_refs) { + ref = list_entry(entry, struct nouveau_gpuobj_ref, list); + + nouveau_gpuobj_ref_del(dev, &ref); + } + + nouveau_gpuobj_ref_del(dev, &chan->ramht); + + nouveau_gpuobj_del(dev, &chan->vm_pd); + nouveau_gpuobj_ref_del(dev, &chan->vm_gart_pt); + + if (chan->ramin_heap) + nouveau_mem_takedown(&chan->ramin_heap); + if (chan->ramin) + nouveau_gpuobj_ref_del(dev, &chan->ramin); + +} + +int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct nouveau_channel *chan; + struct drm_nouveau_grobj_alloc *init = data; + struct nouveau_gpuobj *gr = NULL; + int ret; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan); + + //FIXME: check args, only allow trusted objects to be created + + if (init->handle == ~0) + return -EINVAL; + + if (nouveau_gpuobj_ref_find(chan, init->handle, NULL) == 0) + return -EEXIST; + + ret = nouveau_gpuobj_gr_new(chan, init->class, &gr); + if (ret) { + DRM_ERROR("Error creating gr object: %d (%d/0x%08x)\n", + ret, init->channel, init->handle); + return ret; + } + + if ((ret = nouveau_gpuobj_ref_add(dev, chan, init->handle, gr, NULL))) { + DRM_ERROR("Error referencing gr object: %d (%d/0x%08x\n)", + ret, init->channel, init->handle); + nouveau_gpuobj_del(dev, &gr); + return ret; + } + + return 0; +} + +int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_gpuobj_free *objfree = data; + struct nouveau_gpuobj_ref *ref; + struct nouveau_channel *chan; + int ret; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan); + + if ((ret = nouveau_gpuobj_ref_find(chan, objfree->handle, &ref))) + return ret; + nouveau_gpuobj_ref_del(dev, &ref); + + return 0; +} + diff --git a/drivers/char/drm/nouveau_reg.h b/drivers/char/drm/nouveau_reg.h new file mode 100644 index 0000000..a1895c3 --- /dev/null +++ b/drivers/char/drm/nouveau_reg.h @@ -0,0 +1,538 @@ + + +#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 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 +/*The following is not a real value used by nvidia cards, it's changed by nouveau_object_dma_create*/ +#define NV_DMA_TARGET_PCI_NONLINEAR 8 + +/* 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 128 +#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 NV50_FIFO_REGS_SIZE 0x2000 +#define NV50_FIFO_REGS(i) (0x00c00000+i*NV50_FIFO_REGS_SIZE) +# define NV50_FIFO_REGS_DMAPUT(i) (NV50_FIFO_REGS(i)+0x40) +# define NV50_FIFO_REGS_DMAGET(i) (NV50_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 + +/* probably PMC ? */ +#define NV50_PUNK_BAR0_PRAMIN 0x00001700 +#define NV50_PUNK_BAR_CFG_BASE 0x00001704 +#define NV50_PUNK_BAR_CFG_BASE_VALID (1<<30) +#define NV50_PUNK_BAR1_CTXDMA 0x00001708 +#define NV50_PUNK_BAR1_CTXDMA_VALID (1<<31) +#define NV50_PUNK_BAR3_CTXDMA 0x0000170C +#define NV50_PUNK_BAR3_CTXDMA_VALID (1<<31) +#define NV50_PUNK_UNK1710 0x00001710 + +#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_NSTATUS 0x00400104 +# define NV03_PGRAPH_NSTATUS_STATE_IN_USE (1<<23) +# define NV03_PGRAPH_NSTATUS_INVALID_STATE (1<<24) +# define NV03_PGRAPH_NSTATUS_BAD_ARGUMENT (1<<25) +# define NV03_PGRAPH_NSTATUS_PROTECTION_FAULT (1<<26) +#define NV03_PGRAPH_NSOURCE 0x00400108 +# define NV03_PGRAPH_NSOURCE_NOTIFICATION (1<< 0) +# define NV03_PGRAPH_NSOURCE_DATA_ERROR (1<< 1) +# define NV03_PGRAPH_NSOURCE_PROTECTION_ERROR (1<< 2) +# define NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION (1<< 3) +# define NV03_PGRAPH_NSOURCE_LIMIT_COLOR (1<< 4) +# define NV03_PGRAPH_NSOURCE_LIMIT_ZETA (1<< 5) +# define NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD (1<< 6) +# define NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION (1<< 7) +# define NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION (1<< 8) +# define NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION (1<< 9) +# define NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION (1<<10) +# define NV03_PGRAPH_NSOURCE_STATE_INVALID (1<<11) +# define NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY (1<<12) +# define NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE (1<<13) +# define NV03_PGRAPH_NSOURCE_METHOD_CNT (1<<14) +# define NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION (1<<15) +# define NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION (1<<16) +# define NV03_PGRAPH_NSOURCE_DMA_WIDTH_A (1<<17) +# define NV03_PGRAPH_NSOURCE_DMA_WIDTH_B (1<<18) +#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 NV40_PGRAPH_CTXCTL_0304 0x00400304 +#define NV40_PGRAPH_CTXCTL_0304_XFER_CTX 0x00000001 +#define NV40_PGRAPH_CTXCTL_UCODE_STAT 0x00400308 +#define NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_MASK 0xff000000 +#define NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT 24 +#define NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK 0x00ffffff +#define NV40_PGRAPH_CTXCTL_0310 0x00400310 +#define NV40_PGRAPH_CTXCTL_0310_XFER_SAVE 0x00000020 +#define NV40_PGRAPH_CTXCTL_0310_XFER_LOAD 0x00000040 +#define NV40_PGRAPH_CTXCTL_030C 0x0040030c +#define NV40_PGRAPH_CTXCTL_UCODE_INDEX 0x00400324 +#define NV40_PGRAPH_CTXCTL_UCODE_DATA 0x00400328 +#define NV40_PGRAPH_CTXCTL_CUR 0x0040032c +#define NV40_PGRAPH_CTXCTL_CUR_LOADED 0x01000000 +#define NV40_PGRAPH_CTXCTL_CUR_INST_MASK 0x000FFFFF +#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 NV03_PGRAPH_STATUS 0x004006B0 +#define NV04_PGRAPH_STATUS 0x00400700 +#define NV04_PGRAPH_TRAPPED_ADDR 0x00400704 +#define NV04_PGRAPH_TRAPPED_DATA 0x00400708 +#define NV04_PGRAPH_SURFACE 0x0040070C +#define NV10_PGRAPH_TRAPPED_DATA_HIGH 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 NV20_PGRAPH_CHANNEL_CTX_POINTER 0x00400784 +#define NV10_PGRAPH_CHANNEL_CTX_POINTER 0x00400788 +#define NV20_PGRAPH_CHANNEL_CTX_XFER 0x00400788 +#define NV20_PGRAPH_CHANNEL_CTX_XFER_LOAD 0x00000001 +#define NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE 0x00000002 +#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 NV50_PFIFO_CTX_TABLE(c) (0x2600+(c)*4) +#define NV50_PFIFO_CTX_TABLE__SIZE 128 +#define NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED (1<<31) +#define NV50_PFIFO_CTX_TABLE_UNK30_BAD (1<<30) +#define NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80 0x0FFFFFFF +#define NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84 0x00FFFFFF +#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 NV04_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_STATE 0x0C +#define NV04_RAMFC_DMA_FETCH 0x10 +#define NV04_RAMFC_ENGINE 0x14 +#define NV04_RAMFC_PULL1_ENGINE 0x18 + +#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_UNK_4C 0x4C +#define NV40_RAMFC_UNK_50 0x50 + diff --git a/drivers/char/drm/nouveau_sgdma.c b/drivers/char/drm/nouveau_sgdma.c new file mode 100644 index 0000000..3b3d8f9 --- /dev/null +++ b/drivers/char/drm/nouveau_sgdma.c @@ -0,0 +1,311 @@ +#include "drmP.h" +#include "nouveau_drv.h" + +#define NV_CTXDMA_PAGE_SHIFT 12 +#define NV_CTXDMA_PAGE_SIZE (1 << NV_CTXDMA_PAGE_SHIFT) +#define NV_CTXDMA_PAGE_MASK (NV_CTXDMA_PAGE_SIZE - 1) + +struct nouveau_sgdma_be { +// struct drm_ttm_backend backend; + struct drm_device *dev; + + int pages; + int pages_populated; + dma_addr_t *pagelist; + int is_bound; + + unsigned int pte_start; +}; + +static void nouveau_sgdma_clear(struct nouveau_sgdma_be *nvbe); +static int nouveau_sgdma_unbind(struct nouveau_sgdma_be *nvbe); + +static int +nouveau_sgdma_populate(struct nouveau_sgdma_be *nvbe, unsigned long num_pages, + struct page **pages) +{ + int p, d, o; + + DRM_DEBUG("num_pages = %ld\n", num_pages); + + if (nvbe->pagelist) + return -EINVAL; + nvbe->pages = (num_pages << PAGE_SHIFT) >> NV_CTXDMA_PAGE_SHIFT; + nvbe->pagelist = drm_alloc(nvbe->pages*sizeof(dma_addr_t), + DRM_MEM_PAGES); + + nvbe->pages_populated = d = 0; + for (p = 0; p < num_pages; p++) { + for (o = 0; o < PAGE_SIZE; o += NV_CTXDMA_PAGE_SIZE) { + nvbe->pagelist[d] = pci_map_page(nvbe->dev->pdev, + pages[p], o, + NV_CTXDMA_PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(nvbe->pagelist[d])) { + nouveau_sgdma_clear(nvbe); + DRM_ERROR("pci_map_page failed\n"); + return -EINVAL; + } + nvbe->pages_populated = ++d; + } + } + + return 0; +} + +static void +nouveau_sgdma_clear(struct nouveau_sgdma_be *nvbe) +{ + int d; + + DRM_DEBUG("\n"); + + if (nvbe && nvbe->pagelist) { + if (nvbe->is_bound) + nouveau_sgdma_unbind(nvbe); + + for (d = 0; d < nvbe->pages_populated; d++) { + pci_unmap_page(nvbe->dev->pdev, nvbe->pagelist[d], + NV_CTXDMA_PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + } + drm_free(nvbe->pagelist, nvbe->pages*sizeof(dma_addr_t), + DRM_MEM_PAGES); + } +} + +static int +nouveau_sgdma_bind(struct nouveau_sgdma_be *nvbe, unsigned long pg_start, + int cached) +{ + struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; + struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; + uint64_t offset = (pg_start << PAGE_SHIFT); + uint32_t i; + + DRM_DEBUG("pg=0x%lx (0x%llx), cached=%d\n", pg_start, offset, cached); + + if (offset & NV_CTXDMA_PAGE_MASK) + return -EINVAL; + nvbe->pte_start = (offset >> NV_CTXDMA_PAGE_SHIFT); + if (dev_priv->card_type < NV_50) + nvbe->pte_start += 2; /* skip ctxdma header */ + + for (i = nvbe->pte_start; i < nvbe->pte_start + nvbe->pages; i++) { + uint64_t pteval = nvbe->pagelist[i - nvbe->pte_start]; + + if (pteval & NV_CTXDMA_PAGE_MASK) { + DRM_ERROR("Bad pteval 0x%llx\n", pteval); + return -EINVAL; + } + + if (dev_priv->card_type < NV_50) { + INSTANCE_WR(gpuobj, i, pteval | 3); + } else { + INSTANCE_WR(gpuobj, (i<<1)+0, pteval | 0x21); + INSTANCE_WR(gpuobj, (i<<1)+1, 0x00000000); + } + } + + nvbe->is_bound = 1; + return 0; +} + +static int nouveau_sgdma_unbind(struct nouveau_sgdma_be *nvbe) +{ + struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; + + DRM_DEBUG("\n"); + + if (nvbe->is_bound) { + struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; + unsigned int pte; + + pte = nvbe->pte_start; + while (pte < (nvbe->pte_start + nvbe->pages)) { + uint64_t pteval = dev_priv->gart_info.sg_dummy_bus; + + if (dev_priv->card_type < NV_50) { + INSTANCE_WR(gpuobj, pte, pteval | 3); + } else { + INSTANCE_WR(gpuobj, (pte<<1)+0, 0x00000010); + INSTANCE_WR(gpuobj, (pte<<1)+1, 0x00000004); + } + + pte++; + } + + nvbe->is_bound = 0; + } + + return 0; +} + +static void +nouveau_sgdma_destroy(struct nouveau_sgdma_be *nvbe) +{ + DRM_DEBUG("\n"); + if (nvbe) { + if (nvbe->pagelist) + nouveau_sgdma_clear(nvbe); + drm_free(nvbe, sizeof(*nvbe), DRM_MEM_DRIVER); + } +} + +struct nouveau_sgdma_be * +nouveau_sgdma_init_ttm(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_sgdma_be *nvbe; + + if (!dev_priv->gart_info.sg_ctxdma) + return NULL; + + nvbe = drm_calloc(1, sizeof(*nvbe), DRM_MEM_DRIVER); + if (!nvbe) + return NULL; + + nvbe->dev = dev; + + return nvbe; +} + +int +nouveau_sgdma_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj = NULL; + uint32_t aper_size, obj_size; + int i, ret; + + if (dev_priv->card_type < NV_50) { + aper_size = (64 * 1024 * 1024); + obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4; + obj_size += 8; /* ctxdma header */ + } else { + /* 1 entire VM page table */ + aper_size = (512 * 1024 * 1024); + obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 8; + } + + if ((ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16, + NVOBJ_FLAG_ALLOW_NO_REFS | + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, &gpuobj))) { + DRM_ERROR("Error creating sgdma object: %d\n", ret); + return ret; + } + + if (dev_priv->card_type < NV_50) { + dev_priv->gart_info.sg_dummy_page = + alloc_page(GFP_KERNEL|__GFP_DMA32); + SetPageLocked(dev_priv->gart_info.sg_dummy_page); + dev_priv->gart_info.sg_dummy_bus = + pci_map_page(dev->pdev, + dev_priv->gart_info.sg_dummy_page, 0, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + + /* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and + * confirmed to work on c51. Perhaps means NV_DMA_TARGET_PCIE + * on those cards? */ + INSTANCE_WR(gpuobj, 0, NV_CLASS_DMA_IN_MEMORY | + (1 << 12) /* PT present */ | + (0 << 13) /* PT *not* linear */ | + (NV_DMA_ACCESS_RW << 14) | + (NV_DMA_TARGET_PCI << 16)); + INSTANCE_WR(gpuobj, 1, aper_size - 1); + for (i=2; i<2+(aper_size>>12); i++) { + INSTANCE_WR(gpuobj, i, + dev_priv->gart_info.sg_dummy_bus | 3); + } + } else { + for (i=0; igart_info.type = NOUVEAU_GART_SGDMA; + dev_priv->gart_info.aper_base = 0; + dev_priv->gart_info.aper_size = aper_size; + dev_priv->gart_info.sg_ctxdma = gpuobj; + return 0; +} + +void +nouveau_sgdma_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->gart_info.sg_dummy_page) { + pci_unmap_page(dev->pdev, dev_priv->gart_info.sg_dummy_bus, + NV_CTXDMA_PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + //unlock_page(dev_priv->gart_info.sg_dummy_page); + __free_page(dev_priv->gart_info.sg_dummy_page); + dev_priv->gart_info.sg_dummy_page = NULL; + dev_priv->gart_info.sg_dummy_bus = 0; + } + + nouveau_gpuobj_del(dev, &dev_priv->gart_info.sg_ctxdma); +} + +int +nouveau_sgdma_nottm_hack_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_sgdma_be *nvbe; + struct drm_scatter_gather sgreq; + int ret; + + nvbe = nouveau_sgdma_init_ttm(dev); + if (!nvbe) + return -ENOMEM; + + /* Hack the aperture size down to the amount of system memory + * we're going to bind into it. + */ + if (dev_priv->gart_info.aper_size > 32*1024*1024) + dev_priv->gart_info.aper_size = 32*1024*1024; + + sgreq.size = dev_priv->gart_info.aper_size; + if ((ret = drm_sg_alloc(dev, &sgreq))) { + DRM_ERROR("drm_sg_alloc failed: %d\n", ret); + return ret; + } + dev_priv->gart_info.sg_handle = sgreq.handle; + + if ((ret = nouveau_sgdma_populate(nvbe, dev->sg->pages, dev->sg->pagelist))) { + DRM_ERROR("failed populate: %d\n", ret); + return ret; + } + + if ((ret = nouveau_sgdma_bind(nvbe, 0, 0))) { + DRM_ERROR("failed bind: %d\n", ret); + return ret; + } + + return 0; +} + +void +nouveau_sgdma_nottm_hack_takedown(struct drm_device *dev) +{ +} + +int +nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; + int pte; + + pte = (offset >> NV_CTXDMA_PAGE_SHIFT); + if (dev_priv->card_type < NV_50) { + *page = INSTANCE_RD(gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK; + return 0; + } + + DRM_ERROR("Unimplemented on NV50\n"); + return -EINVAL; +} + diff --git a/drivers/char/drm/nouveau_state.c b/drivers/char/drm/nouveau_state.c new file mode 100644 index 0000000..7ab7f7d --- /dev/null +++ b/drivers/char/drm/nouveau_state.c @@ -0,0 +1,569 @@ +/* + * 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 "drmP.h" +#include "drm.h" +#include "drm_sarea.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +static int nouveau_init_card_mappings(struct drm_device *dev) +{ + struct drm_nouveau_private *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 */ + dev_priv->ramin = NULL; + 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; + } + } + + /* On older cards (or if the above failed), create a map covering + * the BAR0 PRAMIN aperture */ + if (!dev_priv->ramin) { + ret = drm_addmap(dev, + drm_get_resource_start(dev, 0) + NV_RAMIN, + (1*1024*1024), + _DRM_REGISTERS, _DRM_READ_ONLY, + &dev_priv->ramin); + if (ret) { + DRM_ERROR("Failed to map BAR0 PRAMIN: %d\n", ret); + return ret; + } + } + + return 0; +} + +static int nouveau_stub_init(struct drm_device *dev) { return 0; } +static void nouveau_stub_takedown(struct drm_device *dev) {} +static uint64_t nouveau_stub_timer_read(struct drm_device *dev) { return 0; } + +static int nouveau_init_engine_ptrs(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->Engine; + + switch (dev_priv->chipset & 0xf0) { + case 0x00: + engine->instmem.init = nv04_instmem_init; + engine->instmem.takedown= nv04_instmem_takedown; + engine->instmem.populate = nv04_instmem_populate; + engine->instmem.clear = nv04_instmem_clear; + engine->instmem.bind = nv04_instmem_bind; + engine->instmem.unbind = nv04_instmem_unbind; + engine->mc.init = nv04_mc_init; + engine->mc.takedown = nv04_mc_takedown; + engine->timer.init = nv04_timer_init; + engine->timer.read = nv04_timer_read; + 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->graph.create_context = nv04_graph_create_context; + engine->graph.destroy_context = nv04_graph_destroy_context; + engine->graph.load_context = nv04_graph_load_context; + engine->graph.save_context = nv04_graph_save_context; + engine->fifo.init = nouveau_fifo_init; + engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.create_context = nv04_fifo_create_context; + engine->fifo.destroy_context = nv04_fifo_destroy_context; + engine->fifo.load_context = nv04_fifo_load_context; + engine->fifo.save_context = nv04_fifo_save_context; + break; + case 0x10: + engine->instmem.init = nv04_instmem_init; + engine->instmem.takedown= nv04_instmem_takedown; + engine->instmem.populate = nv04_instmem_populate; + engine->instmem.clear = nv04_instmem_clear; + engine->instmem.bind = nv04_instmem_bind; + engine->instmem.unbind = nv04_instmem_unbind; + engine->mc.init = nv04_mc_init; + engine->mc.takedown = nv04_mc_takedown; + engine->timer.init = nv04_timer_init; + engine->timer.read = nv04_timer_read; + 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->graph.create_context = nv10_graph_create_context; + engine->graph.destroy_context = nv10_graph_destroy_context; + engine->graph.load_context = nv10_graph_load_context; + engine->graph.save_context = nv10_graph_save_context; + engine->fifo.init = nouveau_fifo_init; + engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.create_context = nv10_fifo_create_context; + engine->fifo.destroy_context = nv10_fifo_destroy_context; + engine->fifo.load_context = nv10_fifo_load_context; + engine->fifo.save_context = nv10_fifo_save_context; + break; + case 0x20: + engine->instmem.init = nv04_instmem_init; + engine->instmem.takedown= nv04_instmem_takedown; + engine->instmem.populate = nv04_instmem_populate; + engine->instmem.clear = nv04_instmem_clear; + engine->instmem.bind = nv04_instmem_bind; + engine->instmem.unbind = nv04_instmem_unbind; + engine->mc.init = nv04_mc_init; + engine->mc.takedown = nv04_mc_takedown; + engine->timer.init = nv04_timer_init; + engine->timer.read = nv04_timer_read; + 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->graph.create_context = nv20_graph_create_context; + engine->graph.destroy_context = nv20_graph_destroy_context; + engine->graph.load_context = nv20_graph_load_context; + engine->graph.save_context = nv20_graph_save_context; + engine->fifo.init = nouveau_fifo_init; + engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.create_context = nv10_fifo_create_context; + engine->fifo.destroy_context = nv10_fifo_destroy_context; + engine->fifo.load_context = nv10_fifo_load_context; + engine->fifo.save_context = nv10_fifo_save_context; + break; + case 0x30: + engine->instmem.init = nv04_instmem_init; + engine->instmem.takedown= nv04_instmem_takedown; + engine->instmem.populate = nv04_instmem_populate; + engine->instmem.clear = nv04_instmem_clear; + engine->instmem.bind = nv04_instmem_bind; + engine->instmem.unbind = nv04_instmem_unbind; + engine->mc.init = nv04_mc_init; + engine->mc.takedown = nv04_mc_takedown; + engine->timer.init = nv04_timer_init; + engine->timer.read = nv04_timer_read; + 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->graph.create_context = nv30_graph_create_context; + engine->graph.destroy_context = nv30_graph_destroy_context; + engine->graph.load_context = nv30_graph_load_context; + engine->graph.save_context = nv30_graph_save_context; + engine->fifo.init = nouveau_fifo_init; + engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.create_context = nv10_fifo_create_context; + engine->fifo.destroy_context = nv10_fifo_destroy_context; + engine->fifo.load_context = nv10_fifo_load_context; + engine->fifo.save_context = nv10_fifo_save_context; + break; + case 0x40: + engine->instmem.init = nv04_instmem_init; + engine->instmem.takedown= nv04_instmem_takedown; + engine->instmem.populate = nv04_instmem_populate; + engine->instmem.clear = nv04_instmem_clear; + engine->instmem.bind = nv04_instmem_bind; + engine->instmem.unbind = nv04_instmem_unbind; + engine->mc.init = nv40_mc_init; + engine->mc.takedown = nv40_mc_takedown; + engine->timer.init = nv04_timer_init; + engine->timer.read = nv04_timer_read; + 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->graph.create_context = nv40_graph_create_context; + engine->graph.destroy_context = nv40_graph_destroy_context; + engine->graph.load_context = nv40_graph_load_context; + engine->graph.save_context = nv40_graph_save_context; + engine->fifo.init = nv40_fifo_init; + engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.create_context = nv40_fifo_create_context; + engine->fifo.destroy_context = nv40_fifo_destroy_context; + engine->fifo.load_context = nv40_fifo_load_context; + engine->fifo.save_context = nv40_fifo_save_context; + break; + case 0x50: + case 0x80: /* gotta love NVIDIA's consistency.. */ + engine->instmem.init = nv50_instmem_init; + engine->instmem.takedown= nv50_instmem_takedown; + engine->instmem.populate = nv50_instmem_populate; + engine->instmem.clear = nv50_instmem_clear; + engine->instmem.bind = nv50_instmem_bind; + engine->instmem.unbind = nv50_instmem_unbind; + engine->mc.init = nv50_mc_init; + engine->mc.takedown = nv50_mc_takedown; + engine->timer.init = nouveau_stub_init; + engine->timer.read = nouveau_stub_timer_read; + engine->timer.takedown = nouveau_stub_takedown; + engine->fb.init = nouveau_stub_init; + engine->fb.takedown = nouveau_stub_takedown; + engine->graph.init = nv50_graph_init; + engine->graph.takedown = nv50_graph_takedown; + engine->graph.create_context = nv50_graph_create_context; + engine->graph.destroy_context = nv50_graph_destroy_context; + engine->graph.load_context = nv50_graph_load_context; + engine->graph.save_context = nv50_graph_save_context; + engine->fifo.init = nv50_fifo_init; + engine->fifo.takedown = nv50_fifo_takedown; + engine->fifo.create_context = nv50_fifo_create_context; + engine->fifo.destroy_context = nv50_fifo_destroy_context; + engine->fifo.load_context = nv50_fifo_load_context; + engine->fifo.save_context = nv50_fifo_save_context; + break; + default: + DRM_ERROR("NV%02x unsupported\n", dev_priv->chipset); + return 1; + } + + return 0; +} + +int +nouveau_card_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine; + int ret; + + DRM_DEBUG("prev state = %d\n", dev_priv->init_state); + + if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE) + return 0; + + /* 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; + dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED; + + ret = nouveau_gpuobj_early_init(dev); + if (ret) return ret; + + /* Initialise instance memory, must happen before mem_init so we + * know exactly how much VRAM we're able to use for "normal" + * purposes. + */ + ret = engine->instmem.init(dev); + if (ret) return ret; + + /* Setup the memory manager */ + ret = nouveau_mem_init(dev); + if (ret) return ret; + + ret = nouveau_gpuobj_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; + + /* this call irq_preinstall, register irq handler and + * call irq_postinstall + */ + ret = drm_irq_install(dev); + if (ret) return ret; + + /* what about PVIDEO/PCRTC/PRAMDAC etc? */ + + ret = nouveau_dma_channel_init(dev); + if (ret) return ret; + + dev_priv->init_state = NOUVEAU_CARD_INIT_DONE; + return 0; +} + +static void nouveau_card_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->Engine; + + DRM_DEBUG("prev state = %d\n", dev_priv->init_state); + + if (dev_priv->init_state != NOUVEAU_CARD_INIT_DOWN) { + nouveau_dma_channel_takedown(dev); + + engine->fifo.takedown(dev); + engine->graph.takedown(dev); + engine->fb.takedown(dev); + engine->timer.takedown(dev); + engine->mc.takedown(dev); + + nouveau_sgdma_nottm_hack_takedown(dev); + nouveau_sgdma_takedown(dev); + + nouveau_gpuobj_takedown(dev); + + nouveau_mem_close(dev); + engine->instmem.takedown(dev); + + drm_irq_uninstall(dev); + + nouveau_gpuobj_late_takedown(dev); + + dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN; + } +} + +/* here a client dies, release the stuff that was allocated for its + * file_priv */ +void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + nouveau_fifo_cleanup(dev, file_priv); + nouveau_mem_release(file_priv,dev_priv->fb_heap); + nouveau_mem_release(file_priv,dev_priv->agp_heap); + nouveau_mem_release(file_priv,dev_priv->pci_heap); +} + +/* first module load, setup the mmio/fb mapping */ +int nouveau_firstopen(struct drm_device *dev) +{ + return 0; +} + +int nouveau_load(struct drm_device *dev, unsigned long flags) +{ + struct drm_nouveau_private *dev_priv; + + if (flags==NV_UNKNOWN) + return -EINVAL; + + dev_priv = drm_calloc(1, sizeof(*dev_priv), DRM_MEM_DRIVER); + if (!dev_priv) + return -ENOMEM; + + dev_priv->card_type=flags&NOUVEAU_FAMILY; + dev_priv->flags=flags&NOUVEAU_FLAGS; + dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN; + + dev->dev_private = (void *)dev_priv; + return 0; +} + +void nouveau_lastclose(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + nouveau_card_takedown(dev); + + 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(*dev->dev_private), DRM_MEM_DRIVER); + dev->dev_private = NULL; + return 0; +} + +int +nouveau_ioctl_card_init(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return nouveau_card_init(dev); +} + +int nouveau_ioctl_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_getparam *getparam = data; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + + switch (getparam->param) { + case NOUVEAU_GETPARAM_CHIPSET_ID: + getparam->value = dev_priv->chipset; + break; + 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->gart_info.aper_base; + break; + case NOUVEAU_GETPARAM_PCI_PHYSICAL: + if ( dev -> sg ) + getparam->value=(uint64_t)(void *) dev->sg->virtual; + else + { + DRM_ERROR("Requested PCIGART address, while no PCIGART was created\n"); + return -EINVAL; + } + break; + case NOUVEAU_GETPARAM_FB_SIZE: + getparam->value=dev_priv->fb_available_size; + break; + case NOUVEAU_GETPARAM_AGP_SIZE: + getparam->value=dev_priv->gart_info.aper_size; + break; + default: + DRM_ERROR("unknown parameter %lld\n", getparam->param); + return -EINVAL; + } + + return 0; +} + +int nouveau_ioctl_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_setparam *setparam = data; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + + switch (setparam->param) { + case NOUVEAU_SETPARAM_CMDBUF_LOCATION: + switch (setparam->value) { + case NOUVEAU_MEM_AGP: + case NOUVEAU_MEM_FB: + case NOUVEAU_MEM_PCI: + case NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI_ACCEPTABLE: + break; + default: + DRM_ERROR("invalid CMDBUF_LOCATION value=%lld\n", + setparam->value); + return -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 -EINVAL; + } + + return 0; +} + +/* waits for idle */ +void nouveau_wait_for_idle(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv=dev->dev_private; + switch(dev_priv->card_type) { + case NV_03: + while (NV_READ(NV03_PGRAPH_STATUS)); + break; + case NV_50: + break; + default: { + /* This stuff is more or less a copy of what is seen + * in nv28 kmmio dump. + */ + uint64_t started = dev_priv->Engine.timer.read(dev); + uint64_t stopped = started; + uint32_t status; + do { + uint32_t pmc_e = NV_READ(NV03_PMC_ENABLE); + (void)pmc_e; + status = NV_READ(NV04_PGRAPH_STATUS); + if (!status) + break; + stopped = dev_priv->Engine.timer.read(dev); + /* It'll never wrap anyway... */ + } while (stopped - started < 1000000000ULL); + if (status) + DRM_ERROR("timed out with status 0x%08x\n", + status); + } + } +} + + diff --git a/drivers/char/drm/nv04_fb.c b/drivers/char/drm/nv04_fb.c new file mode 100644 index 0000000..534fb50 --- /dev/null +++ b/drivers/char/drm/nv04_fb.c @@ -0,0 +1,24 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv04_fb_init(struct drm_device *dev) +{ + struct drm_nouveau_private *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(struct drm_device *dev) +{ +} + diff --git a/drivers/char/drm/nv04_fifo.c b/drivers/char/drm/nv04_fifo.c new file mode 100644 index 0000000..d750ced --- /dev/null +++ b/drivers/char/drm/nv04_fifo.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2007 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +#define RAMFC_WR(offset,val) INSTANCE_WR(chan->ramfc->gpuobj, \ + NV04_RAMFC_##offset/4, (val)) +#define RAMFC_RD(offset) INSTANCE_RD(chan->ramfc->gpuobj, \ + NV04_RAMFC_##offset/4) +#define NV04_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV04_RAMFC__SIZE)) +#define NV04_RAMFC__SIZE 32 + +int +nv04_fifo_create_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + + if ((ret = nouveau_gpuobj_new_fake(dev, NV04_RAMFC(chan->id), ~0, + NV04_RAMFC__SIZE, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, + NULL, &chan->ramfc))) + return ret; + + /* Setup initial state */ + RAMFC_WR(DMA_PUT, chan->pushbuf_base); + RAMFC_WR(DMA_GET, chan->pushbuf_base); + RAMFC_WR(DMA_INSTANCE, chan->pushbuf->instance >> 4); + 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 + 0)); + + /* enable the fifo dma operation */ + NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE) | (1<id)); + return 0; +} + +void +nv04_fifo_destroy_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + + NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<id)); + + nouveau_gpuobj_ref_del(dev, &chan->ramfc); +} + +int +nv04_fifo_load_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t tmp; + + NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, (1<<8) | chan->id); + + NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET, RAMFC_RD(DMA_GET)); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT, RAMFC_RD(DMA_PUT)); + + tmp = RAMFC_RD(DMA_INSTANCE); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE, tmp & 0xFFFF); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_DCOUNT, tmp >> 16); + + NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, RAMFC_RD(DMA_STATE)); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_FETCH, RAMFC_RD(DMA_FETCH)); + NV_WRITE(NV04_PFIFO_CACHE1_ENGINE, RAMFC_RD(ENGINE)); + NV_WRITE(NV04_PFIFO_CACHE1_PULL1, RAMFC_RD(PULL1_ENGINE)); + + /* Reset NV04_PFIFO_CACHE1_DMA_CTL_AT_INFO to INVALID */ + tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_CTL) & ~(1<<31); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, tmp); + + return 0; +} + +int +nv04_fifo_save_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t tmp; + + RAMFC_WR(DMA_PUT, NV04_PFIFO_CACHE1_DMA_PUT); + RAMFC_WR(DMA_GET, NV04_PFIFO_CACHE1_DMA_GET); + + tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16; + tmp |= NV_READ(NV04_PFIFO_CACHE1_DMA_INSTANCE); + RAMFC_WR(DMA_INSTANCE, tmp); + + 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)); + + return 0; +} + diff --git a/drivers/char/drm/nv04_graph.c b/drivers/char/drm/nv04_graph.c new file mode 100644 index 0000000..050f6e8 --- /dev/null +++ b/drivers/char/drm/nv04_graph.c @@ -0,0 +1,415 @@ +/* + * 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 "drmP.h" +#include "drm.h" +#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(struct drm_device *dev) +{ + struct drm_nouveau_private *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_create_context(struct nouveau_channel *chan) { + DRM_DEBUG("nv04_graph_context_create %d\n", chan->id); + + memset(chan->pgraph_ctx, 0, sizeof(chan->pgraph_ctx)); + + //dev_priv->fifos[channel].pgraph_ctx_user = channel << 24; + chan->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; +} + +void nv04_graph_destroy_context(struct nouveau_channel *chan) +{ +} + +int nv04_graph_load_context(struct nouveau_channel *chan) +{ + DRM_ERROR("stub!\n"); + return 0; +} + +int nv04_graph_save_context(struct nouveau_channel *chan) +{ + DRM_ERROR("stub!\n"); + return 0; +} + +int nv04_graph_init(struct drm_device *dev) { + struct drm_nouveau_private *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); + + /* Enable PGRAPH interrupts */ + NV_WRITE(NV03_PGRAPH_INTR, 0xFFFFFFFF); + NV_WRITE(NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); + + // 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(struct drm_device *dev) +{ +} + diff --git a/drivers/char/drm/nv04_instmem.c b/drivers/char/drm/nv04_instmem.c new file mode 100644 index 0000000..fed6ff7 --- /dev/null +++ b/drivers/char/drm/nv04_instmem.c @@ -0,0 +1,160 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +static void +nv04_instmem_determine_amount(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i; + + /* Figure out how much instance memory we need */ + if (dev_priv->card_type >= 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_rsvd_vram = (1*1024* 1024); + } else { + /*XXX: what *are* the limits on ramin_rsvd_vram = (512*1024); + } + DRM_DEBUG("RAMIN size: %dKiB\n", dev_priv->ramin_rsvd_vram>>10); + + /* Clear all of it, except the BIOS image that's in the first 64KiB */ + for (i=(64*1024); iramin_rsvd_vram; i+=4) + NV_WI32(i, 0x00000000); +} + +static void +nv04_instmem_configure_fixed_tables(struct drm_device *dev) +{ + struct drm_nouveau_private *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_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_17: + case NV_11: + 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 nv04_instmem_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t offset; + int ret = 0; + + nv04_instmem_determine_amount(dev); + nv04_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; + + /* On my NV4E, there's *something* clobbering the 16KiB just after + * where we setup these fixed tables. No idea what it is just yet, + * so reserve this space on all NV4X cards for now. + */ + if (dev_priv->card_type >= NV_40) + offset += 16*1024; + + ret = nouveau_mem_init_heap(&dev_priv->ramin_heap, + offset, dev_priv->ramin_rsvd_vram - offset); + if (ret) { + dev_priv->ramin_heap = NULL; + DRM_ERROR("Failed to init RAMIN heap\n"); + } + + return ret; +} + +void +nv04_instmem_takedown(struct drm_device *dev) +{ +} + +int +nv04_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, uint32_t *sz) +{ + if (gpuobj->im_backing) + return -EINVAL; + + return 0; +} + +void +nv04_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (gpuobj && gpuobj->im_backing) { + if (gpuobj->im_bound) + dev_priv->Engine.instmem.unbind(dev, gpuobj); + gpuobj->im_backing = NULL; + } +} + +int +nv04_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +{ + if (!gpuobj->im_pramin || gpuobj->im_bound) + return -EINVAL; + + gpuobj->im_bound = 1; + return 0; +} + +int +nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +{ + if (gpuobj->im_bound == 0) + return -EINVAL; + + gpuobj->im_bound = 0; + return 0; +} + diff --git a/drivers/char/drm/nv04_mc.c b/drivers/char/drm/nv04_mc.c new file mode 100644 index 0000000..eee0c50 --- /dev/null +++ b/drivers/char/drm/nv04_mc.c @@ -0,0 +1,23 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv04_mc_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + /* Power up everything, resetting each individual unit will + * be done later if needed. + */ + NV_WRITE(NV03_PMC_ENABLE, 0xFFFFFFFF); + + return 0; +} + +void +nv04_mc_takedown(struct drm_device *dev) +{ +} + diff --git a/drivers/char/drm/nv04_timer.c b/drivers/char/drm/nv04_timer.c new file mode 100644 index 0000000..08a27f4 --- /dev/null +++ b/drivers/char/drm/nv04_timer.c @@ -0,0 +1,45 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv04_timer_init(struct drm_device *dev) +{ + struct drm_nouveau_private *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; +} + +uint64_t +nv04_timer_read(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t low; + /* From kmmio dumps on nv28 this looks like how the blob does this. + * It reads the high dword twice, before and after. + * The only explanation seems to be that the 64-bit timer counter + * advances between high and low dword reads and may corrupt the + * result. Not confirmed. + */ + uint32_t high2 = NV_READ(NV04_PTIMER_TIME_1); + uint32_t high1; + do { + high1 = high2; + low = NV_READ(NV04_PTIMER_TIME_0); + high2 = NV_READ(NV04_PTIMER_TIME_1); + } while(high1 != high2); + return (((uint64_t)high2) << 32) | (uint64_t)low; +} + +void +nv04_timer_takedown(struct drm_device *dev) +{ +} + diff --git a/drivers/char/drm/nv10_fb.c b/drivers/char/drm/nv10_fb.c new file mode 100644 index 0000000..7fff5b3 --- /dev/null +++ b/drivers/char/drm/nv10_fb.c @@ -0,0 +1,26 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv10_fb_init(struct drm_device *dev) +{ + struct drm_nouveau_private *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; iramfc->gpuobj, \ + NV10_RAMFC_##offset/4, (val)) +#define RAMFC_RD(offset) INSTANCE_RD(chan->ramfc->gpuobj, \ + NV10_RAMFC_##offset/4) +#define NV10_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV10_RAMFC__SIZE)) +#define NV10_RAMFC__SIZE ((dev_priv->chipset) >= 0x17 ? 64 : 32) + +int +nv10_fifo_create_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + + if ((ret = nouveau_gpuobj_new_fake(dev, NV10_RAMFC(chan->id), ~0, + NV10_RAMFC__SIZE, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, + NULL, &chan->ramfc))) + return ret; + + /* Fill entries that are seen filled in dumps of nvidia driver just + * after channel's is put into DMA mode + */ + RAMFC_WR(DMA_PUT , chan->pushbuf_base); + RAMFC_WR(DMA_GET , chan->pushbuf_base); + RAMFC_WR(DMA_INSTANCE , chan->pushbuf->instance >> 4); + 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 + 0); + + /* enable the fifo dma operation */ + NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE)|(1<id)); + return 0; +} + +void +nv10_fifo_destroy_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + + NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<id)); + + nouveau_gpuobj_ref_del(dev, &chan->ramfc); +} + +int +nv10_fifo_load_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t tmp; + + NV_WRITE(NV03_PFIFO_CACHE1_PUSH1 , 0x00000100 | chan->id); + + NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET , RAMFC_RD(DMA_GET)); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT , RAMFC_RD(DMA_PUT)); + NV_WRITE(NV10_PFIFO_CACHE1_REF_CNT , RAMFC_RD(REF_CNT)); + + tmp = RAMFC_RD(DMA_INSTANCE); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE , tmp & 0xFFFF); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_DCOUNT , tmp >> 16); + + NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE , RAMFC_RD(DMA_STATE)); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_FETCH , RAMFC_RD(DMA_FETCH)); + NV_WRITE(NV04_PFIFO_CACHE1_ENGINE , RAMFC_RD(ENGINE)); + NV_WRITE(NV04_PFIFO_CACHE1_PULL1 , RAMFC_RD(PULL1_ENGINE)); + + if (dev_priv->chipset >= 0x17) { + NV_WRITE(NV10_PFIFO_CACHE1_ACQUIRE_VALUE, + RAMFC_RD(ACQUIRE_VALUE)); + NV_WRITE(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP, + RAMFC_RD(ACQUIRE_TIMESTAMP)); + NV_WRITE(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT, + RAMFC_RD(ACQUIRE_TIMEOUT)); + NV_WRITE(NV10_PFIFO_CACHE1_SEMAPHORE, + RAMFC_RD(SEMAPHORE)); + NV_WRITE(NV10_PFIFO_CACHE1_DMA_SUBROUTINE, + RAMFC_RD(DMA_SUBROUTINE)); + } + + /* Reset NV04_PFIFO_CACHE1_DMA_CTL_AT_INFO to INVALID */ + tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_CTL) & ~(1<<31); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, tmp); + + return 0; +} + +int +nv10_fifo_save_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t tmp; + + 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)); + + tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_INSTANCE) & 0xFFFF; + tmp |= (NV_READ(NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16); + RAMFC_WR(DMA_INSTANCE , tmp); + + 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)); + + if (dev_priv->chipset >= 0x17) { + 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)); + } + + return 0; +} + diff --git a/drivers/char/drm/nv10_graph.c b/drivers/char/drm/nv10_graph.c new file mode 100644 index 0000000..e470ff0 --- /dev/null +++ b/drivers/char/drm/nv10_graph.c @@ -0,0 +1,777 @@ +/* + * Copyright 2007 Matthieu CASTET + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drm.h" +#include "nouveau_drv.h" + + +static void nv10_praph_pipe(struct drm_device *dev) { + struct drm_nouveau_private *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); +} + +static int nv10_graph_ctx_regs [] = { +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_MISC0, +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(struct drm_device *dev, int reg) +{ + struct drm_nouveau_private *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; +} + +int nv10_graph_load_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + 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], chan->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], chan->pgraph_ctx[i]); + } + NV_WRITE(NV10_PGRAPH_CTX_USER, chan->id << 24); + + return 0; +} + +int nv10_graph_save_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i, j; + + for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++) + chan->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++) + chan->pgraph_ctx[i] = NV_READ(nv17_graph_ctx_regs[j]); + } + + return 0; +} + +void nouveau_nv10_context_switch(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv; + struct nouveau_channel *next, *last; + int chid; + + if (!dev) { + DRM_DEBUG("Invalid drm_device\n"); + return; + } + dev_priv = dev->dev_private; + if (!dev_priv) { + DRM_DEBUG("Invalid drm_nouveau_private\n"); + return; + } + if (!dev_priv->fifos) { + DRM_DEBUG("Invalid drm_nouveau_private->fifos\n"); + return; + } + + chid = (NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 20)&(nouveau_fifo_number(dev)-1); + next = dev_priv->fifos[chid]; + + if (!next) { + DRM_DEBUG("Invalid next channel\n"); + return; + } + + chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); + last = dev_priv->fifos[chid]; + + if (!last) { + DRM_DEBUG("WARNING: Invalid last channel, switch to %x\n", + next->id); + } else { + DRM_INFO("NV: PGRAPH context switch interrupt channel %x -> %x\n", + last->id, next->id); + } + + NV_WRITE(NV04_PGRAPH_FIFO,0x0); + if (last) { + nv10_graph_save_context(last); + } + + 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); + + nv10_graph_load_context(next); + + NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100); + //NV_WRITE(NV10_PGRAPH_CTX_USER, next->id << 24); + NV_WRITE(NV10_PGRAPH_FFINTFC_ST2, NV_READ(NV10_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF); + 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) \ + chan->pgraph_ctx[offset] = val; \ + } while (0) + +int nv10_graph_create_context(struct nouveau_channel *chan) { + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + + DRM_DEBUG("nv10_graph_context_create %d\n", chan->id); + + memset(chan->pgraph_ctx, 0, sizeof(chan->pgraph_ctx)); + + /* mmio trace suggest that should be done in ddx with methods/objects */ +#if 0 + uint32_t tmp, vramsz; + /* 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_ABS_UCLIP_XMIN, 0); + NV_WRITE_CTX(NV03_PGRAPH_ABS_UCLIP_YMIN, 0); + NV_WRITE_CTX(NV03_PGRAPH_ABS_UCLIP_XMAX, 0x7fff); + NV_WRITE_CTX(NV03_PGRAPH_ABS_UCLIP_YMAX, 0x7fff); +#endif + + NV_WRITE_CTX(0x00400e88, 0x08000000); + NV_WRITE_CTX(0x00400e9c, 0x4b7fffff); + NV_WRITE_CTX(NV03_PGRAPH_XY_LOGIC_MISC0, 0x0001ffff); + NV_WRITE_CTX(0x00400e10, 0x00001000); + NV_WRITE_CTX(0x00400e14, 0x00001000); + NV_WRITE_CTX(0x00400e30, 0x00080008); + NV_WRITE_CTX(0x00400e34, 0x00080008); + if (dev_priv->chipset>=0x17) { + /* is it really needed ??? */ + NV_WRITE_CTX(NV10_PGRAPH_DEBUG_4, NV_READ(NV10_PGRAPH_DEBUG_4)); + NV_WRITE_CTX(0x004006b0, NV_READ(0x004006b0)); + NV_WRITE_CTX(0x00400eac, 0x0fff0000); + NV_WRITE_CTX(0x00400eb0, 0x0fff0000); + NV_WRITE_CTX(0x00400ec0, 0x00000080); + NV_WRITE_CTX(0x00400ed0, 0x00000080); + } + + /* for the first channel init the regs */ + if (dev_priv->fifo_alloc_count == 0) + nv10_graph_load_context(chan); + + + //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; +} + +void nv10_graph_destroy_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int chid; + chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); + + /* does this avoid a potential context switch while we are written graph + * reg, or we should mask graph interrupt ??? + */ + NV_WRITE(NV04_PGRAPH_FIFO,0x0); + if (chid == chan->id) { + DRM_INFO("cleanning a channel with graph in current context\n"); + nouveau_wait_for_idle(dev); + DRM_INFO("reseting current graph context\n"); + nv10_graph_create_context(chan); + nv10_graph_load_context(chan); + } + NV_WRITE(NV04_PGRAPH_FIFO,0x1); +} + +int nv10_graph_init(struct drm_device *dev) { + struct drm_nouveau_private *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 , 0xFFFFFFFF); + NV_WRITE(NV03_PGRAPH_INTR_EN, 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); /* 0x25f92ad9 */ + NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x25f92ad9); + NV_WRITE(NV04_PGRAPH_DEBUG_3, 0x55DE0830 | + (1<<29) | + (1<<31)); + if (dev_priv->chipset>=0x17) { + NV_WRITE(NV10_PGRAPH_DEBUG_4, 0x1f000000); + NV_WRITE(0x004006b0, 0x40000020); + } + else + NV_WRITE(NV10_PGRAPH_DEBUG_4, 0x00000000); + + /* 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 "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +#define NV20_GRCTX_SIZE (3529*4) + +int nv20_graph_create_context(struct nouveau_channel *chan) { + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + unsigned int ctx_size = NV20_GRCTX_SIZE; + int ret; + + if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, ctx_size, 16, + NVOBJ_FLAG_ZERO_ALLOC, + &chan->ramin_grctx))) + return ret; + + /* Initialise default context values */ + INSTANCE_WR(chan->ramin_grctx->gpuobj, 10, chan->id<<24); /* CTX_USER */ + + INSTANCE_WR(dev_priv->ctx_table->gpuobj, chan->id, + chan->ramin_grctx->instance >> 4); + return 0; +} + +void nv20_graph_destroy_context(struct nouveau_channel *chan) { + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + + nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); + + INSTANCE_WR(dev_priv->ctx_table->gpuobj, chan->id, 0); +} + +static void nv20_graph_rdi(struct drm_device *dev) { + struct drm_nouveau_private *dev_priv = 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 + */ +int nv20_graph_save_context(struct nouveau_channel *chan) { + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t instance; + + instance = INSTANCE_RD(dev_priv->ctx_table->gpuobj, chan->id); + if (!instance) { + return -EINVAL; + } + if (instance != (chan->ramin_grctx->instance >> 4)) + DRM_ERROR("nv20_graph_save_context : bad instance\n"); + + NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_SIZE, instance); + NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_POINTER, 2 /* save ctx */); + return 0; +} + + +/* Restore the context for a specific channel into PGRAPH + */ +int nv20_graph_load_context(struct nouveau_channel *chan) { + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t instance; + + instance = INSTANCE_RD(dev_priv->ctx_table->gpuobj, chan->id); + if (!instance) { + return -EINVAL; + } + if (instance != (chan->ramin_grctx->instance >> 4)) + DRM_ERROR("nv20_graph_load_context_current : bad instance\n"); + + NV_WRITE(NV10_PGRAPH_CTX_USER, chan->id << 24); + NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_SIZE, instance); + NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_POINTER, 1 /* restore ctx */); + return 0; +} + +void nouveau_nv20_context_switch(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *next, *last; + int chid; + + chid = NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); + next = dev_priv->fifos[chid]; + + chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); + last = dev_priv->fifos[chid]; + + DRM_DEBUG("NV: PGRAPH context switch interrupt channel %x -> %x\n", + last->id, next->id); + + NV_WRITE(NV04_PGRAPH_FIFO,0x0); + + nv20_graph_save_context(last); + + nouveau_wait_for_idle(dev); + + NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10000000); + + nv20_graph_load_context(next); + + nouveau_wait_for_idle(dev); + + if ((NV_READ(NV10_PGRAPH_CTX_USER) >> 24) != next->id) + DRM_ERROR("nouveau_nv20_context_switch : wrong channel restored %x %x!!!\n", next->id, 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(struct drm_device *dev) { + struct drm_nouveau_private *dev_priv = + (struct drm_nouveau_private *)dev->dev_private; + uint32_t tmp, vramsz; + int ret, 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; + if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, + dev_priv->ctx_table_size, 16, + NVOBJ_FLAG_ZERO_ALLOC, + &dev_priv->ctx_table))) + return ret; + + NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_TABLE, + dev_priv->ctx_table->instance >> 4); + + //XXX need to be done and save/restore for each fifo ??? + nv20_graph_rdi(dev); + + NV_WRITE(NV03_PGRAPH_INTR , 0xFFFFFFFF); + NV_WRITE(NV03_PGRAPH_INTR_EN, 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; idev_private; + + nouveau_gpuobj_ref_del(dev, &dev_priv->ctx_table); +} + diff --git a/drivers/char/drm/nv30_graph.c b/drivers/char/drm/nv30_graph.c new file mode 100644 index 0000000..ca43bb9 --- /dev/null +++ b/drivers/char/drm/nv30_graph.c @@ -0,0 +1,2911 @@ +/* + * Based on nv40_graph.c + * Someday this will all go away... + */ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +/* + * There are 4 families : + * NV30 is 0x10de:0x030* (not working, no dump for that one) + * + * NV31 is 0x10de:0x031* + * + * NV34 is 0x10de:0x032* + * + * NV35 is 0x10de:0x033* (NV35 and NV36 are the same) + * NV36 is 0x10de:0x034* + * + * Not seen in the wild, no dumps (probably NV35) : + * NV37 is 0x10de:0x00fc, 0x10de:0x00fd + * NV38 is 0x10de:0x0333, 0x10de:0x00fe + * + */ + + +#define NV31_GRCTX_SIZE (22392) +#define NV34_GRCTX_SIZE (18140) +#define NV35_GRCTX_SIZE (22396) + +static void nv31_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i; + + INSTANCE_WR(ctx, 0x410/4, 0x00000101); + INSTANCE_WR(ctx, 0x424/4, 0x00000111); + INSTANCE_WR(ctx, 0x428/4, 0x00000060); + INSTANCE_WR(ctx, 0x444/4, 0x00000080); + INSTANCE_WR(ctx, 0x448/4, 0xffff0000); + INSTANCE_WR(ctx, 0x44c/4, 0x00000001); + INSTANCE_WR(ctx, 0x460/4, 0x44400000); + INSTANCE_WR(ctx, 0x48c/4, 0xffff0000); + for(i = 0x4e0; i< 0x4e8; i += 4) + INSTANCE_WR(ctx, i/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x4ec/4, 0x00011100); + for(i = 0x508; i< 0x548; i += 4) + INSTANCE_WR(ctx, i/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x550/4, 0x4b7fffff); + INSTANCE_WR(ctx, 0x58c/4, 0x00000080); + INSTANCE_WR(ctx, 0x590/4, 0x30201000); + INSTANCE_WR(ctx, 0x594/4, 0x70605040); + INSTANCE_WR(ctx, 0x598/4, 0xb8a89888); + INSTANCE_WR(ctx, 0x59c/4, 0xf8e8d8c8); + INSTANCE_WR(ctx, 0x5b0/4, 0xb0000000); + for(i = 0x600; i< 0x640; i += 4) + INSTANCE_WR(ctx, i/4, 0x00010588); + for(i = 0x640; i< 0x680; i += 4) + INSTANCE_WR(ctx, i/4, 0x00030303); + for(i = 0x6c0; i< 0x700; i += 4) + INSTANCE_WR(ctx, i/4, 0x0008aae4); + for(i = 0x700; i< 0x740; i += 4) + INSTANCE_WR(ctx, i/4, 0x01012000); + for(i = 0x740; i< 0x780; i += 4) + INSTANCE_WR(ctx, i/4, 0x00080008); + INSTANCE_WR(ctx, 0x85c/4, 0x00040000); + INSTANCE_WR(ctx, 0x860/4, 0x00010000); + for(i = 0x864; i< 0x874; i += 4) + INSTANCE_WR(ctx, i/4, 0x00040004); + INSTANCE_WR(ctx, 0x1f18/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f1c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f20/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f28/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f2c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f30/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f38/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f3c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f40/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f48/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f4c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f50/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f58/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f5c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f60/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f68/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f6c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f70/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f78/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f7c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f80/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f88/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f8c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f90/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f98/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f9c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1fa0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1fa8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1fac/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1fb0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1fb8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1fbc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1fc0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1fc8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1fcc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1fd0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1fd8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1fdc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1fe0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1fe8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1fec/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1ff0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1ff8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1ffc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2000/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2008/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x200c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2010/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2018/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x201c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2020/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2028/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x202c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2030/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2038/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x203c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2040/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2048/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x204c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2050/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2058/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x205c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2060/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2068/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x206c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2070/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2078/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x207c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2080/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2088/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x208c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2090/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2098/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x209c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x20a0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x20a8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x20ac/4, 0x0436086c); + INSTANCE_WR(ctx, 0x20b0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x20b8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x20bc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x20c0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x20c8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x20cc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x20d0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x20d8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x20dc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x20e0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x20e8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x20ec/4, 0x0436086c); + INSTANCE_WR(ctx, 0x20f0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x20f8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x20fc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2100/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2108/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x210c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2110/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2118/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x211c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2120/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2128/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x212c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2130/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2138/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x213c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2140/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2148/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x214c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2150/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2158/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x215c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2160/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2168/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x216c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2170/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2178/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x217c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2180/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2188/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x218c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2190/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2198/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x219c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x21a0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x21a8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x21ac/4, 0x0436086c); + INSTANCE_WR(ctx, 0x21b0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x21b8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x21bc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x21c0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x21c8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x21cc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x21d0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x21d8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x21dc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x21e0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x21e8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x21ec/4, 0x0436086c); + INSTANCE_WR(ctx, 0x21f0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x21f8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x21fc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2200/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2208/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x220c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2210/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2218/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x221c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2220/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2228/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x222c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2230/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2238/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x223c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2240/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2248/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x224c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2250/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2258/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x225c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2260/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2268/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x226c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2270/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2278/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x227c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2280/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2288/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x228c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2290/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2298/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x229c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x22a0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x22a8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x22ac/4, 0x0436086c); + INSTANCE_WR(ctx, 0x22b0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x22b8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x22bc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x22c0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x22c8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x22cc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x22d0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x22d8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x22dc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x22e0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x22e8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x22ec/4, 0x0436086c); + INSTANCE_WR(ctx, 0x22f0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x22f8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x22fc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2300/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2308/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x230c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2310/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2318/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x231c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2320/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2328/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x232c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2330/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2338/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x233c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2340/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2348/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x234c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2350/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2358/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x235c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2360/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2368/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x236c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2370/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2378/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x237c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2380/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2388/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x238c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2390/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2398/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x239c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x23a0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x23a8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x23ac/4, 0x0436086c); + INSTANCE_WR(ctx, 0x23b0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x23b8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x23bc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x23c0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x23c8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x23cc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x23d0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x23d8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x23dc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x23e0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x23e8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x23ec/4, 0x0436086c); + INSTANCE_WR(ctx, 0x23f0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x23f8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x23fc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2400/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2408/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x240c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2410/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2418/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x241c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2420/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2428/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x242c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2430/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2438/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x243c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2440/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2448/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x244c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2450/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2458/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x245c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2460/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2468/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x246c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2470/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2478/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x247c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2480/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2488/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x248c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2490/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2498/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x249c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x24a0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x24a8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x24ac/4, 0x0436086c); + INSTANCE_WR(ctx, 0x24b0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x24b8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x24bc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x24c0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x24c8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x24cc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x24d0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x24d8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x24dc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x24e0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x24e8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x24ec/4, 0x0436086c); + INSTANCE_WR(ctx, 0x24f0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x24f8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x24fc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2500/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2508/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x250c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2510/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2518/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x251c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2520/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2528/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x252c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2530/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2538/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x253c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2540/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2548/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x254c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2550/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2558/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x255c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2560/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2568/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x256c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2570/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2578/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x257c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2580/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2588/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x258c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2590/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2598/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x259c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x25a0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x25a8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x25ac/4, 0x0436086c); + INSTANCE_WR(ctx, 0x25b0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x25b8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x25bc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x25c0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x25c8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x25cc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x25d0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x25d8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x25dc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x25e0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x25e8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x25ec/4, 0x0436086c); + INSTANCE_WR(ctx, 0x25f0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x25f8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x25fc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2600/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2608/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x260c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2610/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2618/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x261c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2620/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2628/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x262c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2630/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2638/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x263c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2640/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2648/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x264c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2650/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2658/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x265c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2660/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2668/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x266c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2670/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2678/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x267c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2680/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2688/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x268c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2690/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2698/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x269c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x26a0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x26a8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x26ac/4, 0x0436086c); + INSTANCE_WR(ctx, 0x26b0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x26b8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x26bc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x26c0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x26c8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x26cc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x26d0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x26d8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x26dc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x26e0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x26e8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x26ec/4, 0x0436086c); + INSTANCE_WR(ctx, 0x26f0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x26f8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x26fc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2700/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2708/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x270c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2710/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2718/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x271c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2720/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2728/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x272c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2730/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2738/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x273c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2740/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2748/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x274c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2750/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2758/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x275c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2760/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2768/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x276c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2770/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2778/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x277c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2780/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2788/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x278c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2790/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2798/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x279c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x27a0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x27a8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x27ac/4, 0x0436086c); + INSTANCE_WR(ctx, 0x27b0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x27b8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x27bc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x27c0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x27c8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x27cc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x27d0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x27d8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x27dc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x27e0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x27e8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x27ec/4, 0x0436086c); + INSTANCE_WR(ctx, 0x27f0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x27f8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x27fc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2800/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2808/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x280c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2810/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2818/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x281c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2820/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2828/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x282c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2830/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2838/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x283c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2840/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2848/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x284c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2850/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2858/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x285c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2860/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2868/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x286c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2870/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2878/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x287c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2880/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2888/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x288c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2890/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2898/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x289c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x28a0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x28a8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x28ac/4, 0x0436086c); + INSTANCE_WR(ctx, 0x28b0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x28b8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x28bc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x28c0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x28c8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x28cc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x28d0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x28d8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x28dc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x28e0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x28e8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x28ec/4, 0x0436086c); + INSTANCE_WR(ctx, 0x28f0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x28f8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x28fc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2900/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2908/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x290c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2910/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2918/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x291c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2920/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2928/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x292c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2930/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2938/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x293c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2940/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2948/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x294c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2950/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2958/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x295c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2960/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2968/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x296c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2970/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2978/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x297c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2980/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2988/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x298c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2990/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2998/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x299c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x29a0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x29a8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x29ac/4, 0x0436086c); + INSTANCE_WR(ctx, 0x29b0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x29b8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x29bc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x29c0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x29c8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x29cc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x29d0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x29d8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x29dc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x29e0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x29e8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x29ec/4, 0x0436086c); + INSTANCE_WR(ctx, 0x29f0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x29f8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x29fc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a00/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a08/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a0c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a10/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a18/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a1c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a20/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a28/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a2c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a30/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a38/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a3c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a40/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a48/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a4c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a50/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a58/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a5c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a60/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a68/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a6c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a70/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a78/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a7c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a80/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a88/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a8c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a90/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a98/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a9c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2aa0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2aa8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2aac/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ab0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2ab8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2abc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ac0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2ac8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2acc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ad0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2ad8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2adc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ae0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2ae8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2aec/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2af0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2af8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2afc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b00/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b08/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b0c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b10/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b18/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b1c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b20/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b28/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b2c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b30/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b38/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b3c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b40/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b48/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b4c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b50/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b58/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b5c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b60/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b68/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b6c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b70/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b78/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b7c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b80/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b88/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b8c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b90/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b98/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b9c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ba0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2ba8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2bac/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2bb0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2bb8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2bbc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2bc0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2bc8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2bcc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2bd0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2bd8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2bdc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2be0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2be8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2bec/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2bf0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2bf8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2bfc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c00/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c08/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c0c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c10/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c18/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c1c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c20/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c28/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c2c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c30/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c38/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c3c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c40/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c48/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c4c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c50/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c58/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c5c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c60/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c68/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c6c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c70/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c78/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c7c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c80/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c88/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c8c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c90/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c98/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c9c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ca0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2ca8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2cac/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2cb0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2cb8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2cbc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2cc0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2cc8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2ccc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2cd0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2cd8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2cdc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ce0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2ce8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2cec/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2cf0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2cf8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2cfc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d00/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d08/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d0c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d10/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d18/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d1c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d20/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d28/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d2c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d30/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d38/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d3c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d40/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d48/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d4c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d50/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d58/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d5c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d60/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d68/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d6c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d70/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d78/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d7c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d80/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d88/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d8c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d90/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d98/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d9c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2da0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2da8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2dac/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2db0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2db8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2dbc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2dc0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2dc8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2dcc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2dd0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2dd8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2ddc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2de0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2de8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2dec/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2df0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2df8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2dfc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e00/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e08/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e0c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e10/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e18/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e1c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e20/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e28/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e2c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e30/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e38/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e3c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e40/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e48/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e4c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e50/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e58/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e5c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e60/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e68/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e6c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e70/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e78/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e7c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e80/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e88/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e8c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e90/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e98/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e9c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ea0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2ea8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2eac/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2eb0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2eb8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2ebc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ec0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2ec8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2ecc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ed0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2ed8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2edc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ee0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2ee8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2eec/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ef0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2ef8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2efc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f00/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f08/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f0c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f10/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f18/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f1c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f20/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f28/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f2c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f30/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f38/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f3c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f40/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f48/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f4c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f50/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f58/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f5c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f60/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f68/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f6c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f70/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f78/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f7c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f80/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f88/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f8c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f90/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f98/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f9c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2fa0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2fa8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2fac/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2fb0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2fb8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2fbc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2fc0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2fc8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2fcc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2fd0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2fd8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2fdc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2fe0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2fe8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2fec/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ff0/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2ff8/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2ffc/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3000/4, 0x000c001b); + INSTANCE_WR(ctx, 0x3008/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x300c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3010/4, 0x000c001b); + INSTANCE_WR(ctx, 0x3018/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x301c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3020/4, 0x000c001b); + INSTANCE_WR(ctx, 0x3028/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x302c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3030/4, 0x000c001b); + INSTANCE_WR(ctx, 0x3038/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x303c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3040/4, 0x000c001b); + INSTANCE_WR(ctx, 0x3048/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x304c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3050/4, 0x000c001b); + INSTANCE_WR(ctx, 0x3058/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x305c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3060/4, 0x000c001b); + INSTANCE_WR(ctx, 0x3068/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x306c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3070/4, 0x000c001b); + INSTANCE_WR(ctx, 0x3078/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x307c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3080/4, 0x000c001b); + INSTANCE_WR(ctx, 0x3088/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x308c/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3090/4, 0x000c001b); + for(i = 0x30b8; i< 0x30c8; i += 4) + INSTANCE_WR(ctx, i/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x344c/4, 0x3f800000); + INSTANCE_WR(ctx, 0x3808/4, 0x3f800000); + INSTANCE_WR(ctx, 0x381c/4, 0x3f800000); + INSTANCE_WR(ctx, 0x3848/4, 0x40000000); + INSTANCE_WR(ctx, 0x384c/4, 0x3f800000); + INSTANCE_WR(ctx, 0x3850/4, 0x3f000000); + INSTANCE_WR(ctx, 0x3858/4, 0x40000000); + INSTANCE_WR(ctx, 0x385c/4, 0x3f800000); + INSTANCE_WR(ctx, 0x3864/4, 0xbf800000); + INSTANCE_WR(ctx, 0x386c/4, 0xbf800000);} + +static void nv34_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i; + + INSTANCE_WR(ctx, 0x40c/4, 0x01000101); + 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, 0x480/4, 0xffff0000); + for(i = 0x4d4; i< 0x4dc; i += 4) + INSTANCE_WR(ctx, i/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x4e0/4, 0x00011100); + for(i = 0x4fc; i< 0x53c; i += 4) + INSTANCE_WR(ctx, i/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x544/4, 0x4b7fffff); + INSTANCE_WR(ctx, 0x57c/4, 0x00000080); + INSTANCE_WR(ctx, 0x580/4, 0x30201000); + INSTANCE_WR(ctx, 0x584/4, 0x70605040); + INSTANCE_WR(ctx, 0x588/4, 0xb8a89888); + INSTANCE_WR(ctx, 0x58c/4, 0xf8e8d8c8); + INSTANCE_WR(ctx, 0x5a0/4, 0xb0000000); + for(i = 0x5f0; i< 0x630; i += 4) + INSTANCE_WR(ctx, i/4, 0x00010588); + for(i = 0x630; i< 0x670; i += 4) + INSTANCE_WR(ctx, i/4, 0x00030303); + for(i = 0x6b0; i< 0x6f0; i += 4) + INSTANCE_WR(ctx, i/4, 0x0008aae4); + for(i = 0x6f0; i< 0x730; i += 4) + INSTANCE_WR(ctx, i/4, 0x01012000); + for(i = 0x730; i< 0x770; i += 4) + INSTANCE_WR(ctx, i/4, 0x00080008); + INSTANCE_WR(ctx, 0x850/4, 0x00040000); + INSTANCE_WR(ctx, 0x854/4, 0x00010000); + for(i = 0x858; i< 0x868; i += 4) + INSTANCE_WR(ctx, i/4, 0x00040004); + INSTANCE_WR(ctx, 0x15ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x15b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x15b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x15bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x15c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x15c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x15cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x15d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x15d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x15dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x15e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x15e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x15ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x15f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x15f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x15fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1600/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1604/4, 0x000c001b); + INSTANCE_WR(ctx, 0x160c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1610/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1614/4, 0x000c001b); + INSTANCE_WR(ctx, 0x161c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1620/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1624/4, 0x000c001b); + INSTANCE_WR(ctx, 0x162c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1630/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1634/4, 0x000c001b); + INSTANCE_WR(ctx, 0x163c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1640/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1644/4, 0x000c001b); + INSTANCE_WR(ctx, 0x164c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1650/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1654/4, 0x000c001b); + INSTANCE_WR(ctx, 0x165c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1660/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1664/4, 0x000c001b); + INSTANCE_WR(ctx, 0x166c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1670/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1674/4, 0x000c001b); + INSTANCE_WR(ctx, 0x167c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1680/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1684/4, 0x000c001b); + INSTANCE_WR(ctx, 0x168c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1690/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1694/4, 0x000c001b); + INSTANCE_WR(ctx, 0x169c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x16a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x16a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x16ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x16b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x16b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x16bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x16c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x16c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x16cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x16d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x16d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x16dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x16e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x16e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x16ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x16f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x16f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x16fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1700/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1704/4, 0x000c001b); + INSTANCE_WR(ctx, 0x170c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1710/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1714/4, 0x000c001b); + INSTANCE_WR(ctx, 0x171c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1720/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1724/4, 0x000c001b); + INSTANCE_WR(ctx, 0x172c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1730/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1734/4, 0x000c001b); + INSTANCE_WR(ctx, 0x173c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1740/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1744/4, 0x000c001b); + INSTANCE_WR(ctx, 0x174c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1750/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1754/4, 0x000c001b); + INSTANCE_WR(ctx, 0x175c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1760/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1764/4, 0x000c001b); + INSTANCE_WR(ctx, 0x176c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1770/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1774/4, 0x000c001b); + INSTANCE_WR(ctx, 0x177c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1780/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1784/4, 0x000c001b); + INSTANCE_WR(ctx, 0x178c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1790/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1794/4, 0x000c001b); + INSTANCE_WR(ctx, 0x179c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x17a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x17a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x17ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x17b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x17b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x17bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x17c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x17c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x17cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x17d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x17d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x17dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x17e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x17e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x17ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x17f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x17f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x17fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1800/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1804/4, 0x000c001b); + INSTANCE_WR(ctx, 0x180c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1810/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1814/4, 0x000c001b); + INSTANCE_WR(ctx, 0x181c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1820/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1824/4, 0x000c001b); + INSTANCE_WR(ctx, 0x182c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1830/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1834/4, 0x000c001b); + INSTANCE_WR(ctx, 0x183c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1840/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1844/4, 0x000c001b); + INSTANCE_WR(ctx, 0x184c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1850/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1854/4, 0x000c001b); + INSTANCE_WR(ctx, 0x185c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1860/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1864/4, 0x000c001b); + INSTANCE_WR(ctx, 0x186c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1870/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1874/4, 0x000c001b); + INSTANCE_WR(ctx, 0x187c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1880/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1884/4, 0x000c001b); + INSTANCE_WR(ctx, 0x188c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1890/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1894/4, 0x000c001b); + INSTANCE_WR(ctx, 0x189c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x18a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x18a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x18ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x18b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x18b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x18bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x18c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x18c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x18cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x18d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x18d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x18dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x18e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x18e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x18ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x18f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x18f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x18fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1900/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1904/4, 0x000c001b); + INSTANCE_WR(ctx, 0x190c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1910/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1914/4, 0x000c001b); + INSTANCE_WR(ctx, 0x191c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1920/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1924/4, 0x000c001b); + INSTANCE_WR(ctx, 0x192c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1930/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1934/4, 0x000c001b); + INSTANCE_WR(ctx, 0x193c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1940/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1944/4, 0x000c001b); + INSTANCE_WR(ctx, 0x194c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1950/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1954/4, 0x000c001b); + INSTANCE_WR(ctx, 0x195c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1960/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1964/4, 0x000c001b); + INSTANCE_WR(ctx, 0x196c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1970/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1974/4, 0x000c001b); + INSTANCE_WR(ctx, 0x197c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1980/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1984/4, 0x000c001b); + INSTANCE_WR(ctx, 0x198c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1990/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1994/4, 0x000c001b); + INSTANCE_WR(ctx, 0x199c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x19a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x19a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x19ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x19b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x19b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x19bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x19c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x19c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x19cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x19d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x19d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x19dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x19e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x19e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x19ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x19f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x19f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x19fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1a00/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1a04/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1a0c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1a10/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1a14/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1a1c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1a20/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1a24/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1a2c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1a30/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1a34/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1a3c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1a40/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1a44/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1a4c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1a50/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1a54/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1a5c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1a60/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1a64/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1a6c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1a70/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1a74/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1a7c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1a80/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1a84/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1a8c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1a90/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1a94/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1a9c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1aa0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1aa4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1aac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1ab0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1ab4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1abc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1ac0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1ac4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1acc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1ad0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1ad4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1adc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1ae0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1ae4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1aec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1af0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1af4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1afc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1b00/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1b04/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1b0c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1b10/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1b14/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1b1c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1b20/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1b24/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1b2c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1b30/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1b34/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1b3c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1b40/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1b44/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1b4c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1b50/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1b54/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1b5c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1b60/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1b64/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1b6c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1b70/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1b74/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1b7c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1b80/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1b84/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1b8c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1b90/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1b94/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1b9c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1ba0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1ba4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1bac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1bb0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1bb4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1bbc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1bc0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1bc4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1bcc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1bd0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1bd4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1bdc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1be0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1be4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1bec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1bf0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1bf4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1bfc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1c00/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1c04/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1c0c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1c10/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1c14/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1c1c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1c20/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1c24/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1c2c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1c30/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1c34/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1c3c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1c40/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1c44/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1c4c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1c50/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1c54/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1c5c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1c60/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1c64/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1c6c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1c70/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1c74/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1c7c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1c80/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1c84/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1c8c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1c90/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1c94/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1c9c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1ca0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1ca4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1cac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1cb0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1cb4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1cbc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1cc0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1cc4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1ccc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1cd0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1cd4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1cdc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1ce0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1ce4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1cec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1cf0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1cf4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1cfc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1d00/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1d04/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1d0c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1d10/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1d14/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1d1c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1d20/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1d24/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1d2c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1d30/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1d34/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1d3c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1d40/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1d44/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1d4c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1d50/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1d54/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1d5c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1d60/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1d64/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1d6c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1d70/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1d74/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1d7c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1d80/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1d84/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1d8c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1d90/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1d94/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1d9c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1da0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1da4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1dac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1db0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1db4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1dbc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1dc0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1dc4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1dcc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1dd0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1dd4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1ddc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1de0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1de4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1dec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1df0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1df4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1dfc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1e00/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1e04/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1e0c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1e10/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1e14/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1e1c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1e20/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1e24/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1e2c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1e30/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1e34/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1e3c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1e40/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1e44/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1e4c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1e50/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1e54/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1e5c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1e60/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1e64/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1e6c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1e70/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1e74/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1e7c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1e80/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1e84/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1e8c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1e90/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1e94/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1e9c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1ea0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1ea4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1eac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1eb0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1eb4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1ebc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1ec0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1ec4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1ecc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1ed0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1ed4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1edc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1ee0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1ee4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1eec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1ef0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1ef4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1efc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f00/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f04/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f0c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f10/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f14/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f1c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f20/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f24/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f2c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f30/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f34/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f3c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f40/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f44/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f4c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f50/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f54/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f5c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f60/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f64/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f6c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f70/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f74/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f7c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f80/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f84/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f8c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f90/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f94/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f9c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1fa0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1fa4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1fac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1fb0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1fb4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1fbc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1fc0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1fc4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1fcc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1fd0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1fd4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1fdc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1fe0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1fe4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1fec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1ff0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1ff4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1ffc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2000/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2004/4, 0x000c001b); + INSTANCE_WR(ctx, 0x200c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2010/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2014/4, 0x000c001b); + INSTANCE_WR(ctx, 0x201c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2020/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2024/4, 0x000c001b); + INSTANCE_WR(ctx, 0x202c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2030/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2034/4, 0x000c001b); + INSTANCE_WR(ctx, 0x203c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2040/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2044/4, 0x000c001b); + INSTANCE_WR(ctx, 0x204c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2050/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2054/4, 0x000c001b); + INSTANCE_WR(ctx, 0x205c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2060/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2064/4, 0x000c001b); + INSTANCE_WR(ctx, 0x206c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2070/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2074/4, 0x000c001b); + INSTANCE_WR(ctx, 0x207c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2080/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2084/4, 0x000c001b); + INSTANCE_WR(ctx, 0x208c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2090/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2094/4, 0x000c001b); + INSTANCE_WR(ctx, 0x209c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x20a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x20a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x20ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x20b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x20b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x20bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x20c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x20c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x20cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x20d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x20d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x20dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x20e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x20e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x20ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x20f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x20f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x20fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2100/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2104/4, 0x000c001b); + INSTANCE_WR(ctx, 0x210c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2110/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2114/4, 0x000c001b); + INSTANCE_WR(ctx, 0x211c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2120/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2124/4, 0x000c001b); + INSTANCE_WR(ctx, 0x212c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2130/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2134/4, 0x000c001b); + INSTANCE_WR(ctx, 0x213c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2140/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2144/4, 0x000c001b); + INSTANCE_WR(ctx, 0x214c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2150/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2154/4, 0x000c001b); + INSTANCE_WR(ctx, 0x215c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2160/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2164/4, 0x000c001b); + INSTANCE_WR(ctx, 0x216c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2170/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2174/4, 0x000c001b); + INSTANCE_WR(ctx, 0x217c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2180/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2184/4, 0x000c001b); + INSTANCE_WR(ctx, 0x218c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2190/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2194/4, 0x000c001b); + INSTANCE_WR(ctx, 0x219c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x21a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x21a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x21ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x21b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x21b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x21bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x21c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x21c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x21cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x21d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x21d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x21dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x21e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x21e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x21ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x21f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x21f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x21fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2200/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2204/4, 0x000c001b); + INSTANCE_WR(ctx, 0x220c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2210/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2214/4, 0x000c001b); + INSTANCE_WR(ctx, 0x221c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2220/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2224/4, 0x000c001b); + INSTANCE_WR(ctx, 0x222c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2230/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2234/4, 0x000c001b); + INSTANCE_WR(ctx, 0x223c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2240/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2244/4, 0x000c001b); + INSTANCE_WR(ctx, 0x224c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2250/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2254/4, 0x000c001b); + INSTANCE_WR(ctx, 0x225c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2260/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2264/4, 0x000c001b); + INSTANCE_WR(ctx, 0x226c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2270/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2274/4, 0x000c001b); + INSTANCE_WR(ctx, 0x227c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2280/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2284/4, 0x000c001b); + INSTANCE_WR(ctx, 0x228c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2290/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2294/4, 0x000c001b); + INSTANCE_WR(ctx, 0x229c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x22a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x22a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x22ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x22b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x22b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x22bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x22c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x22c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x22cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x22d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x22d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x22dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x22e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x22e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x22ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x22f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x22f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x22fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2300/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2304/4, 0x000c001b); + INSTANCE_WR(ctx, 0x230c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2310/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2314/4, 0x000c001b); + INSTANCE_WR(ctx, 0x231c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2320/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2324/4, 0x000c001b); + INSTANCE_WR(ctx, 0x232c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2330/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2334/4, 0x000c001b); + INSTANCE_WR(ctx, 0x233c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2340/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2344/4, 0x000c001b); + INSTANCE_WR(ctx, 0x234c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2350/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2354/4, 0x000c001b); + INSTANCE_WR(ctx, 0x235c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2360/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2364/4, 0x000c001b); + INSTANCE_WR(ctx, 0x236c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2370/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2374/4, 0x000c001b); + INSTANCE_WR(ctx, 0x237c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2380/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2384/4, 0x000c001b); + INSTANCE_WR(ctx, 0x238c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2390/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2394/4, 0x000c001b); + INSTANCE_WR(ctx, 0x239c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x23a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x23a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x23ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x23b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x23b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x23bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x23c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x23c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x23cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x23d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x23d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x23dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x23e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x23e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x23ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x23f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x23f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x23fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2400/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2404/4, 0x000c001b); + INSTANCE_WR(ctx, 0x240c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2410/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2414/4, 0x000c001b); + INSTANCE_WR(ctx, 0x241c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2420/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2424/4, 0x000c001b); + INSTANCE_WR(ctx, 0x242c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2430/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2434/4, 0x000c001b); + INSTANCE_WR(ctx, 0x243c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2440/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2444/4, 0x000c001b); + INSTANCE_WR(ctx, 0x244c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2450/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2454/4, 0x000c001b); + INSTANCE_WR(ctx, 0x245c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2460/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2464/4, 0x000c001b); + INSTANCE_WR(ctx, 0x246c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2470/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2474/4, 0x000c001b); + INSTANCE_WR(ctx, 0x247c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2480/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2484/4, 0x000c001b); + INSTANCE_WR(ctx, 0x248c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2490/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2494/4, 0x000c001b); + INSTANCE_WR(ctx, 0x249c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x24a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x24a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x24ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x24b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x24b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x24bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x24c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x24c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x24cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x24d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x24d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x24dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x24e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x24e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x24ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x24f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x24f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x24fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2500/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2504/4, 0x000c001b); + INSTANCE_WR(ctx, 0x250c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2510/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2514/4, 0x000c001b); + INSTANCE_WR(ctx, 0x251c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2520/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2524/4, 0x000c001b); + INSTANCE_WR(ctx, 0x252c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2530/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2534/4, 0x000c001b); + INSTANCE_WR(ctx, 0x253c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2540/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2544/4, 0x000c001b); + INSTANCE_WR(ctx, 0x254c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2550/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2554/4, 0x000c001b); + INSTANCE_WR(ctx, 0x255c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2560/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2564/4, 0x000c001b); + INSTANCE_WR(ctx, 0x256c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2570/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2574/4, 0x000c001b); + INSTANCE_WR(ctx, 0x257c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2580/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2584/4, 0x000c001b); + INSTANCE_WR(ctx, 0x258c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2590/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2594/4, 0x000c001b); + INSTANCE_WR(ctx, 0x259c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x25a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x25a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x25ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x25b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x25b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x25bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x25c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x25c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x25cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x25d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x25d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x25dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x25e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x25e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x25ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x25f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x25f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x25fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2600/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2604/4, 0x000c001b); + INSTANCE_WR(ctx, 0x260c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2610/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2614/4, 0x000c001b); + INSTANCE_WR(ctx, 0x261c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2620/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2624/4, 0x000c001b); + INSTANCE_WR(ctx, 0x262c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2630/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2634/4, 0x000c001b); + INSTANCE_WR(ctx, 0x263c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2640/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2644/4, 0x000c001b); + INSTANCE_WR(ctx, 0x264c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2650/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2654/4, 0x000c001b); + INSTANCE_WR(ctx, 0x265c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2660/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2664/4, 0x000c001b); + INSTANCE_WR(ctx, 0x266c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2670/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2674/4, 0x000c001b); + INSTANCE_WR(ctx, 0x267c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2680/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2684/4, 0x000c001b); + INSTANCE_WR(ctx, 0x268c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2690/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2694/4, 0x000c001b); + INSTANCE_WR(ctx, 0x269c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x26a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x26a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x26ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x26b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x26b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x26bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x26c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x26c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x26cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x26d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x26d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x26dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x26e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x26e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x26ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x26f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x26f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x26fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2700/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2704/4, 0x000c001b); + INSTANCE_WR(ctx, 0x270c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2710/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2714/4, 0x000c001b); + INSTANCE_WR(ctx, 0x271c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2720/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2724/4, 0x000c001b); + for(i = 0x274c; i< 0x275c; i += 4) + INSTANCE_WR(ctx, i/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x2ae0/4, 0x3f800000); + INSTANCE_WR(ctx, 0x2e9c/4, 0x3f800000); + INSTANCE_WR(ctx, 0x2eb0/4, 0x3f800000); + INSTANCE_WR(ctx, 0x2edc/4, 0x40000000); + INSTANCE_WR(ctx, 0x2ee0/4, 0x3f800000); + INSTANCE_WR(ctx, 0x2ee4/4, 0x3f000000); + INSTANCE_WR(ctx, 0x2eec/4, 0x40000000); + INSTANCE_WR(ctx, 0x2ef0/4, 0x3f800000); + INSTANCE_WR(ctx, 0x2ef8/4, 0xbf800000); + INSTANCE_WR(ctx, 0x2f00/4, 0xbf800000); +} + +static void nv35_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i; + + 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, 0x488/4, 0xffff0000); + for(i = 0x4dc; i< 0x4e4; i += 4) + INSTANCE_WR(ctx, i/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x4e8/4, 0x00011100); + for(i = 0x504; i< 0x544; i += 4) + INSTANCE_WR(ctx, i/4, 0x07ff0000); + 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< 0x644; i += 4) + INSTANCE_WR(ctx, i/4, 0x00010588); + for(i = 0x644; i< 0x684; i += 4) + INSTANCE_WR(ctx, i/4, 0x00030303); + for(i = 0x6c4; i< 0x704; i += 4) + INSTANCE_WR(ctx, i/4, 0x0008aae4); + for(i = 0x704; i< 0x744; i += 4) + INSTANCE_WR(ctx, i/4, 0x01012000); + for(i = 0x744; i< 0x784; i += 4) + INSTANCE_WR(ctx, i/4, 0x00080008); + INSTANCE_WR(ctx, 0x860/4, 0x00040000); + INSTANCE_WR(ctx, 0x864/4, 0x00010000); + for(i = 0x868; i< 0x878; i += 4) + INSTANCE_WR(ctx, i/4, 0x00040004); + INSTANCE_WR(ctx, 0x1f1c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f20/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f24/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f2c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f30/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f34/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f3c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f40/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f44/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f4c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f50/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f54/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f5c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f60/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f64/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f6c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f70/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f74/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f7c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f80/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f84/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f8c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1f90/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1f94/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1f9c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1fa0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1fa4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1fac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1fb0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1fb4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1fbc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1fc0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1fc4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1fcc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1fd0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1fd4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1fdc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1fe0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1fe4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1fec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x1ff0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x1ff4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x1ffc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2000/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2004/4, 0x000c001b); + INSTANCE_WR(ctx, 0x200c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2010/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2014/4, 0x000c001b); + INSTANCE_WR(ctx, 0x201c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2020/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2024/4, 0x000c001b); + INSTANCE_WR(ctx, 0x202c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2030/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2034/4, 0x000c001b); + INSTANCE_WR(ctx, 0x203c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2040/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2044/4, 0x000c001b); + INSTANCE_WR(ctx, 0x204c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2050/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2054/4, 0x000c001b); + INSTANCE_WR(ctx, 0x205c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2060/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2064/4, 0x000c001b); + INSTANCE_WR(ctx, 0x206c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2070/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2074/4, 0x000c001b); + INSTANCE_WR(ctx, 0x207c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2080/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2084/4, 0x000c001b); + INSTANCE_WR(ctx, 0x208c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2090/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2094/4, 0x000c001b); + INSTANCE_WR(ctx, 0x209c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x20a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x20a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x20ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x20b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x20b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x20bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x20c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x20c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x20cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x20d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x20d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x20dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x20e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x20e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x20ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x20f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x20f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x20fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2100/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2104/4, 0x000c001b); + INSTANCE_WR(ctx, 0x210c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2110/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2114/4, 0x000c001b); + INSTANCE_WR(ctx, 0x211c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2120/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2124/4, 0x000c001b); + INSTANCE_WR(ctx, 0x212c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2130/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2134/4, 0x000c001b); + INSTANCE_WR(ctx, 0x213c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2140/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2144/4, 0x000c001b); + INSTANCE_WR(ctx, 0x214c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2150/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2154/4, 0x000c001b); + INSTANCE_WR(ctx, 0x215c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2160/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2164/4, 0x000c001b); + INSTANCE_WR(ctx, 0x216c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2170/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2174/4, 0x000c001b); + INSTANCE_WR(ctx, 0x217c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2180/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2184/4, 0x000c001b); + INSTANCE_WR(ctx, 0x218c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2190/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2194/4, 0x000c001b); + INSTANCE_WR(ctx, 0x219c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x21a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x21a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x21ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x21b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x21b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x21bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x21c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x21c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x21cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x21d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x21d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x21dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x21e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x21e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x21ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x21f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x21f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x21fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2200/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2204/4, 0x000c001b); + INSTANCE_WR(ctx, 0x220c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2210/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2214/4, 0x000c001b); + INSTANCE_WR(ctx, 0x221c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2220/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2224/4, 0x000c001b); + INSTANCE_WR(ctx, 0x222c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2230/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2234/4, 0x000c001b); + INSTANCE_WR(ctx, 0x223c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2240/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2244/4, 0x000c001b); + INSTANCE_WR(ctx, 0x224c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2250/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2254/4, 0x000c001b); + INSTANCE_WR(ctx, 0x225c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2260/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2264/4, 0x000c001b); + INSTANCE_WR(ctx, 0x226c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2270/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2274/4, 0x000c001b); + INSTANCE_WR(ctx, 0x227c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2280/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2284/4, 0x000c001b); + INSTANCE_WR(ctx, 0x228c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2290/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2294/4, 0x000c001b); + INSTANCE_WR(ctx, 0x229c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x22a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x22a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x22ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x22b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x22b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x22bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x22c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x22c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x22cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x22d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x22d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x22dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x22e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x22e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x22ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x22f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x22f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x22fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2300/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2304/4, 0x000c001b); + INSTANCE_WR(ctx, 0x230c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2310/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2314/4, 0x000c001b); + INSTANCE_WR(ctx, 0x231c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2320/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2324/4, 0x000c001b); + INSTANCE_WR(ctx, 0x232c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2330/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2334/4, 0x000c001b); + INSTANCE_WR(ctx, 0x233c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2340/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2344/4, 0x000c001b); + INSTANCE_WR(ctx, 0x234c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2350/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2354/4, 0x000c001b); + INSTANCE_WR(ctx, 0x235c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2360/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2364/4, 0x000c001b); + INSTANCE_WR(ctx, 0x236c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2370/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2374/4, 0x000c001b); + INSTANCE_WR(ctx, 0x237c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2380/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2384/4, 0x000c001b); + INSTANCE_WR(ctx, 0x238c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2390/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2394/4, 0x000c001b); + INSTANCE_WR(ctx, 0x239c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x23a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x23a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x23ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x23b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x23b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x23bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x23c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x23c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x23cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x23d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x23d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x23dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x23e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x23e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x23ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x23f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x23f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x23fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2400/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2404/4, 0x000c001b); + INSTANCE_WR(ctx, 0x240c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2410/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2414/4, 0x000c001b); + INSTANCE_WR(ctx, 0x241c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2420/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2424/4, 0x000c001b); + INSTANCE_WR(ctx, 0x242c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2430/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2434/4, 0x000c001b); + INSTANCE_WR(ctx, 0x243c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2440/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2444/4, 0x000c001b); + INSTANCE_WR(ctx, 0x244c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2450/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2454/4, 0x000c001b); + INSTANCE_WR(ctx, 0x245c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2460/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2464/4, 0x000c001b); + INSTANCE_WR(ctx, 0x246c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2470/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2474/4, 0x000c001b); + INSTANCE_WR(ctx, 0x247c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2480/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2484/4, 0x000c001b); + INSTANCE_WR(ctx, 0x248c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2490/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2494/4, 0x000c001b); + INSTANCE_WR(ctx, 0x249c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x24a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x24a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x24ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x24b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x24b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x24bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x24c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x24c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x24cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x24d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x24d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x24dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x24e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x24e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x24ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x24f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x24f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x24fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2500/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2504/4, 0x000c001b); + INSTANCE_WR(ctx, 0x250c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2510/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2514/4, 0x000c001b); + INSTANCE_WR(ctx, 0x251c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2520/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2524/4, 0x000c001b); + INSTANCE_WR(ctx, 0x252c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2530/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2534/4, 0x000c001b); + INSTANCE_WR(ctx, 0x253c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2540/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2544/4, 0x000c001b); + INSTANCE_WR(ctx, 0x254c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2550/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2554/4, 0x000c001b); + INSTANCE_WR(ctx, 0x255c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2560/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2564/4, 0x000c001b); + INSTANCE_WR(ctx, 0x256c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2570/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2574/4, 0x000c001b); + INSTANCE_WR(ctx, 0x257c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2580/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2584/4, 0x000c001b); + INSTANCE_WR(ctx, 0x258c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2590/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2594/4, 0x000c001b); + INSTANCE_WR(ctx, 0x259c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x25a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x25a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x25ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x25b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x25b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x25bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x25c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x25c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x25cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x25d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x25d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x25dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x25e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x25e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x25ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x25f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x25f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x25fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2600/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2604/4, 0x000c001b); + INSTANCE_WR(ctx, 0x260c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2610/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2614/4, 0x000c001b); + INSTANCE_WR(ctx, 0x261c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2620/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2624/4, 0x000c001b); + INSTANCE_WR(ctx, 0x262c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2630/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2634/4, 0x000c001b); + INSTANCE_WR(ctx, 0x263c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2640/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2644/4, 0x000c001b); + INSTANCE_WR(ctx, 0x264c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2650/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2654/4, 0x000c001b); + INSTANCE_WR(ctx, 0x265c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2660/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2664/4, 0x000c001b); + INSTANCE_WR(ctx, 0x266c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2670/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2674/4, 0x000c001b); + INSTANCE_WR(ctx, 0x267c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2680/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2684/4, 0x000c001b); + INSTANCE_WR(ctx, 0x268c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2690/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2694/4, 0x000c001b); + INSTANCE_WR(ctx, 0x269c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x26a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x26a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x26ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x26b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x26b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x26bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x26c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x26c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x26cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x26d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x26d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x26dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x26e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x26e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x26ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x26f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x26f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x26fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2700/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2704/4, 0x000c001b); + INSTANCE_WR(ctx, 0x270c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2710/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2714/4, 0x000c001b); + INSTANCE_WR(ctx, 0x271c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2720/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2724/4, 0x000c001b); + INSTANCE_WR(ctx, 0x272c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2730/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2734/4, 0x000c001b); + INSTANCE_WR(ctx, 0x273c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2740/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2744/4, 0x000c001b); + INSTANCE_WR(ctx, 0x274c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2750/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2754/4, 0x000c001b); + INSTANCE_WR(ctx, 0x275c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2760/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2764/4, 0x000c001b); + INSTANCE_WR(ctx, 0x276c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2770/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2774/4, 0x000c001b); + INSTANCE_WR(ctx, 0x277c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2780/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2784/4, 0x000c001b); + INSTANCE_WR(ctx, 0x278c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2790/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2794/4, 0x000c001b); + INSTANCE_WR(ctx, 0x279c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x27a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x27a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x27ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x27b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x27b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x27bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x27c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x27c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x27cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x27d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x27d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x27dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x27e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x27e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x27ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x27f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x27f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x27fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2800/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2804/4, 0x000c001b); + INSTANCE_WR(ctx, 0x280c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2810/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2814/4, 0x000c001b); + INSTANCE_WR(ctx, 0x281c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2820/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2824/4, 0x000c001b); + INSTANCE_WR(ctx, 0x282c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2830/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2834/4, 0x000c001b); + INSTANCE_WR(ctx, 0x283c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2840/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2844/4, 0x000c001b); + INSTANCE_WR(ctx, 0x284c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2850/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2854/4, 0x000c001b); + INSTANCE_WR(ctx, 0x285c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2860/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2864/4, 0x000c001b); + INSTANCE_WR(ctx, 0x286c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2870/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2874/4, 0x000c001b); + INSTANCE_WR(ctx, 0x287c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2880/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2884/4, 0x000c001b); + INSTANCE_WR(ctx, 0x288c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2890/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2894/4, 0x000c001b); + INSTANCE_WR(ctx, 0x289c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x28a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x28a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x28ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x28b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x28b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x28bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x28c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x28c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x28cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x28d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x28d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x28dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x28e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x28e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x28ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x28f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x28f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x28fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2900/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2904/4, 0x000c001b); + INSTANCE_WR(ctx, 0x290c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2910/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2914/4, 0x000c001b); + INSTANCE_WR(ctx, 0x291c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2920/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2924/4, 0x000c001b); + INSTANCE_WR(ctx, 0x292c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2930/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2934/4, 0x000c001b); + INSTANCE_WR(ctx, 0x293c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2940/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2944/4, 0x000c001b); + INSTANCE_WR(ctx, 0x294c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2950/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2954/4, 0x000c001b); + INSTANCE_WR(ctx, 0x295c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2960/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2964/4, 0x000c001b); + INSTANCE_WR(ctx, 0x296c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2970/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2974/4, 0x000c001b); + INSTANCE_WR(ctx, 0x297c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2980/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2984/4, 0x000c001b); + INSTANCE_WR(ctx, 0x298c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2990/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2994/4, 0x000c001b); + INSTANCE_WR(ctx, 0x299c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x29a0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x29a4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x29ac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x29b0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x29b4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x29bc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x29c0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x29c4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x29cc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x29d0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x29d4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x29dc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x29e0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x29e4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x29ec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x29f0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x29f4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x29fc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a00/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a04/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a0c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a10/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a14/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a1c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a20/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a24/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a2c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a30/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a34/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a3c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a40/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a44/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a4c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a50/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a54/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a5c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a60/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a64/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a6c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a70/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a74/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a7c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a80/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a84/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a8c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2a90/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2a94/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2a9c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2aa0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2aa4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2aac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2ab0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ab4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2abc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2ac0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ac4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2acc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2ad0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ad4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2adc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2ae0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ae4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2aec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2af0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2af4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2afc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b00/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b04/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b0c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b10/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b14/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b1c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b20/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b24/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b2c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b30/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b34/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b3c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b40/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b44/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b4c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b50/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b54/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b5c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b60/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b64/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b6c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b70/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b74/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b7c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b80/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b84/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b8c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2b90/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2b94/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2b9c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2ba0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ba4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2bac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2bb0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2bb4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2bbc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2bc0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2bc4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2bcc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2bd0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2bd4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2bdc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2be0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2be4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2bec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2bf0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2bf4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2bfc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c00/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c04/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c0c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c10/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c14/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c1c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c20/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c24/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c2c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c30/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c34/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c3c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c40/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c44/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c4c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c50/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c54/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c5c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c60/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c64/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c6c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c70/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c74/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c7c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c80/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c84/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c8c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2c90/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2c94/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2c9c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2ca0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ca4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2cac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2cb0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2cb4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2cbc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2cc0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2cc4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2ccc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2cd0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2cd4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2cdc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2ce0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ce4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2cec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2cf0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2cf4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2cfc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d00/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d04/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d0c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d10/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d14/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d1c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d20/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d24/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d2c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d30/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d34/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d3c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d40/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d44/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d4c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d50/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d54/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d5c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d60/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d64/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d6c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d70/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d74/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d7c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d80/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d84/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d8c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2d90/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2d94/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2d9c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2da0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2da4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2dac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2db0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2db4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2dbc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2dc0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2dc4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2dcc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2dd0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2dd4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2ddc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2de0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2de4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2dec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2df0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2df4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2dfc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e00/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e04/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e0c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e10/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e14/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e1c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e20/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e24/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e2c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e30/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e34/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e3c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e40/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e44/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e4c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e50/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e54/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e5c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e60/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e64/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e6c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e70/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e74/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e7c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e80/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e84/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e8c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2e90/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2e94/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2e9c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2ea0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ea4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2eac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2eb0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2eb4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2ebc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2ec0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ec4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2ecc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2ed0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ed4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2edc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2ee0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ee4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2eec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2ef0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ef4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2efc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f00/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f04/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f0c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f10/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f14/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f1c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f20/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f24/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f2c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f30/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f34/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f3c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f40/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f44/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f4c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f50/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f54/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f5c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f60/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f64/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f6c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f70/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f74/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f7c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f80/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f84/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f8c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2f90/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2f94/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2f9c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2fa0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2fa4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2fac/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2fb0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2fb4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2fbc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2fc0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2fc4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2fcc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2fd0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2fd4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2fdc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2fe0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2fe4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2fec/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x2ff0/4, 0x0436086c); + INSTANCE_WR(ctx, 0x2ff4/4, 0x000c001b); + INSTANCE_WR(ctx, 0x2ffc/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x3000/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3004/4, 0x000c001b); + INSTANCE_WR(ctx, 0x300c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x3010/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3014/4, 0x000c001b); + INSTANCE_WR(ctx, 0x301c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x3020/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3024/4, 0x000c001b); + INSTANCE_WR(ctx, 0x302c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x3030/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3034/4, 0x000c001b); + INSTANCE_WR(ctx, 0x303c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x3040/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3044/4, 0x000c001b); + INSTANCE_WR(ctx, 0x304c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x3050/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3054/4, 0x000c001b); + INSTANCE_WR(ctx, 0x305c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x3060/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3064/4, 0x000c001b); + INSTANCE_WR(ctx, 0x306c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x3070/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3074/4, 0x000c001b); + INSTANCE_WR(ctx, 0x307c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x3080/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3084/4, 0x000c001b); + INSTANCE_WR(ctx, 0x308c/4, 0x10700ff9); + INSTANCE_WR(ctx, 0x3090/4, 0x0436086c); + INSTANCE_WR(ctx, 0x3094/4, 0x000c001b); + for(i = 0x30bc; i< 0x30cc; i += 4) + INSTANCE_WR(ctx, i/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x3450/4, 0x3f800000); + INSTANCE_WR(ctx, 0x380c/4, 0x3f800000); + INSTANCE_WR(ctx, 0x3820/4, 0x3f800000); + INSTANCE_WR(ctx, 0x384c/4, 0x40000000); + INSTANCE_WR(ctx, 0x3850/4, 0x3f800000); + INSTANCE_WR(ctx, 0x3854/4, 0x3f000000); + INSTANCE_WR(ctx, 0x385c/4, 0x40000000); + INSTANCE_WR(ctx, 0x3860/4, 0x3f800000); + INSTANCE_WR(ctx, 0x3868/4, 0xbf800000); + INSTANCE_WR(ctx, 0x3870/4, 0xbf800000);} + +int nv30_graph_create_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *); + unsigned int ctx_size; + int ret; + + switch (dev_priv->chipset) { + case 0x31: + ctx_size = NV31_GRCTX_SIZE; + ctx_init = nv31_graph_context_init; + break; + case 0x34: + ctx_size = NV34_GRCTX_SIZE; + ctx_init = nv34_graph_context_init; + break; + case 0x35: + case 0x36: + ctx_size = NV35_GRCTX_SIZE; + ctx_init = nv35_graph_context_init; + break; + default: + ctx_size = 0; + ctx_init = nv35_graph_context_init; + DRM_ERROR("Please contact the devs if you want your NV%x card to work\n",dev_priv->chipset); + break; + } + + if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, ctx_size, 16, + NVOBJ_FLAG_ZERO_ALLOC, + &chan->ramin_grctx))) + return ret; + + /* Initialise default context values */ + ctx_init(dev, chan->ramin_grctx->gpuobj); + + INSTANCE_WR(chan->ramin_grctx->gpuobj, 0x28/4, (chan->id<<24)|0x1); /* CTX_USER */ + INSTANCE_WR(dev_priv->ctx_table->gpuobj, chan->id, + chan->ramin_grctx->instance >> 4); + + return 0; +} + +void nv30_graph_destroy_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (chan->ramin_grctx) + nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); + + INSTANCE_WR(dev_priv->ctx_table->gpuobj, chan->id, 0); +} + +static int +nouveau_graph_wait_idle(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int tv = 1000; + + while (tv--) { + if (NV_READ(0x400700) == 0) + break; + } + + if (NV_READ(0x400700)) { + DRM_ERROR("timeout!\n"); + return -EBUSY; + } + return 0; +} + +int nv30_graph_load_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t inst; + + if (!chan->ramin_grctx) + return -EINVAL; + inst = chan->ramin_grctx->instance >> 4; + + NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); + NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_XFER, + NV20_PGRAPH_CHANNEL_CTX_XFER_LOAD); + + return nouveau_graph_wait_idle(dev); +} + +int nv30_graph_save_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t inst; + + if (!chan->ramin_grctx) + return -EINVAL; + inst = chan->ramin_grctx->instance >> 4; + + NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); + NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_XFER, + NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE); + + return nouveau_graph_wait_idle(dev); +} + +int nv30_graph_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t vramsz, tmp; + int ret, 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; + if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, + dev_priv->ctx_table_size, 16, + NVOBJ_FLAG_ZERO_ALLOC, + &dev_priv->ctx_table))) + return ret; + + NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_TABLE, + dev_priv->ctx_table->instance >> 4); + + NV_WRITE(NV03_PGRAPH_INTR , 0xFFFFFFFF); + NV_WRITE(NV03_PGRAPH_INTR_EN, 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, 0x01b463ff); + NV_WRITE(NV04_PGRAPH_DEBUG_3, 0xf3de0471); + NV_WRITE(NV10_PGRAPH_DEBUG_4, 0x00008000); + NV_WRITE(NV04_PGRAPH_LIMIT_VIOL_PIX, 0xf04bdff6); + NV_WRITE(0x400B80, 0x1003d888); + NV_WRITE(0x400098, 0x00000000); + NV_WRITE(0x40009C, 0x0005ad00); + NV_WRITE(0x400B88, 0x62ff00ff); // suspiciously like PGRAPH_DEBUG_2 + NV_WRITE(0x4000a0, 0x00000000); + NV_WRITE(0x4000a4, 0x00000008); + NV_WRITE(0x4008a8, 0xb784a400); + NV_WRITE(0x400ba0, 0x002f8685); + NV_WRITE(0x400ba4, 0x00231f3f); + NV_WRITE(0x4008a4, 0x40000020); + NV_WRITE(0x400B84, 0x0c000000); + NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x62ff0f7f); + NV_WRITE(0x4000c0, 0x00000016); + NV_WRITE(0x400780, 0x000014e4); + + /* copy tile info from PFB */ + for (i=0; idev_private; + + nouveau_gpuobj_ref_del(dev, &dev_priv->ctx_table); +} + diff --git a/drivers/char/drm/nv40_fb.c b/drivers/char/drm/nv40_fb.c new file mode 100644 index 0000000..2cbb40e --- /dev/null +++ b/drivers/char/drm/nv40_fb.c @@ -0,0 +1,56 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv40_fb_init(struct drm_device *dev) +{ + struct drm_nouveau_private *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; iramfc->gpuobj, \ + NV40_RAMFC_##offset/4, (val)) +#define RAMFC_RD(offset) INSTANCE_RD(chan->ramfc->gpuobj, \ + NV40_RAMFC_##offset/4) +#define NV40_RAMFC(c) (dev_priv->ramfc_offset + ((c)*NV40_RAMFC__SIZE)) +#define NV40_RAMFC__SIZE 128 + +int +nv40_fifo_create_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + + if ((ret = nouveau_gpuobj_new_fake(dev, NV40_RAMFC(chan->id), ~0, + NV40_RAMFC__SIZE, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, + NULL, &chan->ramfc))) + return ret; + + /* Fill entries that are seen filled in dumps of nvidia driver just + * after channel's is put into DMA mode + */ + RAMFC_WR(DMA_PUT , chan->pushbuf_base); + RAMFC_WR(DMA_GET , chan->pushbuf_base); + RAMFC_WR(DMA_INSTANCE , chan->pushbuf->instance >> 4); + 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(DMA_SUBROUTINE, 0); + RAMFC_WR(GRCTX_INSTANCE, chan->ramin_grctx->instance >> 4); + RAMFC_WR(DMA_TIMESLICE , 0x0001FFFF); + + /* enable the fifo dma operation */ + NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE)|(1<id)); + return 0; +} + +void +nv40_fifo_destroy_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + + NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<id)); + + if (chan->ramfc) + nouveau_gpuobj_ref_del(dev, &chan->ramfc); +} + +int +nv40_fifo_load_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t tmp, tmp2; + + NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET , RAMFC_RD(DMA_GET)); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT , RAMFC_RD(DMA_PUT)); + NV_WRITE(NV10_PFIFO_CACHE1_REF_CNT , RAMFC_RD(REF_CNT)); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE , RAMFC_RD(DMA_INSTANCE)); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_DCOUNT , RAMFC_RD(DMA_DCOUNT)); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE , RAMFC_RD(DMA_STATE)); + + /* No idea what 0x2058 is.. */ + tmp = RAMFC_RD(DMA_FETCH); + tmp2 = NV_READ(0x2058) & 0xFFF; + tmp2 |= (tmp & 0x30000000); + NV_WRITE(0x2058, tmp2); + tmp &= ~0x30000000; + NV_WRITE(NV04_PFIFO_CACHE1_DMA_FETCH , tmp); + + NV_WRITE(NV04_PFIFO_CACHE1_ENGINE , RAMFC_RD(ENGINE)); + NV_WRITE(NV04_PFIFO_CACHE1_PULL1 , RAMFC_RD(PULL1_ENGINE)); + NV_WRITE(NV10_PFIFO_CACHE1_ACQUIRE_VALUE , RAMFC_RD(ACQUIRE_VALUE)); + NV_WRITE(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP, RAMFC_RD(ACQUIRE_TIMESTAMP)); + NV_WRITE(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT , RAMFC_RD(ACQUIRE_TIMEOUT)); + NV_WRITE(NV10_PFIFO_CACHE1_SEMAPHORE , RAMFC_RD(SEMAPHORE)); + NV_WRITE(NV10_PFIFO_CACHE1_DMA_SUBROUTINE , RAMFC_RD(DMA_SUBROUTINE)); + NV_WRITE(NV40_PFIFO_GRCTX_INSTANCE , RAMFC_RD(GRCTX_INSTANCE)); + NV_WRITE(0x32e4, RAMFC_RD(UNK_40)); + /* NVIDIA does this next line twice... */ + NV_WRITE(0x32e8, RAMFC_RD(UNK_44)); + NV_WRITE(0x2088, RAMFC_RD(UNK_4C)); + NV_WRITE(0x3300, RAMFC_RD(UNK_50)); + + /* not sure what part is PUT, and which is GET.. never seen a non-zero + * value appear in a mmio-trace yet.. + */ +#if 0 + tmp = NV_READ(UNK_84); + NV_WRITE(NV_PFIFO_CACHE1_GET, tmp ???); + NV_WRITE(NV_PFIFO_CACHE1_PUT, tmp ???); +#endif + + /* Don't clobber the TIMEOUT_ENABLED flag when restoring from RAMFC */ + tmp = NV_READ(NV04_PFIFO_DMA_TIMESLICE) & ~0x1FFFF; + tmp |= RAMFC_RD(DMA_TIMESLICE) & 0x1FFFF; + NV_WRITE(NV04_PFIFO_DMA_TIMESLICE, tmp); + + /* Set channel active, and in DMA mode */ + NV_WRITE(NV03_PFIFO_CACHE1_PUSH1 , 0x00010000 | chan->id); + /* Reset DMA_CTL_AT_INFO to INVALID */ + tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_CTL) & ~(1<<31); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, tmp); + + return 0; +} + +int +nv40_fifo_save_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t tmp; + + 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(NV04_PFIFO_CACHE1_DMA_DCOUNT)); + RAMFC_WR(DMA_STATE , NV_READ(NV04_PFIFO_CACHE1_DMA_STATE)); + + tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_FETCH); + tmp |= NV_READ(0x2058) & 0x30000000; + RAMFC_WR(DMA_FETCH , tmp); + + 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)); + tmp = NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP); + RAMFC_WR(ACQUIRE_TIMESTAMP, tmp); + RAMFC_WR(ACQUIRE_TIMEOUT , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT)); + RAMFC_WR(SEMAPHORE , NV_READ(NV10_PFIFO_CACHE1_SEMAPHORE)); + + /* NVIDIA read 0x3228 first, then write DMA_GET here.. maybe something + * more involved depending on the value of 0x3228? + */ + RAMFC_WR(DMA_SUBROUTINE , NV_READ(NV04_PFIFO_CACHE1_DMA_GET)); + + RAMFC_WR(GRCTX_INSTANCE , NV_READ(NV40_PFIFO_GRCTX_INSTANCE)); + + /* No idea what the below is for exactly, ripped from a mmio-trace */ + RAMFC_WR(UNK_40 , NV_READ(NV40_PFIFO_UNK32E4)); + + /* NVIDIA do this next line twice.. bug? */ + RAMFC_WR(UNK_44 , NV_READ(0x32e8)); + RAMFC_WR(UNK_4C , NV_READ(0x2088)); + RAMFC_WR(UNK_50 , NV_READ(0x3300)); + +#if 0 /* no real idea which is PUT/GET in UNK_48.. */ + tmp = NV_READ(NV04_PFIFO_CACHE1_GET); + tmp |= (NV_READ(NV04_PFIFO_CACHE1_PUT) << 16); + RAMFC_WR(UNK_48 , tmp); +#endif + + return 0; +} + +int +nv40_fifo_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + + if ((ret = nouveau_fifo_init(dev))) + return ret; + + NV_WRITE(NV04_PFIFO_DMA_TIMESLICE, 0x2101ffff); + return 0; +} + diff --git a/drivers/char/drm/nv40_graph.c b/drivers/char/drm/nv40_graph.c new file mode 100644 index 0000000..26237c7 --- /dev/null +++ b/drivers/char/drm/nv40_graph.c @@ -0,0 +1,1683 @@ +/* + * Copyright (C) 2007 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.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 NV49_GRCTX_SIZE (164640) +#define NV4A_GRCTX_SIZE (64*1024) +#define NV4B_GRCTX_SIZE (164640) +#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(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i; + + /* Always has the "instance address" of itself at offset 0 */ + INSTANCE_WR(ctx, 0x00000/4, ctx->im_pramin->start); + /* 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(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i; + + INSTANCE_WR(ctx, 0x00000/4, ctx->im_pramin->start); + 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(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i; + + INSTANCE_WR(ctx, 0x00000/4, ctx->im_pramin->start); + 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 +nv49_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i; + + INSTANCE_WR(ctx, 0x00000/4, ctx->im_pramin->start); + INSTANCE_WR(ctx, 0x00004/4, 0x0000c040); + INSTANCE_WR(ctx, 0x00008/4, 0x0000c040); + INSTANCE_WR(ctx, 0x0000c/4, 0x0000c040); + INSTANCE_WR(ctx, 0x00010/4, 0x0000c040); + INSTANCE_WR(ctx, 0x00014/4, 0x0000c040); + INSTANCE_WR(ctx, 0x00018/4, 0x0000c040); + INSTANCE_WR(ctx, 0x0001c/4, 0x0000c040); + INSTANCE_WR(ctx, 0x00020/4, 0x0000c040); + INSTANCE_WR(ctx, 0x000c4/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x000c8/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x000d0/4, 0x00000001); + INSTANCE_WR(ctx, 0x001bc/4, 0x20010001); + INSTANCE_WR(ctx, 0x001c0/4, 0x0f73ef00); + INSTANCE_WR(ctx, 0x001c8/4, 0x02008821); + INSTANCE_WR(ctx, 0x00218/4, 0x00000040); + INSTANCE_WR(ctx, 0x0021c/4, 0x00000040); + INSTANCE_WR(ctx, 0x00220/4, 0x00000040); + INSTANCE_WR(ctx, 0x00228/4, 0x00000040); + INSTANCE_WR(ctx, 0x00234/4, 0x80000000); + INSTANCE_WR(ctx, 0x00238/4, 0x80000000); + INSTANCE_WR(ctx, 0x0023c/4, 0x80000000); + INSTANCE_WR(ctx, 0x00240/4, 0x80000000); + INSTANCE_WR(ctx, 0x00244/4, 0x80000000); + INSTANCE_WR(ctx, 0x00248/4, 0x80000000); + INSTANCE_WR(ctx, 0x0024c/4, 0x80000000); + INSTANCE_WR(ctx, 0x00250/4, 0x80000000); + INSTANCE_WR(ctx, 0x00270/4, 0x0b0b0b0c); + INSTANCE_WR(ctx, 0x003e0/4, 0x00040000); + INSTANCE_WR(ctx, 0x003f0/4, 0x55555555); + INSTANCE_WR(ctx, 0x003f4/4, 0x55555555); + INSTANCE_WR(ctx, 0x003f8/4, 0x55555555); + INSTANCE_WR(ctx, 0x003fc/4, 0x55555555); + INSTANCE_WR(ctx, 0x00428/4, 0x00000008); + INSTANCE_WR(ctx, 0x0043c/4, 0x00001010); + INSTANCE_WR(ctx, 0x00460/4, 0x00000111); + INSTANCE_WR(ctx, 0x00464/4, 0x00000111); + INSTANCE_WR(ctx, 0x00468/4, 0x00000111); + INSTANCE_WR(ctx, 0x0046c/4, 0x00000111); + INSTANCE_WR(ctx, 0x00470/4, 0x00000111); + INSTANCE_WR(ctx, 0x00474/4, 0x00000111); + INSTANCE_WR(ctx, 0x00478/4, 0x00000111); + INSTANCE_WR(ctx, 0x0047c/4, 0x00000111); + INSTANCE_WR(ctx, 0x00480/4, 0x00000111); + INSTANCE_WR(ctx, 0x00484/4, 0x00000111); + INSTANCE_WR(ctx, 0x00488/4, 0x00000111); + INSTANCE_WR(ctx, 0x0048c/4, 0x00000111); + INSTANCE_WR(ctx, 0x00490/4, 0x00000111); + INSTANCE_WR(ctx, 0x00494/4, 0x00000111); + INSTANCE_WR(ctx, 0x00498/4, 0x00000111); + INSTANCE_WR(ctx, 0x0049c/4, 0x00000111); + INSTANCE_WR(ctx, 0x004f4/4, 0x00000111); + INSTANCE_WR(ctx, 0x004f8/4, 0x00080060); + INSTANCE_WR(ctx, 0x00514/4, 0x00000080); + INSTANCE_WR(ctx, 0x00518/4, 0xffff0000); + INSTANCE_WR(ctx, 0x0051c/4, 0x00000001); + INSTANCE_WR(ctx, 0x00530/4, 0x46400000); + INSTANCE_WR(ctx, 0x00540/4, 0xffff0000); + INSTANCE_WR(ctx, 0x00544/4, 0x88888888); + INSTANCE_WR(ctx, 0x00548/4, 0x88888888); + INSTANCE_WR(ctx, 0x0054c/4, 0x88888888); + INSTANCE_WR(ctx, 0x00550/4, 0x88888888); + INSTANCE_WR(ctx, 0x00554/4, 0x88888888); + INSTANCE_WR(ctx, 0x00558/4, 0x88888888); + INSTANCE_WR(ctx, 0x0055c/4, 0x88888888); + INSTANCE_WR(ctx, 0x00560/4, 0x88888888); + INSTANCE_WR(ctx, 0x00564/4, 0x88888888); + INSTANCE_WR(ctx, 0x00568/4, 0x88888888); + INSTANCE_WR(ctx, 0x0056c/4, 0x88888888); + INSTANCE_WR(ctx, 0x00570/4, 0x88888888); + INSTANCE_WR(ctx, 0x00574/4, 0x88888888); + INSTANCE_WR(ctx, 0x00578/4, 0x88888888); + INSTANCE_WR(ctx, 0x0057c/4, 0x88888888); + INSTANCE_WR(ctx, 0x00580/4, 0x88888888); + INSTANCE_WR(ctx, 0x00594/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x00598/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x005a0/4, 0x00011100); + INSTANCE_WR(ctx, 0x005bc/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005c0/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005c4/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005c8/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005cc/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005d0/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005d4/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005d8/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005dc/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005e0/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005e4/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005e8/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005ec/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005f0/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005f4/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005f8/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x00604/4, 0x4b7fffff); + INSTANCE_WR(ctx, 0x0062c/4, 0x30201000); + INSTANCE_WR(ctx, 0x00630/4, 0x70605040); + INSTANCE_WR(ctx, 0x00634/4, 0xb8a89888); + INSTANCE_WR(ctx, 0x00638/4, 0xf8e8d8c8); + INSTANCE_WR(ctx, 0x0064c/4, 0x40100000); + INSTANCE_WR(ctx, 0x00668/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x0069c/4, 0x435185d6); + INSTANCE_WR(ctx, 0x006a0/4, 0x2155b699); + INSTANCE_WR(ctx, 0x006a4/4, 0xfedcba98); + INSTANCE_WR(ctx, 0x006a8/4, 0x00000098); + INSTANCE_WR(ctx, 0x006b8/4, 0xffffffff); + INSTANCE_WR(ctx, 0x006bc/4, 0x00ff7000); + INSTANCE_WR(ctx, 0x006c0/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x006d0/4, 0x00ff0000); + INSTANCE_WR(ctx, 0x0070c/4, 0x00ffff00); + for (i=0x00750; i<=0x0078c; i+=4) + INSTANCE_WR(ctx, i/4, 0x00018488); + for (i=0x00790; i<=0x007cc; i+=4) + INSTANCE_WR(ctx, i/4, 0x00028202); + for (i=0x00810; i<=0x0084c; i+=4) + INSTANCE_WR(ctx, i/4, 0x0000aae4); + for (i=0x00850; i<=0x0088c; i+=4) + INSTANCE_WR(ctx, i/4, 0x01012000); + for (i=0x00890; i<=0x008cc; i+=4) + INSTANCE_WR(ctx, i/4, 0x00080008); + for (i=0x00910; i<=0x0094c; i+=4) + INSTANCE_WR(ctx, i/4, 0x00100008); + for (i=0x009a0; i<=0x009ac; i+=4) + INSTANCE_WR(ctx, i/4, 0x0001bc80); + for (i=0x009b0; i<=0x009bc; i+=4) + INSTANCE_WR(ctx, i/4, 0x00000202); + for (i=0x009d0; i<=0x009dc; i+=4) + INSTANCE_WR(ctx, i/4, 0x00000008); + for (i=0x009f0; i<=0x009fc; i+=4) + INSTANCE_WR(ctx, i/4, 0x00080008); + INSTANCE_WR(ctx, 0x00a10/4, 0x00000002); + INSTANCE_WR(ctx, 0x00a44/4, 0x00000421); + INSTANCE_WR(ctx, 0x00a48/4, 0x030c30c3); + INSTANCE_WR(ctx, 0x00a54/4, 0x3e020200); + INSTANCE_WR(ctx, 0x00a58/4, 0x00ffffff); + INSTANCE_WR(ctx, 0x00a5c/4, 0x20103f00); + INSTANCE_WR(ctx, 0x00a68/4, 0x00040000); + INSTANCE_WR(ctx, 0x00aa0/4, 0x00008100); + INSTANCE_WR(ctx, 0x00b2c/4, 0x00000001); + INSTANCE_WR(ctx, 0x00b70/4, 0x00001001); + INSTANCE_WR(ctx, 0x00b7c/4, 0x00000003); + INSTANCE_WR(ctx, 0x00b80/4, 0x00888001); + INSTANCE_WR(ctx, 0x00bb0/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bb4/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bb8/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bbc/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bc0/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bc4/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bc8/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bcc/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bd0/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bd4/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bd8/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bdc/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00be0/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00be4/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00be8/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bec/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bf0/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bf4/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bf8/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bfc/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c00/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c04/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c08/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c0c/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c10/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c14/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c18/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c1c/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c20/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c24/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c28/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c2c/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c54/4, 0x00000005); + INSTANCE_WR(ctx, 0x00c60/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00c7c/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c80/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c84/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c88/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c8c/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c90/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c94/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c98/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c9c/4, 0x00000001); + INSTANCE_WR(ctx, 0x00cd4/4, 0x00000001); + INSTANCE_WR(ctx, 0x00cd8/4, 0x08e00001); + INSTANCE_WR(ctx, 0x00cdc/4, 0x000e3000); + for(i=0x030a0; i<=0x03118; i+=8) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for(i=0x098a0; i<=0x0ba90; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for(i=0x0baa0; i<=0x0be90; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for(i=0x0e2e0; i<=0x0fff0; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for(i=0x10008; i<=0x104d0; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for(i=0x104e0; i<=0x108d0; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for(i=0x12d20; i<=0x14f10; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for(i=0x14f20; i<=0x15310; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for(i=0x17760; i<=0x19950; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for(i=0x19960; i<=0x19d50; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for(i=0x1c1a0; i<=0x1e390; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for(i=0x1e3a0; i<=0x1e790; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for(i=0x20be0; i<=0x22dd0; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for(i=0x22de0; i<=0x231d0; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); +} + +static void +nv4a_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i; + + INSTANCE_WR(ctx, 0x00000/4, ctx->im_pramin->start); + 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 +nv4b_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i; + + INSTANCE_WR(ctx, 0x00000/4, ctx->im_pramin->start); + INSTANCE_WR(ctx, 0x00004/4, 0x0000c040); + INSTANCE_WR(ctx, 0x00008/4, 0x0000c040); + INSTANCE_WR(ctx, 0x0000c/4, 0x0000c040); + INSTANCE_WR(ctx, 0x00010/4, 0x0000c040); + INSTANCE_WR(ctx, 0x00014/4, 0x0000c040); + INSTANCE_WR(ctx, 0x00018/4, 0x0000c040); + INSTANCE_WR(ctx, 0x0001c/4, 0x0000c040); + INSTANCE_WR(ctx, 0x00020/4, 0x0000c040); + INSTANCE_WR(ctx, 0x000c4/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x000c8/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x000d0/4, 0x00000001); + INSTANCE_WR(ctx, 0x001bc/4, 0x20010001); + INSTANCE_WR(ctx, 0x001c0/4, 0x0f73ef00); + INSTANCE_WR(ctx, 0x001c8/4, 0x02008821); + INSTANCE_WR(ctx, 0x00218/4, 0x00000040); + INSTANCE_WR(ctx, 0x0021c/4, 0x00000040); + INSTANCE_WR(ctx, 0x00220/4, 0x00000040); + INSTANCE_WR(ctx, 0x00228/4, 0x00000040); + INSTANCE_WR(ctx, 0x00234/4, 0x80000000); + INSTANCE_WR(ctx, 0x00238/4, 0x80000000); + INSTANCE_WR(ctx, 0x0023c/4, 0x80000000); + INSTANCE_WR(ctx, 0x00240/4, 0x80000000); + INSTANCE_WR(ctx, 0x00244/4, 0x80000000); + INSTANCE_WR(ctx, 0x00248/4, 0x80000000); + INSTANCE_WR(ctx, 0x0024c/4, 0x80000000); + INSTANCE_WR(ctx, 0x00250/4, 0x80000000); + INSTANCE_WR(ctx, 0x00270/4, 0x0b0b0b0c); + INSTANCE_WR(ctx, 0x003e0/4, 0x00040000); + INSTANCE_WR(ctx, 0x003f0/4, 0x55555555); + INSTANCE_WR(ctx, 0x003f4/4, 0x55555555); + INSTANCE_WR(ctx, 0x003f8/4, 0x55555555); + INSTANCE_WR(ctx, 0x003fc/4, 0x55555555); + INSTANCE_WR(ctx, 0x00428/4, 0x00000008); + INSTANCE_WR(ctx, 0x0043c/4, 0x00001010); + INSTANCE_WR(ctx, 0x00460/4, 0x00000111); + INSTANCE_WR(ctx, 0x00464/4, 0x00000111); + INSTANCE_WR(ctx, 0x00468/4, 0x00000111); + INSTANCE_WR(ctx, 0x0046c/4, 0x00000111); + INSTANCE_WR(ctx, 0x00470/4, 0x00000111); + INSTANCE_WR(ctx, 0x00474/4, 0x00000111); + INSTANCE_WR(ctx, 0x00478/4, 0x00000111); + INSTANCE_WR(ctx, 0x0047c/4, 0x00000111); + INSTANCE_WR(ctx, 0x00480/4, 0x00000111); + INSTANCE_WR(ctx, 0x00484/4, 0x00000111); + INSTANCE_WR(ctx, 0x00488/4, 0x00000111); + INSTANCE_WR(ctx, 0x0048c/4, 0x00000111); + INSTANCE_WR(ctx, 0x00490/4, 0x00000111); + INSTANCE_WR(ctx, 0x00494/4, 0x00000111); + INSTANCE_WR(ctx, 0x00498/4, 0x00000111); + INSTANCE_WR(ctx, 0x0049c/4, 0x00000111); + INSTANCE_WR(ctx, 0x004f4/4, 0x00000111); + INSTANCE_WR(ctx, 0x004f8/4, 0x00080060); + INSTANCE_WR(ctx, 0x00514/4, 0x00000080); + INSTANCE_WR(ctx, 0x00518/4, 0xffff0000); + INSTANCE_WR(ctx, 0x0051c/4, 0x00000001); + INSTANCE_WR(ctx, 0x00530/4, 0x46400000); + INSTANCE_WR(ctx, 0x00540/4, 0xffff0000); + INSTANCE_WR(ctx, 0x00544/4, 0x88888888); + INSTANCE_WR(ctx, 0x00548/4, 0x88888888); + INSTANCE_WR(ctx, 0x0054c/4, 0x88888888); + INSTANCE_WR(ctx, 0x00550/4, 0x88888888); + INSTANCE_WR(ctx, 0x00554/4, 0x88888888); + INSTANCE_WR(ctx, 0x00558/4, 0x88888888); + INSTANCE_WR(ctx, 0x0055c/4, 0x88888888); + INSTANCE_WR(ctx, 0x00560/4, 0x88888888); + INSTANCE_WR(ctx, 0x00564/4, 0x88888888); + INSTANCE_WR(ctx, 0x00568/4, 0x88888888); + INSTANCE_WR(ctx, 0x0056c/4, 0x88888888); + INSTANCE_WR(ctx, 0x00570/4, 0x88888888); + INSTANCE_WR(ctx, 0x00574/4, 0x88888888); + INSTANCE_WR(ctx, 0x00578/4, 0x88888888); + INSTANCE_WR(ctx, 0x0057c/4, 0x88888888); + INSTANCE_WR(ctx, 0x00580/4, 0x88888888); + INSTANCE_WR(ctx, 0x00594/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x00598/4, 0x0fff0000); + INSTANCE_WR(ctx, 0x005a0/4, 0x00011100); + INSTANCE_WR(ctx, 0x005bc/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005c0/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005c4/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005c8/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005cc/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005d0/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005d4/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005d8/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005dc/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005e0/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005e4/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005e8/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005ec/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005f0/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005f4/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x005f8/4, 0x07ff0000); + INSTANCE_WR(ctx, 0x00604/4, 0x4b7fffff); + INSTANCE_WR(ctx, 0x0062c/4, 0x30201000); + INSTANCE_WR(ctx, 0x00630/4, 0x70605040); + INSTANCE_WR(ctx, 0x00634/4, 0xb8a89888); + INSTANCE_WR(ctx, 0x00638/4, 0xf8e8d8c8); + INSTANCE_WR(ctx, 0x0064c/4, 0x40100000); + INSTANCE_WR(ctx, 0x00668/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x0069c/4, 0x435185d6); + INSTANCE_WR(ctx, 0x006a0/4, 0x2155b699); + INSTANCE_WR(ctx, 0x006a4/4, 0xfedcba98); + INSTANCE_WR(ctx, 0x006a8/4, 0x00000098); + INSTANCE_WR(ctx, 0x006b8/4, 0xffffffff); + INSTANCE_WR(ctx, 0x006bc/4, 0x00ff7000); + INSTANCE_WR(ctx, 0x006c0/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x006d0/4, 0x00ff0000); + INSTANCE_WR(ctx, 0x0070c/4, 0x00ffff00); + for (i=0x00750; i<=0x0078c; i+=4) + INSTANCE_WR(ctx, i/4, 0x00018488); + for (i=0x00790; i<=0x007cc; i+=4) + INSTANCE_WR(ctx, i/4, 0x00028202); + for (i=0x00810; i<=0x0084c; i+=4) + INSTANCE_WR(ctx, i/4, 0x0000aae4); + for (i=0x00850; i<=0x0088c; i+=4) + INSTANCE_WR(ctx, i/4, 0x01012000); + for (i=0x00890; i<=0x008cc; i+=4) + INSTANCE_WR(ctx, i/4, 0x00080008); + for (i=0x00910; i<=0x0094c; i+=4) + INSTANCE_WR(ctx, i/4, 0x00100008); + for (i=0x009a0; i<=0x009ac; i+=4) + INSTANCE_WR(ctx, i/4, 0x0001bc80); + for (i=0x009b0; i<=0x009bc; i+=4) + INSTANCE_WR(ctx, i/4, 0x00000202); + for (i=0x009d0; i<=0x009dc; i+=4) + INSTANCE_WR(ctx, i/4, 0x00000008); + for (i=0x009f0; i<=0x009fc; i+=4) + INSTANCE_WR(ctx, i/4, 0x00080008); + INSTANCE_WR(ctx, 0x00a10/4, 0x00000002); + INSTANCE_WR(ctx, 0x00a44/4, 0x00000421); + INSTANCE_WR(ctx, 0x00a48/4, 0x030c30c3); + INSTANCE_WR(ctx, 0x00a54/4, 0x3e020200); + INSTANCE_WR(ctx, 0x00a58/4, 0x00ffffff); + INSTANCE_WR(ctx, 0x00a5c/4, 0x20103f00); + INSTANCE_WR(ctx, 0x00a68/4, 0x00040000); + INSTANCE_WR(ctx, 0x00aa0/4, 0x00008100); + INSTANCE_WR(ctx, 0x00b2c/4, 0x00000001); + INSTANCE_WR(ctx, 0x00b70/4, 0x00001001); + INSTANCE_WR(ctx, 0x00b7c/4, 0x00000003); + INSTANCE_WR(ctx, 0x00b80/4, 0x00888001); + INSTANCE_WR(ctx, 0x00bb0/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bb4/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bb8/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bbc/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bc0/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bc4/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bc8/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bcc/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bd0/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bd4/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bd8/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bdc/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00be0/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00be4/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00be8/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bec/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bf0/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bf4/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bf8/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00bfc/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c00/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c04/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c08/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c0c/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c10/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c14/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c18/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c1c/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c20/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c24/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c28/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c2c/4, 0xffffffff); + INSTANCE_WR(ctx, 0x00c54/4, 0x00000005); + INSTANCE_WR(ctx, 0x00c60/4, 0x0000ffff); + INSTANCE_WR(ctx, 0x00c7c/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c80/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c84/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c88/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c8c/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c90/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c94/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c98/4, 0x00005555); + INSTANCE_WR(ctx, 0x00c9c/4, 0x00000001); + INSTANCE_WR(ctx, 0x00cd4/4, 0x00000001); + INSTANCE_WR(ctx, 0x00cd8/4, 0x08e00001); + INSTANCE_WR(ctx, 0x00cdc/4, 0x000e3000); + for(i=0x030a0; i<=0x03118; i+=8) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for(i=0x098a0; i<=0x0ba90; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for(i=0x0baa0; i<=0x0be90; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for(i=0x0e2e0; i<=0x0fff0; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for(i=0x10008; i<=0x104d0; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for(i=0x104e0; i<=0x108d0; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for(i=0x12d20; i<=0x14f10; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for(i=0x14f20; i<=0x15310; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); + for(i=0x17760; i<=0x19950; i+=24) + INSTANCE_WR(ctx, i/4, 0x00000001); + for(i=0x19960; i<=0x19d50; i+=16) + INSTANCE_WR(ctx, i/4, 0x3f800000); +} + +static void +nv4c_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i; + + INSTANCE_WR(ctx, 0x00000/4, ctx->im_pramin->start); + 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(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i; + + INSTANCE_WR(ctx, 0x00000/4, ctx->im_pramin->start); + 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_create_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *); + unsigned int ctx_size; + int ret; + + 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 0x49: + ctx_size = NV49_GRCTX_SIZE; + ctx_init = nv49_graph_context_init; + break; + case 0x44: + case 0x4a: + ctx_size = NV4A_GRCTX_SIZE; + ctx_init = nv4a_graph_context_init; + break; + case 0x4b: + ctx_size = NV4B_GRCTX_SIZE; + ctx_init = nv4b_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; + } + + if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, ctx_size, 16, + NVOBJ_FLAG_ZERO_ALLOC, + &chan->ramin_grctx))) + return ret; + + /* Initialise default context values */ + ctx_init(dev, chan->ramin_grctx->gpuobj); + + return 0; +} + +void +nv40_graph_destroy_context(struct nouveau_channel *chan) +{ + nouveau_gpuobj_ref_del(chan->dev, &chan->ramin_grctx); +} + +static int +nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t old_cp, tv = 1000, tmp; + int i; + + old_cp = NV_READ(NV20_PGRAPH_CHANNEL_CTX_POINTER); + NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); + + tmp = NV_READ(NV40_PGRAPH_CTXCTL_0310); + tmp |= save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE : + NV40_PGRAPH_CTXCTL_0310_XFER_LOAD; + NV_WRITE(NV40_PGRAPH_CTXCTL_0310, tmp); + + tmp = NV_READ(NV40_PGRAPH_CTXCTL_0304); + tmp |= NV40_PGRAPH_CTXCTL_0304_XFER_CTX; + NV_WRITE(NV40_PGRAPH_CTXCTL_0304, tmp); + + for (i = 0; i < tv; i++) { + if (NV_READ(NV40_PGRAPH_CTXCTL_030C) == 0) + break; + } + + NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, old_cp); + + if (i == tv) { + uint32_t ucstat = NV_READ(NV40_PGRAPH_CTXCTL_UCODE_STAT); + DRM_ERROR("Failed: Instance=0x%08x Save=%d\n", inst, save); + DRM_ERROR("IP: 0x%02x, Opcode: 0x%08x\n", + ucstat >> NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT, + ucstat & NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK); + DRM_ERROR("0x40030C = 0x%08x\n", + NV_READ(NV40_PGRAPH_CTXCTL_030C)); + return -EBUSY; + } + + return 0; +} + +/* Save current context (from PGRAPH) into the channel's context + *XXX: fails sometimes, not sure why.. + */ +int +nv40_graph_save_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + uint32_t inst; + + if (!chan->ramin_grctx) + return -EINVAL; + inst = chan->ramin_grctx->instance >> 4; + + return nv40_graph_transfer_context(dev, inst, 1); +} + +/* Restore the context for a specific channel into PGRAPH + * XXX: fails sometimes.. not sure why + */ +int +nv40_graph_load_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t inst; + int ret; + + if (!chan->ramin_grctx) + return -EINVAL; + inst = chan->ramin_grctx->instance >> 4; + + ret = nv40_graph_transfer_context(dev, inst, 0); + if (ret) + return ret; + + /* 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(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); + NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, + (inst & NV40_PGRAPH_CTXCTL_CUR_INST_MASK) | + NV40_PGRAPH_CTXCTL_CUR_LOADED); + /* 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, inst); + return 0; +} + +/* 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[] = { +/*(DEBLOBBED)*/ + ~0 +}; + +static uint32_t nv43_ctx_voodoo[] = { +/*(DEBLOBBED)*/ + ~0 +}; + +static uint32_t nv44_ctx_voodoo[] = { +/*(DEBLOBBED)*/~0 +}; + +static uint32_t nv46_ctx_voodoo[] = { +/*(DEBLOBBED)*/~0 +}; + +//this is used for nv49 and nv4b +static uint32_t nv49_4b_ctx_voodoo[] ={ +/*(DEBLOBBED)*/~0 +}; + + +static uint32_t nv4a_ctx_voodoo[] = { +/*(DEBLOBBED)*/~0 +}; + +static uint32_t nv4c_ctx_voodoo[] = { +/*(DEBLOBBED)*/~0 +}; + +static uint32_t nv4e_ctx_voodoo[] = { +/*(DEBLOBBED)*/~0 +}; + +/* + * G70 0x47 + * G71 0x49 + * NV45 0x48 + * G72[M] 0x46 + * G73 0x4b + * C51_G7X 0x4c + * C51 0x4e + */ +int +nv40_graph_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = + (struct drm_nouveau_private *)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 0x44: ctx_voodoo = nv44_ctx_voodoo; break; + case 0x46: ctx_voodoo = nv46_ctx_voodoo; break; + case 0x49: ctx_voodoo = nv49_4b_ctx_voodoo; break; + case 0x4a: ctx_voodoo = nv4a_ctx_voodoo; break; + case 0x4b: ctx_voodoo = nv49_4b_ctx_voodoo; break; + case 0x4c: ctx_voodoo = nv4c_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(NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); + while (ctx_voodoo[i] != ~0) { + NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_DATA, ctx_voodoo[i]); + i++; + } + } + + /* No context present currently */ + NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, 0x00000000); + + NV_WRITE(NV03_PGRAPH_INTR , 0xFFFFFFFF); + NV_WRITE(NV40_PGRAPH_INTR_EN, 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(struct drm_device *dev) +{ +} + diff --git a/drivers/char/drm/nv40_mc.c b/drivers/char/drm/nv40_mc.c new file mode 100644 index 0000000..c7db902 --- /dev/null +++ b/drivers/char/drm/nv40_mc.c @@ -0,0 +1,39 @@ +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" +#include "nouveau_drm.h" + +int +nv40_mc_init(struct drm_device *dev) +{ + struct drm_nouveau_private *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); + + 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(struct drm_device *dev) +{ +} + diff --git a/drivers/char/drm/nv50_fifo.c b/drivers/char/drm/nv50_fifo.c new file mode 100644 index 0000000..7859544 --- /dev/null +++ b/drivers/char/drm/nv50_fifo.c @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2007 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +typedef struct { + struct nouveau_gpuobj_ref *thingo; +} nv50_fifo_priv; + +#define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50) + +static void +nv50_fifo_init_thingo(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv; + struct nouveau_gpuobj_ref *thingo = priv->thingo; + int i, fi=2; + + DRM_DEBUG("\n"); + + INSTANCE_WR(thingo->gpuobj, 0, 0x7e); + INSTANCE_WR(thingo->gpuobj, 1, 0x7e); + for (i = 1; i < 127; i++, fi) { + if (dev_priv->fifos[i]) { + INSTANCE_WR(thingo->gpuobj, fi, i); + fi++; + } + } + + NV_WRITE(0x32f4, thingo->instance >> 12); + NV_WRITE(0x32ec, fi); + NV_WRITE(0x2500, 0x101); +} + +static int +nv50_fifo_channel_enable(struct drm_device *dev, int channel, int nt) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = dev_priv->fifos[channel]; + uint32_t inst; + + DRM_DEBUG("ch%d\n", channel); + + if (!chan->ramfc) + return -EINVAL; + + if (IS_G80) inst = chan->ramfc->instance >> 12; + else inst = chan->ramfc->instance >> 8; + NV_WRITE(NV50_PFIFO_CTX_TABLE(channel), + inst | NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED); + + if (!nt) nv50_fifo_init_thingo(dev); + return 0; +} + +static void +nv50_fifo_channel_disable(struct drm_device *dev, int channel, int nt) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t inst; + + DRM_DEBUG("ch%d, nt=%d\n", channel, nt); + + if (IS_G80) inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80; + else inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84; + NV_WRITE(NV50_PFIFO_CTX_TABLE(channel), inst); + + if (!nt) nv50_fifo_init_thingo(dev); +} + +static void +nv50_fifo_init_reset(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t pmc_e; + + DRM_DEBUG("\n"); + + pmc_e = NV_READ(NV03_PMC_ENABLE); + NV_WRITE(NV03_PMC_ENABLE, pmc_e & ~NV_PMC_ENABLE_PFIFO); + pmc_e = NV_READ(NV03_PMC_ENABLE); + NV_WRITE(NV03_PMC_ENABLE, pmc_e | NV_PMC_ENABLE_PFIFO); +} + +static void +nv50_fifo_init_intr(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + DRM_DEBUG("\n"); + + NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF); + NV_WRITE(NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF); +} + +static void +nv50_fifo_init_context_table(struct drm_device *dev) +{ + int i; + + DRM_DEBUG("\n"); + + for (i = 0; i < NV50_PFIFO_CTX_TABLE__SIZE; i++) + nv50_fifo_channel_disable(dev, i, 1); + nv50_fifo_init_thingo(dev); +} + +static void +nv50_fifo_init_regs__nv(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + DRM_DEBUG("\n"); + + NV_WRITE(0x250c, 0x6f3cfc34); +} + +static int +nv50_fifo_init_regs(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + DRM_DEBUG("\n"); + + NV_WRITE(0x2500, 0); + NV_WRITE(0x3250, 0); + NV_WRITE(0x3220, 0); + NV_WRITE(0x3204, 0); + NV_WRITE(0x3210, 0); + NV_WRITE(0x3270, 0); + + /* Enable dummy channels setup by nv50_instmem.c */ + nv50_fifo_channel_enable(dev, 0, 1); + nv50_fifo_channel_enable(dev, 127, 1); + + return 0; +} + +int +nv50_fifo_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + nv50_fifo_priv *priv; + int ret; + + DRM_DEBUG("\n"); + + priv = drm_calloc(1, sizeof(*priv), DRM_MEM_DRIVER); + if (!priv) + return -ENOMEM; + dev_priv->Engine.fifo.priv = priv; + + nv50_fifo_init_reset(dev); + nv50_fifo_init_intr(dev); + + if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, (128+2)*4, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, + &priv->thingo))) { + DRM_ERROR("error creating thingo: %d\n", ret); + return ret; + } + + nv50_fifo_init_context_table(dev); + + nv50_fifo_init_regs__nv(dev); + if ((ret = nv50_fifo_init_regs(dev))) + return ret; + + return 0; +} + +void +nv50_fifo_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv; + + DRM_DEBUG("\n"); + + if (!priv) + return; + + nouveau_gpuobj_ref_del(dev, &priv->thingo); + + dev_priv->Engine.fifo.priv = NULL; + drm_free(priv, sizeof(*priv), DRM_MEM_DRIVER); +} + +int +nv50_fifo_create_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *ramfc = NULL; + int ret; + + DRM_DEBUG("ch%d\n", chan->id); + + if (IS_G80) { + uint32_t ramfc_offset = chan->ramin->gpuobj->im_pramin->start; + uint32_t vram_offset = chan->ramin->gpuobj->im_backing->start; + if ((ret = nouveau_gpuobj_new_fake(dev, ramfc_offset, + vram_offset, 0x100, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, + &ramfc, &chan->ramfc))) + return ret; + } else { + if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 0x100, + 256, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, + &chan->ramfc))) + return ret; + ramfc = chan->ramfc->gpuobj; + } + + INSTANCE_WR(ramfc, 0x48/4, chan->pushbuf->instance >> 4); + INSTANCE_WR(ramfc, 0x80/4, (0xc << 24) | (chan->ramht->instance >> 4)); + INSTANCE_WR(ramfc, 0x3c/4, 0x000f0078); /* fetch? */ + INSTANCE_WR(ramfc, 0x44/4, 0x2101ffff); + INSTANCE_WR(ramfc, 0x60/4, 0x7fffffff); + INSTANCE_WR(ramfc, 0x10/4, 0x00000000); + INSTANCE_WR(ramfc, 0x08/4, 0x00000000); + INSTANCE_WR(ramfc, 0x40/4, 0x00000000); + INSTANCE_WR(ramfc, 0x50/4, 0x2039b2e0); + INSTANCE_WR(ramfc, 0x54/4, 0x000f0000); + INSTANCE_WR(ramfc, 0x7c/4, 0x30000001); + INSTANCE_WR(ramfc, 0x78/4, 0x00000000); + INSTANCE_WR(ramfc, 0x4c/4, chan->pushbuf_mem->size - 1); + + if (!IS_G80) { + INSTANCE_WR(chan->ramin->gpuobj, 0, chan->id); + INSTANCE_WR(chan->ramin->gpuobj, 1, chan->ramfc->instance); + + INSTANCE_WR(ramfc, 0x88/4, 0x3d520); /* some vram addy >> 10 */ + INSTANCE_WR(ramfc, 0x98/4, chan->ramin->instance >> 12); + } + + if ((ret = nv50_fifo_channel_enable(dev, chan->id, 0))) { + DRM_ERROR("error enabling ch%d: %d\n", chan->id, ret); + nouveau_gpuobj_ref_del(dev, &chan->ramfc); + return ret; + } + + return 0; +} + +void +nv50_fifo_destroy_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + + DRM_DEBUG("ch%d\n", chan->id); + + nv50_fifo_channel_disable(dev, chan->id, 0); + + /* Dummy channel, also used on ch 127 */ + if (chan->id == 0) + nv50_fifo_channel_disable(dev, 127, 0); + + nouveau_gpuobj_ref_del(dev, &chan->ramfc); +} + +int +nv50_fifo_load_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *ramfc = chan->ramfc->gpuobj; + + DRM_DEBUG("ch%d\n", chan->id); + + /*XXX: incomplete, only touches the regs that NV does */ + + NV_WRITE(0x3244, 0); + NV_WRITE(0x3240, 0); + + NV_WRITE(0x3224, INSTANCE_RD(ramfc, 0x3c/4)); + NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE, INSTANCE_RD(ramfc, 0x48/4)); + NV_WRITE(0x3234, INSTANCE_RD(ramfc, 0x4c/4)); + NV_WRITE(0x3254, 1); + NV_WRITE(NV03_PFIFO_RAMHT, INSTANCE_RD(ramfc, 0x80/4)); + + if (!IS_G80) { + NV_WRITE(0x340c, INSTANCE_RD(ramfc, 0x88/4)); + NV_WRITE(0x3410, INSTANCE_RD(ramfc, 0x98/4)); + } + + NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16)); + return 0; +} + +int +nv50_fifo_save_context(struct nouveau_channel *chan) +{ + DRM_DEBUG("ch%d\n", chan->id); + DRM_ERROR("stub!\n"); + return 0; +} + diff --git a/drivers/char/drm/nv50_graph.c b/drivers/char/drm/nv50_graph.c new file mode 100644 index 0000000..e5bbf65 --- /dev/null +++ b/drivers/char/drm/nv50_graph.c @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2007 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +#define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50) + +static void +nv50_graph_init_reset(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t pmc_e; + + DRM_DEBUG("\n"); + + pmc_e = NV_READ(NV03_PMC_ENABLE); + NV_WRITE(NV03_PMC_ENABLE, pmc_e & ~NV_PMC_ENABLE_PGRAPH); + pmc_e = NV_READ(NV03_PMC_ENABLE); + NV_WRITE(NV03_PMC_ENABLE, pmc_e | NV_PMC_ENABLE_PGRAPH); +} + +static void +nv50_graph_init_intr(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + DRM_DEBUG("\n"); + NV_WRITE(NV03_PGRAPH_INTR, 0xffffffff); + NV_WRITE(NV40_PGRAPH_INTR_EN, 0xffffffff); +} + +static void +nv50_graph_init_regs__nv(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + DRM_DEBUG("\n"); + + NV_WRITE(0x400804, 0xc0000000); + NV_WRITE(0x406800, 0xc0000000); + NV_WRITE(0x400c04, 0xc0000000); + NV_WRITE(0x401804, 0xc0000000); + NV_WRITE(0x405018, 0xc0000000); + NV_WRITE(0x402000, 0xc0000000); + + NV_WRITE(0x400108, 0xffffffff); + + NV_WRITE(0x400824, 0x00004000); + NV_WRITE(0x400500, 0x00010001); +} + +static void +nv50_graph_init_regs(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + DRM_DEBUG("\n"); + + NV_WRITE(NV04_PGRAPH_DEBUG_3, (1<<2) /* HW_CONTEXT_SWITCH_ENABLED */); +} + +static uint32_t nv84_ctx_voodoo[] = { +/*(DEBLOBBED)*/~0 +}; + +static void +nv50_graph_init_ctxctl(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t *voodoo; + + DRM_DEBUG("\n"); + + switch (dev_priv->chipset) { + case 0x84: + voodoo = nv84_ctx_voodoo; + break; + default: + DRM_ERROR("no voodoo for chipset NV%02x\n", dev_priv->chipset); + break; + } + + if (voodoo) { + NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); + while (*voodoo != ~0) { + NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_DATA, *voodoo); + voodoo++; + } + } + + NV_WRITE(0x400320, 4); + NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, 0); + NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, 0); +} + +int +nv50_graph_init(struct drm_device *dev) +{ + DRM_DEBUG("\n"); + + nv50_graph_init_reset(dev); + nv50_graph_init_intr(dev); + nv50_graph_init_regs__nv(dev); + nv50_graph_init_regs(dev); + nv50_graph_init_ctxctl(dev); + + return 0; +} + +void +nv50_graph_takedown(struct drm_device *dev) +{ + DRM_DEBUG("\n"); +} + +int +nv50_graph_create_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->Engine; + struct nouveau_gpuobj *ramin = chan->ramin->gpuobj; + int grctx_size = 0x60000, hdr; + int ret; + + DRM_DEBUG("ch%d\n", chan->id); + + if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, + grctx_size, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, + &chan->ramin_grctx))) + return ret; + + hdr = IS_G80 ? 0x200 : 0x20; + INSTANCE_WR(ramin, (hdr + 0x00)/4, 0x00190002); + INSTANCE_WR(ramin, (hdr + 0x04)/4, chan->ramin_grctx->instance + + grctx_size - 1); + INSTANCE_WR(ramin, (hdr + 0x08)/4, chan->ramin_grctx->instance); + INSTANCE_WR(ramin, (hdr + 0x0c)/4, 0); + INSTANCE_WR(ramin, (hdr + 0x10)/4, 0); + INSTANCE_WR(ramin, (hdr + 0x14)/4, 0x00010000); + + if ((ret = engine->graph.load_context(chan))) { + DRM_ERROR("Error hacking up initial context: %d\n", ret); + return ret; + } + + return 0; +} + +void +nv50_graph_destroy_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i, hdr; + + DRM_DEBUG("ch%d\n", chan->id); + + hdr = IS_G80 ? 0x200 : 0x20; + for (i=hdr; iramin->gpuobj, i/4, 0); + + nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); +} + +static int +nv50_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t old_cp, tv = 20000; + int i; + + DRM_DEBUG("inst=0x%08x, save=%d\n", inst, save); + + old_cp = NV_READ(NV20_PGRAPH_CHANNEL_CTX_POINTER); + NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst | (1<<31)); + NV_WRITE(0x400824, NV_READ(0x400824) | + (save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE : + NV40_PGRAPH_CTXCTL_0310_XFER_LOAD)); + NV_WRITE(NV40_PGRAPH_CTXCTL_0304, NV40_PGRAPH_CTXCTL_0304_XFER_CTX); + + for (i = 0; i < tv; i++) { + if (NV_READ(NV40_PGRAPH_CTXCTL_030C) == 0) + break; + } + NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, old_cp); + + if (i == tv) { + DRM_ERROR("failed: inst=0x%08x save=%d\n", inst, save); + DRM_ERROR("0x40030C = 0x%08x\n", + NV_READ(NV40_PGRAPH_CTXCTL_030C)); + return -EBUSY; + } + + return 0; +} + +int +nv50_graph_load_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t inst = ((chan->ramin->instance >> 12) | (1<<31)); + int ret; (void)ret; + + DRM_DEBUG("ch%d\n", chan->id); + +#if 0 + if ((ret = nv50_graph_transfer_context(dev, inst, 0))) + return ret; +#endif + + NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); + NV_WRITE(0x400320, 4); + NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, inst); + + return 0; +} + +int +nv50_graph_save_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + uint32_t inst = ((chan->ramin->instance >> 12) | (1<<31)); + + DRM_DEBUG("ch%d\n", chan->id); + + return nv50_graph_transfer_context(dev, inst, 1); +} + diff --git a/drivers/char/drm/nv50_instmem.c b/drivers/char/drm/nv50_instmem.c new file mode 100644 index 0000000..1eeb54d --- /dev/null +++ b/drivers/char/drm/nv50_instmem.c @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2007 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +typedef struct { + uint32_t save1700[5]; /* 0x1700->0x1710 */ + + struct nouveau_gpuobj_ref *pramin_pt; + struct nouveau_gpuobj_ref *pramin_bar; +} nv50_instmem_priv; + +#define NV50_INSTMEM_PAGE_SHIFT 12 +#define NV50_INSTMEM_PAGE_SIZE (1 << NV50_INSTMEM_PAGE_SHIFT) +#define NV50_INSTMEM_PT_SIZE(a) (((a) >> 12) << 3) + +/*NOTE: - Assumes 0x1700 already covers the correct MiB of PRAMIN + */ +#define BAR0_WI32(g,o,v) do { \ + uint32_t offset; \ + if ((g)->im_backing) { \ + offset = (g)->im_backing->start; \ + } else { \ + offset = chan->ramin->gpuobj->im_backing->start; \ + offset += (g)->im_pramin->start; \ + } \ + offset += (o); \ + NV_WRITE(NV_RAMIN + (offset & 0xfffff), (v)); \ +} while(0) + +int +nv50_instmem_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan; + uint32_t c_offset, c_size, c_ramfc, c_vmpd, c_base, pt_size; + nv50_instmem_priv *priv; + int ret, i; + uint32_t v; + + priv = drm_calloc(1, sizeof(*priv), DRM_MEM_DRIVER); + if (!priv) + return -ENOMEM; + dev_priv->Engine.instmem.priv = priv; + + /* Reserve the last MiB of VRAM, we should probably try to avoid + * setting up the below tables over the top of the VBIOS image at + * some point. + */ + dev_priv->ramin_rsvd_vram = 1 << 20; + c_offset = nouveau_mem_fb_amount(dev) - dev_priv->ramin_rsvd_vram; + c_size = 128 << 10; + c_vmpd = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x1400 : 0x200; + c_ramfc = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x0 : 0x20; + c_base = c_vmpd + 0x4000; + pt_size = NV50_INSTMEM_PT_SIZE(dev_priv->ramin->size); + + DRM_DEBUG(" Rsvd VRAM base: 0x%08x\n", c_offset); + DRM_DEBUG(" VBIOS image: 0x%08x\n", (NV_READ(0x619f04)&~0xff)<<8); + DRM_DEBUG(" Aperture size: %d MiB\n", + (uint32_t)dev_priv->ramin->size >> 20); + DRM_DEBUG(" PT size: %d KiB\n", pt_size >> 10); + + NV_WRITE(NV50_PUNK_BAR0_PRAMIN, (c_offset >> 16)); + + /* Create a fake channel, and use it as our "dummy" channels 0/127. + * The main reason for creating a channel is so we can use the gpuobj + * code. However, it's probably worth noting that NVIDIA also setup + * their channels 0/127 with the same values they configure here. + * So, there may be some other reason for doing this. + * + * Have to create the entire channel manually, as the real channel + * creation code assumes we have PRAMIN access, and we don't until + * we're done here. + */ + chan = drm_calloc(1, sizeof(*chan), DRM_MEM_DRIVER); + if (!chan) + return -ENOMEM; + chan->id = 0; + chan->dev = dev; + chan->file_priv = (struct drm_file *)-2; + dev_priv->fifos[0] = dev_priv->fifos[127] = chan; + + /* Channel's PRAMIN object + heap */ + if ((ret = nouveau_gpuobj_new_fake(dev, 0, c_offset, 128<<10, 0, + NULL, &chan->ramin))) + return ret; + + if (nouveau_mem_init_heap(&chan->ramin_heap, c_base, c_size - c_base)) + return -ENOMEM; + + /* RAMFC + zero channel's PRAMIN up to start of VM pagedir */ + if ((ret = nouveau_gpuobj_new_fake(dev, c_ramfc, c_offset + c_ramfc, + 0x4000, 0, NULL, &chan->ramfc))) + return ret; + + for (i = 0; i < c_vmpd; i += 4) + BAR0_WI32(chan->ramin->gpuobj, i, 0); + + /* VM page directory */ + if ((ret = nouveau_gpuobj_new_fake(dev, c_vmpd, c_offset + c_vmpd, + 0x4000, 0, &chan->vm_pd, NULL))) + return ret; + for (i = 0; i < 0x4000; i += 8) { + BAR0_WI32(chan->vm_pd, i + 0x00, 0x00000000); + BAR0_WI32(chan->vm_pd, i + 0x04, 0x00000000); + } + + /* PRAMIN page table, cheat and map into VM at 0x0000000000. + * We map the entire fake channel into the start of the PRAMIN BAR + */ + if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pt_size, 0x1000, + 0, &priv->pramin_pt))) + return ret; + + for (i = 0, v = c_offset; i < pt_size; i+=8, v+=0x1000) { + if (v < (c_offset + c_size)) + BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, v | 1); + else + BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, 0x00000009); + BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, 0x00000000); + } + + BAR0_WI32(chan->vm_pd, 0x00, priv->pramin_pt->instance | 0x63); + BAR0_WI32(chan->vm_pd, 0x04, 0x00000000); + + /* DMA object for PRAMIN BAR */ + if ((ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 6*4, 16, 0, + &priv->pramin_bar))) + return ret; + BAR0_WI32(priv->pramin_bar->gpuobj, 0x00, 0x7fc00000); + BAR0_WI32(priv->pramin_bar->gpuobj, 0x04, dev_priv->ramin->size - 1); + BAR0_WI32(priv->pramin_bar->gpuobj, 0x08, 0x00000000); + BAR0_WI32(priv->pramin_bar->gpuobj, 0x0c, 0x00000000); + BAR0_WI32(priv->pramin_bar->gpuobj, 0x10, 0x00000000); + BAR0_WI32(priv->pramin_bar->gpuobj, 0x14, 0x00000000); + + /* Poke the relevant regs, and pray it works :) */ + NV_WRITE(NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12)); + NV_WRITE(NV50_PUNK_UNK1710, 0); + NV_WRITE(NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12) | + NV50_PUNK_BAR_CFG_BASE_VALID); + NV_WRITE(NV50_PUNK_BAR1_CTXDMA, 0); + NV_WRITE(NV50_PUNK_BAR3_CTXDMA, (priv->pramin_bar->instance >> 4) | + NV50_PUNK_BAR3_CTXDMA_VALID); + + /* Assume that praying isn't enough, check that we can re-read the + * entire fake channel back from the PRAMIN BAR */ + for (i = 0; i < c_size; i+=4) { + if (NV_READ(NV_RAMIN + i) != NV_RI32(i)) { + DRM_ERROR("Error reading back PRAMIN at 0x%08x\n", i); + return -EINVAL; + } + } + + /* Global PRAMIN heap */ + if (nouveau_mem_init_heap(&dev_priv->ramin_heap, + c_size, dev_priv->ramin->size - c_size)) { + dev_priv->ramin_heap = NULL; + DRM_ERROR("Failed to init RAMIN heap\n"); + } + + /*XXX: incorrect, but needed to make hash func "work" */ + dev_priv->ramht_offset = 0x10000; + dev_priv->ramht_bits = 9; + dev_priv->ramht_size = (1 << dev_priv->ramht_bits); + return 0; +} + +void +nv50_instmem_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + nv50_instmem_priv *priv = dev_priv->Engine.instmem.priv; + struct nouveau_channel *chan = dev_priv->fifos[0]; + int i; + + DRM_DEBUG("\n"); + + if (!priv) + return; + + /* Restore state from before init */ + for (i = 0x1700; i <= 0x1710; i+=4) + NV_WRITE(i, priv->save1700[(i-0x1700)/4]); + + nouveau_gpuobj_ref_del(dev, &priv->pramin_bar); + nouveau_gpuobj_ref_del(dev, &priv->pramin_pt); + + /* Destroy dummy channel */ + if (chan) { + nouveau_gpuobj_del(dev, &chan->vm_pd); + nouveau_gpuobj_ref_del(dev, &chan->ramfc); + nouveau_gpuobj_ref_del(dev, &chan->ramin); + nouveau_mem_takedown(&chan->ramin_heap); + + dev_priv->fifos[0] = dev_priv->fifos[127] = NULL; + drm_free(chan, sizeof(*chan), DRM_MEM_DRIVER); + } + + dev_priv->Engine.instmem.priv = NULL; + drm_free(priv, sizeof(*priv), DRM_MEM_DRIVER); +} + +int +nv50_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, uint32_t *sz) +{ + if (gpuobj->im_backing) + return -EINVAL; + + *sz = (*sz + (NV50_INSTMEM_PAGE_SIZE-1)) & ~(NV50_INSTMEM_PAGE_SIZE-1); + if (*sz == 0) + return -EINVAL; + + gpuobj->im_backing = nouveau_mem_alloc(dev, NV50_INSTMEM_PAGE_SIZE, + *sz, NOUVEAU_MEM_FB, + (struct drm_file *)-2); + if (!gpuobj->im_backing) { + DRM_ERROR("Couldn't allocate vram to back PRAMIN pages\n"); + return -ENOMEM; + } + + return 0; +} + +void +nv50_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (gpuobj && gpuobj->im_backing) { + if (gpuobj->im_bound) + dev_priv->Engine.instmem.unbind(dev, gpuobj); + nouveau_mem_free(dev, gpuobj->im_backing); + gpuobj->im_backing = NULL; + } +} + +int +nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + nv50_instmem_priv *priv = dev_priv->Engine.instmem.priv; + uint32_t pte, pte_end, vram; + + if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) + return -EINVAL; + + DRM_DEBUG("st=0x%0llx sz=0x%0llx\n", + gpuobj->im_pramin->start, gpuobj->im_pramin->size); + + pte = (gpuobj->im_pramin->start >> 12) << 3; + pte_end = ((gpuobj->im_pramin->size >> 12) << 3) + pte; + vram = gpuobj->im_backing->start; + + DRM_DEBUG("pramin=0x%llx, pte=%d, pte_end=%d\n", + gpuobj->im_pramin->start, pte, pte_end); + DRM_DEBUG("first vram page: 0x%llx\n", + gpuobj->im_backing->start); + + while (pte < pte_end) { + INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 0)/4, vram | 1); + INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 4)/4, 0x00000000); + + pte += 8; + vram += NV50_INSTMEM_PAGE_SIZE; + } + + gpuobj->im_bound = 1; + return 0; +} + +int +nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + nv50_instmem_priv *priv = dev_priv->Engine.instmem.priv; + uint32_t pte, pte_end; + + if (gpuobj->im_bound == 0) + return -EINVAL; + + pte = (gpuobj->im_pramin->start >> 12) << 3; + pte_end = ((gpuobj->im_pramin->size >> 12) << 3) + pte; + while (pte < pte_end) { + INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 0)/4, 0x00000009); + INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 4)/4, 0x00000000); + pte += 8; + } + + gpuobj->im_bound = 0; + return 0; +} + diff --git a/drivers/char/drm/nv50_mc.c b/drivers/char/drm/nv50_mc.c new file mode 100644 index 0000000..b111826 --- /dev/null +++ b/drivers/char/drm/nv50_mc.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2007 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. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +int +nv50_mc_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + NV_WRITE(NV03_PMC_ENABLE, 0xFFFFFFFF); + + return 0; +} + +void nv50_mc_takedown(struct drm_device *dev) +{ +} -- 1.5.3.3