2 Copyright � 1995-2008, The AROS Development Team. All rights reserved.
5 Desc: vmware svga hardware functions
9 #define DEBUG 1 /* no SysBase */
10 #include <aros/debug.h>
15 #include <exec/ports.h>
16 #include <devices/timer.h>
17 #include <proto/exec.h>
19 #include "vmwaresvgahardware.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
);
36 extern struct ExecBase
*SysBase
;
38 ULONG
getVMWareSVGAID(struct HWData
*data
)
42 vmwareWriteReg(data
, SVGA_REG_ID
, SVGA_ID_2
);
43 id
= vmwareReadReg(data
, SVGA_REG_ID
);
46 vmwareWriteReg(data
, SVGA_REG_ID
, SVGA_ID_1
);
47 id
= vmwareReadReg(data
, SVGA_REG_ID
);
52 return SVGA_ID_INVALID
;
55 VOID
initVMWareSVGAFIFO(struct HWData
*data
)
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
);
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
)
89 fifo
= data
->mmiobase
;
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
)
110 id
= getVMWareSVGAID(data
);
111 if ((id
== SVGA_ID_0
) || (id
== SVGA_ID_INVALID
))
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;
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
);
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
);
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
)
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
243 ULONG
*image
= mouse
->shape
;
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
255 for (i
= 0; i
< size
; i
++)
257 ULONG pixel
= *image
++;
263 for (i
= 0; i
< size
; i
++)
265 writeVMWareSVGAFIFO(data
, *xorBuffer
++);
268 syncVMWareSVGAFIFO(data
);
271 VOID
displayCursorVMWareSVGA(struct HWData
*data
, LONG mode
)
274 writeVMWareSVGAFIFO(data
, SVGA_CMD_DISPLAY_CURSOR
);
275 writeVMWareSVGAFIFO(data
, 1);
276 writeVMWareSVGAFIFO(data
, mode
);
277 syncVMWareSVGAFIFO(data
);
279 vmwareWriteReg(data
, SVGA_REG_CURSOR_ID
, 1);
280 vmwareWriteReg(data
, SVGA_REG_CURSOR_ON
, mode
);
284 VOID
moveCursorVMWareSVGA(struct HWData
*data
, LONG x
, LONG y
)
287 writeVMWareSVGAFIFO(data
, SVGA_CMD_MOVE_CURSOR
);
288 writeVMWareSVGAFIFO(data
, x
);
289 writeVMWareSVGAFIFO(data
, y
);
290 syncVMWareSVGAFIFO(data
);
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);
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
);
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
);
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",
404 TASKTAG_ARG1
, hwdata
,