1/*
2 * Copyright 1999, Be Incorporated.
3 * Copyright 2007, Haiku.
4 * Distributed under the terms of the MIT License.
5 *
6 * Authors:
7 *		Be Incorporated
8 *		Eric Petit <eric.petit@lapsus.org>
9 */
10
11
12#include "GlobalData.h"
13
14
15/*--------------------------------------------------------------------*/
16/* UpdateThread: we explicitely need to tell VMware what and when
17 * something should be refreshed from the frame buffer. Since the
18 * app_server doesn't tell us what it's doing, we simply force a full
19 * screen update every 1/50 second */
20
21static int32
22UpdateThread(void *data)
23{
24	bigtime_t begin, end, wait;
25
26	while (!gUpdateThreadDie) {
27		begin = system_time();
28		FifoUpdateFullscreen();
29		end = system_time();
30
31		/* 50 Hz refresh */
32		wait = 20000 - (end - begin);
33		if (wait > 0)
34			snooze(wait);
35	}
36
37	return B_OK;
38}
39
40
41static void
42FifoPrintCapabilities(int c)
43{
44	TRACE("fifo capabilities:\n");
45	if (c & SVGA_FIFO_CAP_FENCE)		TRACE("FENCE\n");
46	if (c & SVGA_FIFO_CAP_ACCELFRONT)	TRACE("ACCELFRONT\n");
47	if (c & SVGA_FIFO_CAP_PITCHLOCK)	TRACE("PITCHLOCK\n");
48}
49
50
51void
52FifoInit(void)
53{
54	uint32 *fifo = gSi->fifo;
55
56	/* Stop update thread, if any */
57	if (gUpdateThread > B_OK) {
58		status_t exitValue;
59		gUpdateThreadDie = 1;
60		wait_for_thread(gUpdateThread, &exitValue);
61	}
62
63	gSi->fifoCapabilities = 0;
64	gSi->fifoFlags = 0;
65	if (gSi->capabilities & SVGA_CAP_EXTENDED_FIFO) {
66		gSi->fifoCapabilities = fifo[SVGA_FIFO_CAPABILITIES];
67		gSi->fifoFlags = fifo[SVGA_FIFO_FLAGS];
68		FifoPrintCapabilities(gSi->fifoCapabilities);
69	}
70
71	fifo[SVGA_FIFO_MIN]		 = gSi->fifoMin * 4;
72	fifo[SVGA_FIFO_MAX]		 = gSi->fifoSize;
73	fifo[SVGA_FIFO_NEXT_CMD] = fifo[SVGA_FIFO_MIN];
74	fifo[SVGA_FIFO_STOP]	 = fifo[SVGA_FIFO_MIN];
75
76	gSi->fifoNext = fifo[SVGA_FIFO_NEXT_CMD];
77
78	/* Launch a new update thread */
79	gUpdateThreadDie = 0;
80	gUpdateThread = spawn_thread(UpdateThread, "VMware",
81		B_REAL_TIME_DISPLAY_PRIORITY, NULL);
82	resume_thread(gUpdateThread);
83
84	TRACE("init fifo: %ld -> %ld\n",
85		fifo[SVGA_FIFO_MIN], fifo[SVGA_FIFO_MAX]);
86}
87
88
89void
90FifoSync(void)
91{
92	ioctl(gFd, VMWARE_FIFO_SYNC, NULL, 0);
93}
94
95
96void
97FifoBeginWrite(void)
98{
99	ACQUIRE_BEN(gSi->fifoLock);
100}
101
102
103void
104FifoWrite(uint32 value)
105{
106	uint32 *fifo = gSi->fifo;
107	uint32 fifoCapacity = fifo[SVGA_FIFO_MAX] - fifo[SVGA_FIFO_MIN];
108
109	/* If the fifo is full, sync it */
110	if (fifo[SVGA_FIFO_STOP] == fifo[SVGA_FIFO_NEXT_CMD] + 4 ||
111		fifo[SVGA_FIFO_STOP] + fifoCapacity == fifo[SVGA_FIFO_NEXT_CMD] + 4)
112		FifoSync();
113
114	fifo[gSi->fifoNext / 4] = value;
115	gSi->fifoNext = fifo[SVGA_FIFO_MIN] +
116		(gSi->fifoNext + 4 - fifo[SVGA_FIFO_MIN]) % fifoCapacity;
117}
118
119
120void
121FifoEndWrite(void)
122{
123	uint32 *fifo = gSi->fifo;
124
125	fifo[SVGA_FIFO_NEXT_CMD] = gSi->fifoNext;
126	RELEASE_BEN(gSi->fifoLock);
127}
128
129
130void
131FifoUpdateFullscreen(void)
132{
133	FifoBeginWrite();
134	FifoWrite(SVGA_CMD_UPDATE);
135	FifoWrite(0);
136	FifoWrite(0);
137	FifoWrite(gSi->dm.virtual_width);
138	FifoWrite(gSi->dm.virtual_height);
139	FifoEndWrite();
140}
141
142