revert between 56095 -> 55830 in arch
[AROS.git] / workbench / hidds / vmwaresvga / vmwaresvgahardware.c
blobe333c40d13064ceb65895d3ba0c64c1a030a5a2b
1 /*
2 Copyright � 1995-2008, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: vmware svga hardware functions
6 Lang: English
7 */
9 #define DEBUG 1 /* no SysBase */
10 #include <aros/debug.h>
12 #include <asm/io.h>
14 #include <limits.h>
15 #include <exec/ports.h>
16 #include <devices/timer.h>
17 #include <proto/exec.h>
19 #include "vmwaresvgahardware.h"
20 #include "svga_reg.h"
21 #include "vmwaresvgaclass.h"
23 ULONG vmwareReadReg(struct HWData *data, ULONG reg)
25 outl(reg, data->indexReg);
26 return inl(data->valueReg);
29 void vmwareWriteReg(struct HWData *data, ULONG reg, ULONG val)
31 outl(reg, data->indexReg);
32 outl(val, data->valueReg);
35 #undef SysBase
36 extern struct ExecBase *SysBase;
38 ULONG getVMWareSVGAID(struct HWData *data)
40 ULONG id;
42 vmwareWriteReg(data, SVGA_REG_ID, SVGA_ID_2);
43 id = vmwareReadReg(data, SVGA_REG_ID);
44 if (id == SVGA_ID_2)
45 return id;
46 vmwareWriteReg(data, SVGA_REG_ID, SVGA_ID_1);
47 id = vmwareReadReg(data, SVGA_REG_ID);
48 if (id == SVGA_ID_1)
49 return id;
50 if (id == SVGA_ID_0)
51 return id;
52 return SVGA_ID_INVALID;
55 VOID initVMWareSVGAFIFO(struct HWData *data)
57 ULONG *fifo;
58 ULONG fifomin;
60 vmwareWriteReg(data, SVGA_REG_CONFIG_DONE, 0); //Stop vmware from reading the fifo
62 fifo = data->mmiobase = (APTR)(IPTR)vmwareReadReg(data, SVGA_REG_MEM_START);
63 data->mmiosize = vmwareReadReg(data, SVGA_REG_MEM_SIZE) & ~3;
65 if (data->capabilities & SVGA_CAP_EXTENDED_FIFO)
66 fifomin = vmwareReadReg(data, SVGA_REG_MEM_REGS);
67 else
68 fifomin =4;
70 fifo[SVGA_FIFO_MIN] = fifomin * sizeof(ULONG);
72 /* reduce size of FIFO queue to prevent VMWare from failing */
73 fifo[SVGA_FIFO_MAX] = (data->mmiosize > 65536) ? 65536 : data->mmiosize;
74 fifo[SVGA_FIFO_NEXT_CMD] = fifomin * sizeof(ULONG);
75 fifo[SVGA_FIFO_STOP] = fifomin * sizeof(ULONG);
77 vmwareWriteReg(data, SVGA_REG_CONFIG_DONE, 1);
80 VOID syncVMWareSVGAFIFO(struct HWData *data)
82 vmwareWriteReg(data, SVGA_REG_SYNC, 1);
85 VOID writeVMWareSVGAFIFO(struct HWData *data, ULONG val)
87 ULONG *fifo;
89 fifo = data->mmiobase;
90 if (
91 (fifo[SVGA_FIFO_NEXT_CMD]+4 == fifo[SVGA_FIFO_STOP]) ||
93 (fifo[SVGA_FIFO_NEXT_CMD] == (fifo[SVGA_FIFO_MAX]-4)) &&
94 (fifo[SVGA_FIFO_STOP] == fifo[SVGA_FIFO_MIN])
97 syncVMWareSVGAFIFO(data);
99 fifo[fifo[SVGA_FIFO_NEXT_CMD] / 4] = val;
100 fifo[SVGA_FIFO_NEXT_CMD] += 4;
102 if (fifo[SVGA_FIFO_NEXT_CMD] == fifo[SVGA_FIFO_MAX])
103 fifo[SVGA_FIFO_NEXT_CMD] = fifo[SVGA_FIFO_MIN];
106 BOOL initVMWareSVGAHW(struct HWData *data, OOP_Object *device)
108 ULONG id;
110 id = getVMWareSVGAID(data);
111 if ((id == SVGA_ID_0) || (id == SVGA_ID_INVALID))
113 return FALSE;
116 initVMWareSVGAFIFO(data);
118 data->capabilities = vmwareReadReg(data, SVGA_REG_CAPABILITIES);
120 if (data->capabilities & SVGA_CAP_8BIT_EMULATION)
122 data->bitsperpixel = vmwareReadReg(data, SVGA_REG_HOST_BITS_PER_PIXEL);
123 vmwareWriteReg(data,SVGA_REG_BITS_PER_PIXEL, data->bitsperpixel);
125 data->bitsperpixel = vmwareReadReg(data, SVGA_REG_BITS_PER_PIXEL);
127 data->depth = vmwareReadReg(data, SVGA_REG_DEPTH);
128 data->maxwidth = vmwareReadReg(data, SVGA_REG_MAX_WIDTH);
129 data->maxheight = vmwareReadReg(data, SVGA_REG_MAX_HEIGHT);
130 data->redmask = vmwareReadReg(data, SVGA_REG_RED_MASK);
131 data->greenmask = vmwareReadReg(data, SVGA_REG_GREEN_MASK);
132 data->bluemask = vmwareReadReg(data, SVGA_REG_BLUE_MASK);
133 data->bytesperpixel = 1;
135 if (data->depth>16)
136 data->bytesperpixel = 4;
137 else if (data->depth>8)
138 data->bytesperpixel = 2;
140 if (data->capabilities & SVGA_CAP_MULTIMON)
142 data->displaycount = vmwareReadReg(data, SVGA_REG_NUM_DISPLAYS);
144 else
146 data->displaycount = 1;
149 data->vramsize = vmwareReadReg(data, SVGA_REG_VRAM_SIZE);
150 data->vrambase = (APTR)(IPTR)vmwareReadReg(data, SVGA_REG_FB_START);
151 data->pseudocolor = vmwareReadReg(data, SVGA_REG_PSEUDOCOLOR);
153 D(bug("[VMWareSVGA] Init: VRAM at 0x%08x size %d\n",data->vrambase, data->vramsize));
154 D(bug("[VMWareSVGA] Init: no.displays: %d\n",data->displaycount));
155 D(bug("[VMWareSVGA] Init: caps : 0x%08x\n",data->capabilities));
156 D(bug("[VMWareSVGA] Init: no.displays: %d\n",data->displaycount));
157 D(bug("[VMWareSVGA] Init: depth: %d\n",data->depth));
158 D(bug("[VMWareSVGA] Init: bpp : %d\n",data->bitsperpixel));
159 D(bug("[VMWareSVGA] Init: maxw: %d\n",data->maxwidth));
160 D(bug("[VMWareSVGA] Init: maxh: %d\n",data->maxheight));
162 VMWareSVGA_RestartRenderTask(data);
164 return TRUE;
167 VOID setModeVMWareSVGA(struct HWData *data, ULONG width, ULONG height)
169 D(bug("[VMWareSVGA] SetMode: %dx%d\n",width,height));
170 vmwareWriteReg(data, SVGA_REG_ENABLE, 0);
172 vmwareWriteReg(data, SVGA_REG_WIDTH, width);
173 vmwareWriteReg(data, SVGA_REG_HEIGHT, height);
175 if (data->capabilities & SVGA_CAP_8BIT_EMULATION)
176 vmwareWriteReg(data, SVGA_REG_BITS_PER_PIXEL,data->bitsperpixel);
178 vmwareWriteReg(data, SVGA_REG_ENABLE, 1);
180 data->fboffset = vmwareReadReg(data, SVGA_REG_FB_OFFSET);
181 data->bytesperline = vmwareReadReg(data, SVGA_REG_BYTES_PER_LINE);
182 data->depth = vmwareReadReg(data, SVGA_REG_DEPTH);
183 data->redmask = vmwareReadReg(data, SVGA_REG_RED_MASK);
184 data->greenmask = vmwareReadReg(data, SVGA_REG_GREEN_MASK);
185 data->bluemask = vmwareReadReg(data, SVGA_REG_BLUE_MASK);
186 data->pseudocolor = vmwareReadReg(data, SVGA_REG_PSEUDOCOLOR);
188 data->display_width = vmwareReadReg(data, SVGA_REG_WIDTH);
189 data->display_height = vmwareReadReg(data, SVGA_REG_HEIGHT);
192 VOID refreshAreaVMWareSVGA(struct HWData *data, struct Box *box)
194 writeVMWareSVGAFIFO(data, SVGA_CMD_UPDATE);
195 writeVMWareSVGAFIFO(data, box->x1);
196 writeVMWareSVGAFIFO(data, box->y1);
197 writeVMWareSVGAFIFO(data, box->x2-box->x1+1);
198 writeVMWareSVGAFIFO(data, box->y2-box->y1+1);
201 VOID rectFillVMWareSVGA(struct HWData *data, ULONG color, LONG x, LONG y, LONG width, LONG height)
203 writeVMWareSVGAFIFO(data, SVGA_CMD_RECT_FILL);
204 writeVMWareSVGAFIFO(data, color);
205 writeVMWareSVGAFIFO(data, x);
206 writeVMWareSVGAFIFO(data, y);
207 writeVMWareSVGAFIFO(data, width);
208 writeVMWareSVGAFIFO(data, height);
209 syncVMWareSVGAFIFO(data);
212 VOID ropFillVMWareSVGA(struct HWData *data, ULONG color, LONG x, LONG y, LONG width, LONG height, ULONG mode)
214 writeVMWareSVGAFIFO(data, SVGA_CMD_RECT_ROP_FILL);
215 writeVMWareSVGAFIFO(data, color);
216 writeVMWareSVGAFIFO(data, x);
217 writeVMWareSVGAFIFO(data, y);
218 writeVMWareSVGAFIFO(data, width);
219 writeVMWareSVGAFIFO(data, height);
220 writeVMWareSVGAFIFO(data, mode);
221 syncVMWareSVGAFIFO(data);
224 VOID ropCopyVMWareSVGA(struct HWData *data, LONG sx, LONG sy, LONG dx, LONG dy, ULONG width, ULONG height, ULONG mode)
226 writeVMWareSVGAFIFO(data, SVGA_CMD_RECT_ROP_COPY);
227 writeVMWareSVGAFIFO(data, sx);
228 writeVMWareSVGAFIFO(data, sy);
229 writeVMWareSVGAFIFO(data, dx);
230 writeVMWareSVGAFIFO(data, dy);
231 writeVMWareSVGAFIFO(data, width);
232 writeVMWareSVGAFIFO(data, height);
233 writeVMWareSVGAFIFO(data, mode);
234 syncVMWareSVGAFIFO(data);
237 VOID defineCursorVMWareSVGA(struct HWData *data, struct MouseData *mouse)
239 int i;
240 ULONG size = mouse->width * mouse->height;
241 // TODO: This is utterly disgusting. Should be moved to either a proper static data area, or dynamic area down to the render task
242 ULONG xorMask[size];
243 ULONG *image = mouse->shape;
244 ULONG *xorBuffer;
246 writeVMWareSVGAFIFO(data, SVGA_CMD_DEFINE_ALPHA_CURSOR);
247 writeVMWareSVGAFIFO(data, 0); // id
248 writeVMWareSVGAFIFO(data, 0); // hotspot x
249 writeVMWareSVGAFIFO(data, 0); // hotspot y
250 writeVMWareSVGAFIFO(data, mouse->width); // width
251 writeVMWareSVGAFIFO(data, mouse->height); // height
253 xorBuffer = xorMask;
255 for (i = 0; i < size; i++)
257 ULONG pixel = *image ++;
258 *xorBuffer = pixel;
259 xorBuffer++;
262 xorBuffer = xorMask;
263 for (i = 0; i < size; i++)
265 writeVMWareSVGAFIFO(data, *xorBuffer++);
268 syncVMWareSVGAFIFO(data);
271 VOID displayCursorVMWareSVGA(struct HWData *data, LONG mode)
273 #if 0
274 writeVMWareSVGAFIFO(data, SVGA_CMD_DISPLAY_CURSOR);
275 writeVMWareSVGAFIFO(data, 1);
276 writeVMWareSVGAFIFO(data, mode);
277 syncVMWareSVGAFIFO(data);
278 #else
279 vmwareWriteReg(data, SVGA_REG_CURSOR_ID, 1);
280 vmwareWriteReg(data, SVGA_REG_CURSOR_ON, mode);
281 #endif
284 VOID moveCursorVMWareSVGA(struct HWData *data, LONG x, LONG y)
286 #if 0
287 writeVMWareSVGAFIFO(data, SVGA_CMD_MOVE_CURSOR);
288 writeVMWareSVGAFIFO(data, x);
289 writeVMWareSVGAFIFO(data, y);
290 syncVMWareSVGAFIFO(data);
291 #else
292 vmwareWriteReg(data, SVGA_REG_CURSOR_ID, 1);
293 vmwareWriteReg(data, SVGA_REG_CURSOR_X, x);
294 vmwareWriteReg(data, SVGA_REG_CURSOR_Y, y);
295 vmwareWriteReg(data, SVGA_REG_CURSOR_ON, 1);
296 #endif
299 VOID VMWareSVGA_Damage_Reset(struct HWData *hwdata)
301 ObtainSemaphore(&hwdata->damage_control);
303 hwdata->delta_damage.x1 = INT_MAX;
304 hwdata->delta_damage.y1 = INT_MAX;
305 hwdata->delta_damage.x2 = INT_MIN;
306 hwdata->delta_damage.y2 = INT_MIN;
308 ReleaseSemaphore(&hwdata->damage_control);
311 VOID VMWareSVGA_Damage_DeltaAdd(struct HWData *hwdata, struct Box box)
313 ObtainSemaphore(&hwdata->damage_control);
315 if (box.x1 < hwdata->delta_damage.x1)
317 hwdata->delta_damage.x1 = box.x1;
319 if (box.y1 < hwdata->delta_damage.y1)
321 hwdata->delta_damage.y1 = box.y1;
323 if (box.x2 > hwdata->delta_damage.x2)
325 hwdata->delta_damage.x2 = box.x2;
327 if (box.y2 > hwdata->delta_damage.y2)
329 hwdata->delta_damage.y2 = box.y2;
331 ReleaseSemaphore(&hwdata->damage_control);
334 void VMWareSVGA_RenderTask(struct HWData *hwdata)
336 struct MsgPort render_thread_message_port;
337 struct timerequest *timer_request;
338 struct IORequest *timer_request_as_io_request;
339 ULONG request_size = sizeof(struct timerequest);
340 BYTE running;
342 render_thread_message_port.mp_Flags = PA_SIGNAL;
343 render_thread_message_port.mp_Node.ln_Type = NT_MSGPORT;
344 render_thread_message_port.mp_MsgList.lh_TailPred = (struct Node *)&render_thread_message_port.mp_MsgList;
345 render_thread_message_port.mp_MsgList.lh_Tail = 0;
346 render_thread_message_port.mp_MsgList.lh_Head = (struct Node *)&render_thread_message_port.mp_MsgList.lh_Tail;
348 render_thread_message_port.mp_SigBit = AllocSignal(-1);
349 render_thread_message_port.mp_SigTask = FindTask(0);
351 timer_request = AllocMem(request_size, MEMF_CLEAR | MEMF_PUBLIC);
352 timer_request_as_io_request = (void *)timer_request;
354 timer_request_as_io_request->io_Message.mn_Node.ln_Type = NT_MESSAGE;
355 timer_request_as_io_request->io_Message.mn_ReplyPort = &render_thread_message_port;
356 timer_request_as_io_request->io_Message.mn_Length = request_size;
358 OpenDevice("timer.device", UNIT_MICROHZ, timer_request_as_io_request, 0);
360 timer_request->tr_node.io_Command = TR_ADDREQUEST;
361 timer_request->tr_time.tv_secs = 0;
362 timer_request->tr_time.tv_micro = 20000;
363 SendIO(timer_request_as_io_request);
365 running = 1;
366 while (running) // TODO: If you'll ever implement GFX Driver hot swap, you will want to unlock this condition and let the RenderTask terminate
368 if (!vmwareReadReg(hwdata, SVGA_REG_BUSY))
370 ObtainSemaphore(&hwdata->damage_control);
371 struct Box damage = hwdata->delta_damage;
372 struct Box all_damage = {0, 0, hwdata->display_width, hwdata->display_height};
374 if (damage.x2 > damage.x1 && damage.y2 > damage.y1)
376 refreshAreaVMWareSVGA(hwdata, &all_damage);
377 VMWareSVGA_Damage_Reset(hwdata);
378 vmwareWriteReg(hwdata, SVGA_REG_SYNC, 1);
380 ReleaseSemaphore(&hwdata->damage_control);
383 WaitIO(timer_request_as_io_request);
384 GetMsg(&render_thread_message_port); // TODO: Did we have to reply to this? Oh memory ...
386 timer_request->tr_node.io_Command = TR_ADDREQUEST;
387 timer_request->tr_time.tv_secs = 0;
388 timer_request->tr_time.tv_micro = 20000; // TODO: This should be adaptive. We would need to know the CPU load and increase the delay to avoid burning all of the CPU time
389 SendIO(timer_request_as_io_request);
392 CloseDevice(timer_request_as_io_request);
395 VOID VMWareSVGA_RestartRenderTask(struct HWData *hwdata)
397 // TODO: CleanUp and add defenses here
399 InitSemaphore(&hwdata->damage_control);
401 hwdata->render_task = NewCreateTask(TASKTAG_PC, VMWareSVGA_RenderTask,
402 TASKTAG_NAME, "VMWare Render Task",
403 TASKTAG_PRI, 1,
404 TASKTAG_ARG1, hwdata,
405 TAG_DONE);