static void nv84_crypt_intr(struct nouveau_subdev *subdev) { struct nouveau_fifo *pfifo = nouveau_fifo(subdev); struct nouveau_engine *engine = nv_engine(subdev); struct nouveau_object *engctx; struct nv84_crypt_priv *priv = (void *)subdev; u32 stat = nv_rd32(priv, 0x102130); u32 mthd = nv_rd32(priv, 0x102190); u32 data = nv_rd32(priv, 0x102194); u32 inst = nv_rd32(priv, 0x102188) & 0x7fffffff; int chid; engctx = nouveau_engctx_get(engine, inst); chid = pfifo->chid(pfifo, engctx); if (stat) { nv_error(priv, ""); nouveau_bitfield_print(nv84_crypt_intr_mask, stat); printk(" ch %d [0x%010llx] mthd 0x%04x data 0x%08x\n", chid, (u64)inst << 12, mthd, data); } nv_wr32(priv, 0x102130, stat); nv_wr32(priv, 0x10200c, 0x10); nv50_fb_trap(nouveau_fb(priv), 1); nouveau_engctx_put(engctx); }
static int nv49_ram_create(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) { struct nouveau_fb *pfb = nouveau_fb(parent); struct nv40_ram *ram; u32 pfb914 = nv_rd32(pfb, 0x100914); int ret; ret = nouveau_ram_create(parent, engine, oclass, &ram); *pobject = nv_object(ram); if (ret) return ret; switch (pfb914 & 0x00000003) { case 0x00000000: ram->base.type = NV_MEM_TYPE_DDR1; break; case 0x00000001: ram->base.type = NV_MEM_TYPE_DDR2; break; case 0x00000002: ram->base.type = NV_MEM_TYPE_GDDR3; break; case 0x00000003: break; } ram->base.size = nv_rd32(pfb, 0x10020c) & 0xff000000; ram->base.parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1; ram->base.tags = nv_rd32(pfb, 0x100320); ram->base.calc = nv40_ram_calc; ram->base.prog = nv40_ram_prog; ram->base.tidy = nv40_ram_tidy; return 0; }
static int nvaa_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 datasize, struct nouveau_object **pobject) { const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ struct nouveau_fb *pfb = nouveau_fb(parent); struct nouveau_ram *ram; int ret; ret = nouveau_ram_create(parent, engine, oclass, &ram); *pobject = nv_object(ram); if (ret) return ret; ram->size = nv_rd32(pfb, 0x10020c); ram->size = (ram->size & 0xffffff00) | ((ram->size & 0x000000ff) << 32); ret = nouveau_mm_init(&pfb->vram, rsvd_head, (ram->size >> 12) - (rsvd_head + rsvd_tail), 1); if (ret) return ret; ram->type = NV_MEM_TYPE_STOLEN; ram->stolen = (u64)nv_rd32(pfb, 0x100e10) << 12; ram->get = nv50_ram_get; ram->put = nv50_ram_put; return 0; }
int nouveau_gem_ioctl_new(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_fb *pfb = nouveau_fb(drm->device); struct drm_nouveau_gem_new *req = data; struct nouveau_bo *nvbo = NULL; int ret = 0; drm->ttm.bdev.dev_mapping = drm->dev->dev_mapping; if (!pfb->memtype_valid(pfb, req->info.tile_flags)) { NV_ERROR(drm, "bad page flags: 0x%08x\n", req->info.tile_flags); return -EINVAL; } ret = nouveau_gem_new(dev, req->info.size, req->align, req->info.domain, req->info.tile_mode, req->info.tile_flags, &nvbo); if (ret) return ret; ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle); if (ret == 0) { ret = nouveau_gem_info(file_priv, nvbo->gem, &req->info); if (ret) drm_gem_handle_delete(file_priv, req->info.handle); } /* drop reference from allocate - handle holds it now */ drm_gem_object_unreference_unlocked(nvbo->gem); return ret; }
static int nv41_ram_create(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) { struct nouveau_fb *pfb = nouveau_fb(parent); struct nouveau_ram *ram; u32 pfb474 = nv_rd32(pfb, 0x100474); int ret; ret = nouveau_ram_create(parent, engine, oclass, &ram); *pobject = nv_object(ram); if (ret) return ret; if (pfb474 & 0x00000004) ram->type = NV_MEM_TYPE_GDDR3; if (pfb474 & 0x00000002) ram->type = NV_MEM_TYPE_DDR2; if (pfb474 & 0x00000001) ram->type = NV_MEM_TYPE_DDR1; ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000; ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1; ram->tags = nv_rd32(pfb, 0x100320); return 0; }
static int gm107_ltc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) { struct nouveau_fb *pfb = nouveau_fb(parent); struct nvkm_ltc_priv *priv; u32 parts, mask; int ret, i; ret = nvkm_ltc_create(parent, engine, oclass, &priv); *pobject = nv_object(priv); if (ret) return ret; parts = nv_rd32(priv, 0x022438); mask = nv_rd32(priv, 0x021c14); for (i = 0; i < parts; i++) { if (!(mask & (1 << i))) priv->ltc_nr++; } priv->lts_nr = nv_rd32(priv, 0x17e280) >> 28; ret = gf100_ltc_init_tag_ram(pfb, priv); if (ret) return ret; return 0; }
static int nv50_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) { struct nouveau_fb *pfb = nouveau_fb(parent); struct nv50_instobj_priv *node; u32 align = (unsigned long)data; int ret; size = max((size + 4095) & ~4095, (u32)4096); align = max((align + 4095) & ~4095, (u32)4096); ret = nouveau_instobj_create(parent, engine, oclass, &node); *pobject = nv_object(node); if (ret) return ret; ret = pfb->ram.get(pfb, size, align, 0, 0x800, &node->mem); if (ret) return ret; node->base.addr = node->mem->offset; node->base.size = node->mem->size << 12; node->mem->page_shift = 12; return 0; }
static int gf100_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) { struct gf100_ltcg_priv *priv; struct nouveau_fb *pfb = nouveau_fb(parent); u32 parts, mask; int ret, i; ret = nouveau_ltcg_create(parent, engine, oclass, &priv); *pobject = nv_object(priv); if (ret) return ret; parts = nv_rd32(priv, 0x022438); mask = nv_rd32(priv, 0x022554); for (i = 0; i < parts; i++) { if (!(mask & (1 << i))) priv->ltc_nr++; } priv->lts_nr = nv_rd32(priv, 0x17e8dc) >> 28; ret = gf100_ltcg_init_tag_ram(pfb, priv); if (ret) return ret; priv->base.tags_alloc = gf100_ltcg_tags_alloc; priv->base.tags_free = gf100_ltcg_tags_free; priv->base.tags_clear = gf100_ltcg_tags_clear; nv_subdev(priv)->intr = gf100_ltcg_intr; return 0; }
static void nv50_instobj_dtor(struct nouveau_object *object) { struct nv50_instobj_priv *node = (void *)object; struct nouveau_fb *pfb = nouveau_fb(object); pfb->ram.put(pfb, &node->mem); nouveau_instobj_destroy(&node->base); }
void gf100_ltc_dtor(struct nouveau_object *object) { struct nouveau_fb *pfb = nouveau_fb(object); struct nvkm_ltc_priv *priv = (void *)object; nouveau_mm_fini(&priv->tags); nouveau_mm_free(&pfb->vram, &priv->tag_ram); nvkm_ltc_destroy(priv); }
static void nvc0_ltcg_dtor(struct nouveau_object *object) { struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object; struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg; struct nouveau_fb *pfb = nouveau_fb(ltcg->base.base.parent); nouveau_mm_fini(&priv->tags); nouveau_mm_free(&pfb->vram, &priv->tag_ram); nouveau_ltcg_destroy(ltcg); }
static void nvc0_ram_train(struct nvc0_ramfuc *fuc, u32 magic) { struct nvc0_ram *ram = container_of(fuc, typeof(*ram), fuc); struct nouveau_fb *pfb = nouveau_fb(ram); u32 part = nv_rd32(pfb, 0x022438), i; u32 mask = nv_rd32(pfb, 0x022554); u32 addr = 0x110974; ram_wr32(fuc, 0x10f910, magic); ram_wr32(fuc, 0x10f914, magic); for (i = 0; (magic & 0x80000000) && i < part; addr += 0x1000, i++) { if (mask & (1 << i)) continue; ram_wait(fuc, addr, 0x0000000f, 0x00000000, 500000); } }
static int nv4e_ram_create(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) { struct nouveau_fb *pfb = nouveau_fb(parent); struct nouveau_ram *ram; int ret; ret = nouveau_ram_create(parent, engine, oclass, &ram); *pobject = nv_object(ram); if (ret) return ret; ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000; ram->type = NV_MEM_TYPE_STOLEN; return 0; }
static int nv04_ram_create(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) { struct nouveau_fb *pfb = nouveau_fb(parent); struct nouveau_ram *ram; u32 boot0 = nv_rd32(pfb, NV04_PFB_BOOT_0); int ret; ret = nouveau_ram_create(parent, engine, oclass, &ram); *pobject = nv_object(ram); if (ret) return ret; if (boot0 & 0x00000100) { ram->size = ((boot0 >> 12) & 0xf) * 2 + 2; ram->size *= 1024 * 1024; } else {
static void nve0_ram_nuts(struct nve0_ram *ram, struct ramfuc_reg *reg, u32 _mask, u32 _data, u32 _copy) { struct nve0_fb_priv *priv = (void *)nouveau_fb(ram); struct ramfuc *fuc = &ram->fuc.base; u32 addr = 0x110000 + (reg->addr[0] & 0xfff); u32 mask = _mask | _copy; u32 data = (_data & _mask) | (reg->data & _copy); u32 i; for (i = 0; i < 16; i++, addr += 0x1000) { if (ram->pnuts & (1 << i)) { u32 prev = nv_rd32(priv, addr); u32 next = (prev & ~mask) | data; nouveau_memx_wr32(fuc->memx, addr, next); } } }
static int nv10_ram_create(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_object **pobject) { struct nouveau_fb *pfb = nouveau_fb(parent); struct nouveau_ram *ram; u32 cfg0 = nv_rd32(pfb, 0x100200); int ret; ret = nouveau_ram_create(parent, engine, oclass, &ram); *pobject = nv_object(ram); if (ret) return ret; if (cfg0 & 0x00000001) ram->type = NV_MEM_TYPE_DDR1; else ram->type = NV_MEM_TYPE_SDRAM; ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000; return 0; }
int nv30_graph_init(struct nouveau_object *object) { struct nouveau_engine *engine = nv_engine(object); struct nv20_graph_priv *priv = (void *)engine; struct nouveau_fb *pfb = nouveau_fb(object); int ret, i; ret = nouveau_graph_init(&priv->base); if (ret) return ret; nv_wr32(priv, NV20_PGRAPH_CHANNEL_CTX_TABLE, priv->ctxtab->addr >> 4); nv_wr32(priv, NV03_PGRAPH_INTR , 0xFFFFFFFF); nv_wr32(priv, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x00000000); nv_wr32(priv, NV04_PGRAPH_DEBUG_1, 0x401287c0); nv_wr32(priv, 0x400890, 0x01b463ff); nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0xf2de0475); nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x00008000); nv_wr32(priv, NV04_PGRAPH_LIMIT_VIOL_PIX, 0xf04bdff6); nv_wr32(priv, 0x400B80, 0x1003d888); nv_wr32(priv, 0x400B84, 0x0c000000); nv_wr32(priv, 0x400098, 0x00000000); nv_wr32(priv, 0x40009C, 0x0005ad00); nv_wr32(priv, 0x400B88, 0x62ff00ff); /* suspiciously like PGRAPH_DEBUG_2 */ nv_wr32(priv, 0x4000a0, 0x00000000); nv_wr32(priv, 0x4000a4, 0x00000008); nv_wr32(priv, 0x4008a8, 0xb784a400); nv_wr32(priv, 0x400ba0, 0x002f8685); nv_wr32(priv, 0x400ba4, 0x00231f3f); nv_wr32(priv, 0x4008a4, 0x40000020); if (nv_device(priv)->chipset == 0x34) { nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0004); nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00200201); nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0008); nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00000008); nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00000032); nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00E00004); nv_wr32(priv, NV10_PGRAPH_RDI_DATA , 0x00000002); } nv_wr32(priv, 0x4000c0, 0x00000016); /* Turn all the tiling regions off. */ for (i = 0; i < pfb->tile.regions; i++) engine->tile_prog(engine, i); nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10000100); nv_wr32(priv, NV10_PGRAPH_STATE , 0xFFFFFFFF); nv_wr32(priv, 0x0040075c , 0x00000001); /* begin RAM config */ /* vramsz = pci_resource_len(priv->dev->pdev, 0) - 1; */ nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200)); nv_wr32(priv, 0x4009A8, nv_rd32(priv, 0x100204)); if (nv_device(priv)->chipset != 0x34) { nv_wr32(priv, 0x400750, 0x00EA0000); nv_wr32(priv, 0x400754, nv_rd32(priv, 0x100200)); nv_wr32(priv, 0x400750, 0x00EA0004); nv_wr32(priv, 0x400754, nv_rd32(priv, 0x100204)); } return 0; }
int nvkm_dmaobj_create_(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void **pdata, u32 *psize, int length, void **pobject) { union { struct nv_dma_v0 v0; } *args = *pdata; struct nouveau_instmem *instmem = nouveau_instmem(parent); struct nouveau_client *client = nouveau_client(parent); struct nouveau_device *device = nv_device(parent); struct nouveau_fb *pfb = nouveau_fb(parent); struct nouveau_dmaobj *dmaobj; void *data = *pdata; u32 size = *psize; int ret; ret = nouveau_object_create_(parent, engine, oclass, 0, length, pobject); dmaobj = *pobject; if (ret) return ret; nv_ioctl(parent, "create dma size %d\n", *psize); if (nvif_unpack(args->v0, 0, 0, true)) { nv_ioctl(parent, "create dma vers %d target %d access %d " "start %016llx limit %016llx\n", args->v0.version, args->v0.target, args->v0.access, args->v0.start, args->v0.limit); dmaobj->target = args->v0.target; dmaobj->access = args->v0.access; dmaobj->start = args->v0.start; dmaobj->limit = args->v0.limit; } else return ret; *pdata = data; *psize = size; if (dmaobj->start > dmaobj->limit) return -EINVAL; switch (dmaobj->target) { case NV_DMA_V0_TARGET_VM: dmaobj->target = NV_MEM_TARGET_VM; break; case NV_DMA_V0_TARGET_VRAM: if (!client->super) { if (dmaobj->limit >= pfb->ram->size - instmem->reserved) return -EACCES; if (device->card_type >= NV_50) return -EACCES; } dmaobj->target = NV_MEM_TARGET_VRAM; break; case NV_DMA_V0_TARGET_PCI: if (!client->super) return -EACCES; dmaobj->target = NV_MEM_TARGET_PCI; break; case NV_DMA_V0_TARGET_PCI_US: case NV_DMA_V0_TARGET_AGP: if (!client->super) return -EACCES; dmaobj->target = NV_MEM_TARGET_PCI_NOSNOOP; break; default: return -EINVAL; } switch (dmaobj->access) { case NV_DMA_V0_ACCESS_VM: dmaobj->access = NV_MEM_ACCESS_VM; break; case NV_DMA_V0_ACCESS_RD: dmaobj->access = NV_MEM_ACCESS_RO; break; case NV_DMA_V0_ACCESS_WR: dmaobj->access = NV_MEM_ACCESS_WO; break; case NV_DMA_V0_ACCESS_RDWR: dmaobj->access = NV_MEM_ACCESS_RW; break; default: return -EINVAL; } return ret; }