Пример #1
0
static int
nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
		    u32 handle, u32 engine, struct nouveau_channel **pchan)
{
	static const u16 oclasses[] = { KEPLER_CHANNEL_GPFIFO_A,
					FERMI_CHANNEL_GPFIFO,
					G82_CHANNEL_GPFIFO,
					NV50_CHANNEL_GPFIFO,
					0 };
	const u16 *oclass = oclasses;
	union {
		struct nv50_channel_gpfifo_v0 nv50;
		struct kepler_channel_gpfifo_a_v0 kepler;
	} args, *retn;
	struct nouveau_channel *chan;
	u32 size;
	int ret;

	/* allocate dma push buffer */
	ret = nouveau_channel_prep(drm, device, handle, 0x12000, &chan);
	*pchan = chan;
	if (ret)
		return ret;

	/* create channel object */
	do {
		if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) {
			args.kepler.version = 0;
			args.kepler.engine  = engine;
			args.kepler.pushbuf = chan->push.ctxdma.handle;
			args.kepler.ilength = 0x02000;
			args.kepler.ioffset = 0x10000 + chan->push.vma.offset;
			size = sizeof(args.kepler);
		} else {
			args.nv50.version = 0;
			args.nv50.pushbuf = chan->push.ctxdma.handle;
			args.nv50.ilength = 0x02000;
			args.nv50.ioffset = 0x10000 + chan->push.vma.offset;
			size = sizeof(args.nv50);
		}

		ret = nvif_object_new(nvif_object(device), handle, *oclass++,
				      &args, size, &chan->object);
		if (ret == 0) {
			retn = chan->object->data;
			if (chan->object->oclass >= KEPLER_CHANNEL_GPFIFO_A)
				chan->chid = retn->kepler.chid;
			else
				chan->chid = retn->nv50.chid;
			return ret;
		}
	} while (*oclass);

	nouveau_channel_del(pchan);
	return ret;
}
Пример #2
0
static int
nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device,
		    u32 handle, struct nouveau_channel **pchan)
{
	static const u16 oclasses[] = { NV40_CHANNEL_DMA,
					NV17_CHANNEL_DMA,
					NV10_CHANNEL_DMA,
					NV03_CHANNEL_DMA,
					0 };
	const u16 *oclass = oclasses;
	struct nv03_channel_dma_v0 args, *retn;
	struct nouveau_channel *chan;
	int ret;

	/* allocate dma push buffer */
	ret = nouveau_channel_prep(drm, device, handle, 0x10000, &chan);
	*pchan = chan;
	if (ret)
		return ret;

	/* create channel object */
	args.version = 0;
	args.pushbuf = chan->push.ctxdma.handle;
	args.offset = chan->push.vma.offset;

	do {
		ret = nvif_object_new(nvif_object(device), handle, *oclass++,
				      &args, sizeof(args), &chan->object);
		if (ret == 0) {
			retn = chan->object->data;
			chan->chid = retn->chid;
			return ret;
		}
	} while (ret && *oclass);

	nouveau_channel_del(pchan);
	return ret;
}
Пример #3
0
static int
nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
		    u32 engine, struct nouveau_channel **pchan)
{
	static const u16 oclasses[] = { MAXWELL_CHANNEL_GPFIFO_A,
					KEPLER_CHANNEL_GPFIFO_B,
					KEPLER_CHANNEL_GPFIFO_A,
					FERMI_CHANNEL_GPFIFO,
					G82_CHANNEL_GPFIFO,
					NV50_CHANNEL_GPFIFO,
					0 };
	const u16 *oclass = oclasses;
	union {
		struct nv50_channel_gpfifo_v0 nv50;
		struct fermi_channel_gpfifo_v0 fermi;
		struct kepler_channel_gpfifo_a_v0 kepler;
	} args;
	struct nouveau_channel *chan;
	u32 size;
	int ret;

	/* allocate dma push buffer */
	ret = nouveau_channel_prep(drm, device, 0x12000, &chan);
	*pchan = chan;
	if (ret)
		return ret;

	/* create channel object */
	do {
		if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) {
			args.kepler.version = 0;
			args.kepler.engines = engine;
			args.kepler.ilength = 0x02000;
			args.kepler.ioffset = 0x10000 + chan->push.vma.offset;
			args.kepler.vm = 0;
			size = sizeof(args.kepler);
		} else
		if (oclass[0] >= FERMI_CHANNEL_GPFIFO) {
			args.fermi.version = 0;
			args.fermi.ilength = 0x02000;
			args.fermi.ioffset = 0x10000 + chan->push.vma.offset;
			args.fermi.vm = 0;
			size = sizeof(args.fermi);
		} else {
			args.nv50.version = 0;
			args.nv50.ilength = 0x02000;
			args.nv50.ioffset = 0x10000 + chan->push.vma.offset;
			args.nv50.pushbuf = nvif_handle(&chan->push.ctxdma);
			args.nv50.vm = 0;
			size = sizeof(args.nv50);
		}

		ret = nvif_object_init(&device->object, 0, *oclass++,
				       &args, size, &chan->user);
		if (ret == 0) {
			if (chan->user.oclass >= KEPLER_CHANNEL_GPFIFO_A)
				chan->chid = args.kepler.chid;
			else
			if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO)
				chan->chid = args.fermi.chid;
			else
				chan->chid = args.nv50.chid;
			return ret;
		}
	} while (*oclass);

	nouveau_channel_del(pchan);
	return ret;
}