summaryrefslogtreecommitdiff
path: root/shared-core/nouveau_drv.h
AgeCommit message (Expand)Author
2008-01-22Merge branch 'master' into vblank-rework, including mach64 supportJesse Barnes
2007-11-14Revert "nouveau: stub superioctl"Ben Skeggs
2007-11-14Merge branch 'fifo-cleanup' into upstream-masterBen Skeggs
2007-11-14nouveau: store user control reg offsets in channel structBen Skeggs
2007-11-14nouveau: funcs to determine active channel on PFIFO.Ben Skeggs
2007-11-14nouveau: stub superioctlBen Skeggs
2007-11-05drm: remove lots of spurious whitespace.Dave Airlie
2007-11-05nouveau: cleanupsBen Skeggs
2007-11-05nouveau: crappy ttm mm init, disabled for now.Ben Skeggs
2007-11-02nouveau: put it all together.Jeremy Kolb
2007-10-31nouveau: ttm stubsJeremy Kolb
2007-10-30Merge branch 'master' into vblank-rework, fixup remaining driversJesse Barnes
2007-09-30nouveau: rename nv30_graph.c to nv20_graph.cPekka Paalanen
2007-09-30nouveau: nv30 graph function renames, removed nv20_graph.cPekka Paalanen
2007-09-30nouveau : pgraph_ctx dynamic alloc for nv04, nv10Matthieu Castet
2007-08-15nouveau: Allow GART notifiers when using sgdma code.Ben Skeggs
2007-08-15nouveau/nv40: Fix channel scheduling.Ben Skeggs
2007-08-10nouveau/nv50: demagic instmem setup.Ben Skeggs
2007-08-10nouveau: Allow creation of gpuobjs before any other init has taken place.Ben Skeggs
2007-08-08nouveau: Always allocate drm's push buffer in VRAMBen Skeggs
2007-08-06nouveau: Give DRM its own gpu channelBen Skeggs
2007-08-06nouveau: Various internal and external API changesBen Skeggs
2007-08-06nouveau: Pass channel struct around instead of channel id.Ben Skeggs
2007-07-20Replace DRM_IOCTL_ARGS with (dev, data, file_priv) and remove DRM_DEVICE.Eric Anholt
2007-07-20Replace filp in ioctl arguments with drm_file *file_priv.Eric Anholt
2007-07-18nouveau: Add read() method to Engine.timer.Pekka Paalanen
2007-07-17nouveau: G8x PCIEGARTBen Skeggs
2007-07-13nouveau: nuke internal typedefs, and drm_device_t use.Ben Skeggs
2007-07-12nouveau: separate region_offset into map_handle and offset.Ben Skeggs
2007-07-11Added support for PCIGART for PCI(E) cards. Bumped DRM interface patchlevel.Arthur Huillet
2007-07-09nouveau: Avoid oopsBen Skeggs
2007-07-09nouveau/nv50: Initial channel/object supportBen Skeggs
2007-07-09nouveau: rewrite gpu object codeBen Skeggs
2007-06-28nouveau: never touch PRAMIN with NV_WRITE, cleanup RAMHT code a bitBen Skeggs
2007-06-28nouveau: simplify PRAMIN accessBen Skeggs
2007-06-28nouveau/nv50: skeletal backendBen Skeggs
2007-06-28nouveau: Nuke DMA_OBJECT_INIT ioctl (bumps interface to 0.0.7)Ben Skeggs
2007-06-24nouveau: NV04/NV10/NV20 PGRAPH engtab functionsBen Skeggs
2007-06-24nouveau: NV3X PGRAPH engtab functionsBen Skeggs
2007-06-24nouveau: NV1X/2X/3X PFIFO engtab functionsBen Skeggs
2007-06-24nouveau: NV04 PFIFO engtab functionsBen Skeggs
2007-06-24nouveau: NV4X PGRAPH engtab functionsBen Skeggs
2007-06-24nouveau: NV4X PFIFO engtab functionsBen Skeggs
2007-06-24nouveau: (mostly) hook up put_base againBen Skeggs
2007-06-24nouveau: prototype PFIFO/PGRAPH engtab APIBen Skeggs
2007-06-24nouveau: rename engtab functionsBen Skeggs
2007-03-26nouveau: move card initialisation into the drmBen Skeggs
2007-03-23nouveau: remove unused cruftBen Skeggs
2007-03-21nouveau: support multiple channels per client (breaks drm interface)Ben Skeggs
2007-03-13nouveau: make sure cmdbuf object gets destroyedBen Skeggs
="hl str">", 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])) { be->func->clear(be); DRM_ERROR("pci_map_page failed\n"); return -EINVAL; } nvbe->pages_populated = ++d; } } return 0; } static void nouveau_sgdma_clear(struct drm_ttm_backend *be) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; int d; DRM_DEBUG("\n"); if (nvbe && nvbe->pagelist) { if (nvbe->is_bound) be->func->unbind(be); 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 drm_ttm_backend *be, struct drm_bo_mem_reg *mem) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; uint64_t offset = (mem->mm_node->start << PAGE_SHIFT); uint32_t i; DRM_DEBUG("pg=0x%lx (0x%llx), cached=%d\n", mem->mm_node->start, offset, (mem->flags & DRM_BO_FLAG_CACHED) == 1); 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 drm_ttm_backend *be) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; 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 drm_ttm_backend *be) { DRM_DEBUG("\n"); if (be) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; if (nvbe) { if (nvbe->pagelist) be->func->clear(be); drm_ctl_free(nvbe, sizeof(*nvbe), DRM_MEM_TTM); } } } static struct drm_ttm_backend_func nouveau_sgdma_backend = { .needs_ub_cache_adjust = nouveau_sgdma_needs_ub_cache_adjust, .populate = nouveau_sgdma_populate, .clear = nouveau_sgdma_clear, .bind = nouveau_sgdma_bind, .unbind = nouveau_sgdma_unbind, .destroy = nouveau_sgdma_destroy }; struct drm_ttm_backend * 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_ctl_calloc(1, sizeof(*nvbe), DRM_MEM_TTM); if (!nvbe) return NULL; nvbe->dev = dev; nvbe->backend.func = &nouveau_sgdma_backend; return &nvbe->backend; } 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; i<obj_size; i+=8) { INSTANCE_WR(gpuobj, (i+0)/4, 0); //x00000010); INSTANCE_WR(gpuobj, (i+4)/4, 0); //0x00000004); } } dev_priv->gart_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 drm_ttm_backend *be; struct drm_scatter_gather sgreq; struct drm_mm_node mm_node; struct drm_bo_mem_reg mem; int ret; dev_priv->gart_info.sg_be = nouveau_sgdma_init_ttm(dev); if (!dev_priv->gart_info.sg_be) return -ENOMEM; be = dev_priv->gart_info.sg_be; /* 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 = be->func->populate(be, dev->sg->pages, dev->sg->pagelist))) { DRM_ERROR("failed populate: %d\n", ret); return ret; } mm_node.start = 0; mem.mm_node = &mm_node; if ((ret = be->func->bind(be, &mem))) { 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; }