summaryrefslogtreecommitdiff
path: root/fifo.c
blob: f21d07d4a770e93415faf43476e274e238c41bb0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/* FIFO setup */

#include <stdio.h>
#include <stdint.h>
#include <xf86drm.h>
#include <nouveau_drm.h>

#include "screen.h"
#include "object.h"

#define DEBUG 0

/* Global variables */

struct drm_nouveau_channel_alloc init;

/* Local variables */

static uint32_t *fifo = NULL;
static uint32_t *fifo_regs = NULL;
static uint32_t *notifier_block = NULL;

static uint32_t fifo_current, fifo_free;

/* Functions */

int fifo_open(void)
{
	int ret;

	init.fb_ctxdma_handle = NvDmaFB;
	init.tt_ctxdma_handle = NvDmaTT;
	ret = drmCommandWriteRead(drm_fd, DRM_NOUVEAU_CHANNEL_ALLOC, &init, sizeof(init));
	if (ret) {
		fprintf(stderr,"Failed to create GPU channel: %d\n", ret);
		return 1;
	}

	printf("Fifo %d: cb_handle=0x%08x, cb_size=0x%08x\n",
		init.channel, init.cmdbuf, init.cmdbuf_size);

	ret = drmMap(drm_fd, init.cmdbuf, init.cmdbuf_size, (void*)&fifo);
	if (ret) {
		fprintf(stderr, "Mapping DMA push buffer returned %d\n", ret);
		return 1;
	}

	ret = drmMap(drm_fd, init.ctrl, init.ctrl_size, (void*)&fifo_regs);
	if (ret) {
		fprintf(stderr, "Mapping FIFO regs returned %d\n", ret);
		return 1;
	}

	ret = drmMap(drm_fd, init.notifier, init.notifier_size, (void*)&notifier_block);
	if (ret) {
		fprintf(stderr, "Mapping notifier block returned %d\n", ret);
		return 1;
	}

	printf("FIFO:\t%p (0x%08x)\n", fifo, init.cmdbuf);
	printf("FIFO regs:\t%p (0x%08x)\n", fifo_regs, init.ctrl);
	printf("Notifiers:\t%p (0x%08x)\n", notifier_block, init.notifier);
	printf("PUT base:\t0x%08x\n", init.put_base);

	fifo_current = 0;
	fifo_free    = (init.cmdbuf_size>>2) - 1;
	printf("FIFO current:\t0x%x free=0x%x\n", fifo_current, fifo_free);
	return 0;
}

void fifo_print_getput(void)
{
	printf("FIFO put=0x%08x, get=0x%08x, current=0x%08x\n",
			fifo_regs[0x40/4],
			fifo_regs[0x44/4],
			fifo_current
			);
}

void OUT_RING(uint32_t data)
{
#if DEBUG
	printf("out_ring(0x%08x)\n", data);
#else
	fifo[fifo_current++] = data;
#endif
}

void OUT_RINGf(float data)
{
#if DEBUG
	printf("out_ringf(0x%08x)= %.f\n", data, data);
#else
	fifo[fifo_current++] = data;
#endif
}

void FIRE_RING(void)
{
#if DEBUG
	printf("fire_ring()\n");
#else
	fifo_regs[0x40/4] = (fifo_current<<2) + init.put_base;
#endif
}

void BEGIN_RING(int subchannel, int method, int size)
{
	size &= (1<<11)-1;
	subchannel &= (1<<3)-1;
	method &= 0x40001ffc;
	if (fifo_free<=size) {
		fprintf(stderr,"FIFO full\n");
		return;
	}
	OUT_RING(method|(size<<18)|(subchannel<<13));
	fifo_free -= size;
}

void SetSubchannel(int subchannel, int obj)
{
	BEGIN_RING(subchannel, 0, 1);
	OUT_RING(obj);
}