2 * UDI Bochs Graphics Driver
3 * By John Hodge (thePowersGang)
8 #define UDI_VERSION 0x101
9 #define UDI_PHYSIO_VERSION 0x101
10 #define UDI_GFX_VERSION 0x101
11 #define UDI_PCI_VERSION 0x101
13 #include <udi_physio.h>
16 #define DEBUG_ENABLED 1
17 #include "../helpers.h"
18 #include "../helpers_gfx.h"
19 #include "bochsga_common.h"
21 /* --- Management Metalang -- */
22 void bochsga_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level)
24 //rdata_t *rdata = UDI_GCB(cb)->context;
25 /*udi_trace_write(rdata->init_context, UDI_TREVENT_LOCAL_PROC_ENTRY, 0, );*/
27 /* TODO: Set up region data */
32 void bochsga_enumerate_req(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level)
34 //rdata_t *rdata = UDI_GCB(cb)->context;
35 udi_instance_attr_list_t *attr_list = cb->attr_list;
37 switch(enumeration_level)
39 case UDI_ENUMERATE_START:
40 case UDI_ENUMERATE_START_RESCAN:
41 cb->attr_valid_length = attr_list - cb->attr_list;
42 udi_enumerate_ack(cb, UDI_ENUMERATE_OK, BOCHSGA_OPS_GFX);
44 case UDI_ENUMERATE_NEXT:
45 udi_enumerate_ack(cb, UDI_ENUMERATE_DONE, 0);
49 void bochsga_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID)
52 void bochsga_final_cleanup_req(udi_mgmt_cb_t *cb)
56 void bochsga_bus_dev_channel_event_ind(udi_channel_event_cb_t *cb);
57 void bochsga_bus_dev_bus_bind_ack(udi_bus_bind_cb_t *cb, udi_dma_constraints_t dma_constraints, udi_ubit8_t perferred_endianness, udi_status_t status);
58 void bochsga_bus_dev_bind__pio_map(udi_cb_t *cb, udi_pio_handle_t new_pio_handle);
59 void bochsga_bus_dev_bind__intr_chanel(udi_cb_t *gcb, udi_channel_t new_channel);
60 void bochsga_bus_dev_bus_unbind_ack(udi_bus_bind_cb_t *cb);
62 void bochsga_bus_dev_channel_event_ind(udi_channel_event_cb_t *cb)
64 udi_cb_t *gcb = UDI_GCB(cb);
65 rdata_t *rdata = gcb->context;
69 case UDI_CHANNEL_CLOSED:
71 case UDI_CHANNEL_BOUND: {
72 rdata->active_cb = gcb;
73 udi_bus_bind_cb_t *bus_bind_cb = UDI_MCB(cb->params.parent_bound.bind_cb, udi_bus_bind_cb_t);
74 udi_bus_bind_req( bus_bind_cb );
75 // continue at bochsga_bus_dev_bus_bind_ack
79 void bochsga_bus_dev_bus_bind_ack(udi_bus_bind_cb_t *cb,
80 udi_dma_constraints_t dma_constraints, udi_ubit8_t perferred_endianness, udi_status_t status)
82 udi_cb_t *gcb = UDI_GCB(cb);
83 rdata_t *rdata = gcb->context;
85 /* Set up PIO handles */
86 rdata->init.pio_index = -1;
87 bochsga_bus_dev_bind__pio_map(gcb, UDI_NULL_PIO_HANDLE);
90 void bochsga_bus_dev_bind__pio_map(udi_cb_t *gcb, udi_pio_handle_t new_pio_handle)
92 rdata_t *rdata = gcb->context;
93 if( rdata->init.pio_index != (udi_index_t)-1 )
95 rdata->pio_handles[rdata->init.pio_index] = new_pio_handle;
98 rdata->init.pio_index ++;
99 if( rdata->init.pio_index < N_PIO )
101 const struct s_pio_ops *ops = &bochsga_pio_ops[rdata->init.pio_index];
102 udi_pio_map(bochsga_bus_dev_bind__pio_map, gcb,
103 ops->regset_idx, ops->base_offset, ops->length,
104 ops->trans_list, ops->list_length,
105 UDI_PIO_LITTLE_ENDIAN, 0, 0
110 udi_channel_event_complete( UDI_MCB(rdata->active_cb, udi_channel_event_cb_t), UDI_OK);
113 void bochsga_bus_dev_bus_unbind_ack(udi_bus_bind_cb_t *cb)
116 void bochsga_bus_dev_intr_attach_ack(udi_intr_attach_cb_t *intr_attach_cb, udi_status_t status)
119 void bochsga_bus_dev_intr_detach_ack(udi_intr_detach_cb_t *intr_detach_cb)
123 /* --- GFX Provider ops -- */
124 void bochsga_gfx_channel_event_ind(udi_channel_event_cb_t *cb)
128 void bochsga_gfx_bind_req(udi_gfx_bind_cb_t *cb)
130 /* TODO: ACK bind if nothing already bound */
132 void bochsga_gfx_unbind_req(udi_gfx_bind_cb_t *cb)
134 /* TODO: Release internal state? */
136 void bochsga_gfx_set_connector_req$pio(udi_cb_t *gcb, udi_buf_t *new_buf, udi_status_t status, udi_ubit16_t result)
138 udi_gfx_state_cb_t *cb = UDI_MCB(gcb, udi_gfx_state_cb_t);
139 udi_gfx_set_connector_ack(cb);
141 void bochsga_gfx_set_connector_req(udi_gfx_state_cb_t *cb, udi_ubit32_t value)
143 udi_cb_t *gcb = UDI_GCB(cb);
144 rdata_t *rdata = gcb->context;
146 switch(cb->attribute)
148 case UDI_GFX_PROP_ENABLE:
149 if( rdata->output_enable != !!value )
151 rdata->output_enable = !!value;
152 udi_pio_trans(bochsga_gfx_set_connector_req$pio, gcb,
153 rdata->pio_handles[BOCHSGA_PIO_ENABLE], rdata->output_enable, NULL, &rdata->outputstate);
156 udi_gfx_set_connector_ack(cb);
158 /* Change input engine */
159 case UDI_GFX_PROP_INPUT:
160 udi_gfx_set_connector_ack(cb);
162 /* Alter output dimensions */
163 case UDI_GFX_PROP_WIDTH:
164 if( value % 8 != 0 ) {
165 /* Qemu doesn't like resolutions not a multiple of 8 */
168 if( !(320 <= value && value <= rdata->limits.max_width) ) {
171 rdata->outputstate.width = value;
172 udi_pio_trans(bochsga_gfx_set_connector_req$pio, gcb,
173 rdata->pio_handles[BOCHSGA_PIO_ENABLE], rdata->output_enable, NULL, &rdata->outputstate);
175 case UDI_GFX_PROP_HEIGHT:
176 if( !(240 <= value && value <= rdata->limits.max_height) ) {
179 rdata->outputstate.height = value;
180 udi_pio_trans(bochsga_gfx_set_connector_req$pio, gcb,
181 rdata->pio_handles[BOCHSGA_PIO_ENABLE], rdata->output_enable, NULL, &rdata->outputstate);
184 CONTIN(bochsga_gfx_set_connector_req, udi_log_write,
185 (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
186 (udi_status_t status)
188 udi_gfx_state_cb_t *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
189 udi_gfx_set_connector_ack(cb /*, UDI_STAT_NOT_SUPPORTED*/);
191 void bochsga_gfx_get_connector_req(udi_gfx_state_cb_t *cb)
193 udi_cb_t *gcb = UDI_GCB(cb);
194 rdata_t *rdata = gcb->context;
196 switch(cb->attribute)
198 case UDI_GFX_PROP_ENABLE:
199 udi_gfx_get_connector_ack(cb, !!rdata->output_enable);
201 case UDI_GFX_PROP_INPUT:
202 udi_gfx_get_connector_ack(cb, 0);
204 case UDI_GFX_PROP_WIDTH:
205 udi_gfx_get_connector_ack(cb, rdata->outputstate.width);
207 case UDI_GFX_PROP_HEIGHT:
208 udi_gfx_get_connector_ack(cb, rdata->outputstate.height);
210 case UDI_GFX_PROP_CONNECTOR_TYPE:
211 udi_gfx_get_connector_ack(cb, UDI_GFX_CONNECTOR_HIDDEN);
213 case UDI_GFX_PROP_SIGNAL:
214 udi_gfx_get_connector_ack(cb, UDI_GFX_SIGNAL_INTEGRATED);
217 CONTIN(bochsga_gfx_get_connector_req, udi_log_write,
218 (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
219 (udi_status_t status)
221 udi_gfx_state_cb_t *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
222 udi_gfx_get_connector_ack(cb, 0);
224 void bochsga_gfx_range_connector_req(udi_gfx_range_cb_t *cb)
226 udi_cb_t *gcb = UDI_GCB(cb);
227 rdata_t *rdata = gcb->context;
229 switch(cb->attribute)
231 case UDI_GFX_PROP_ENABLE:
232 /* 2 values: 0 and 1 */
233 gfxhelpers_return_range_set(udi_gfx_range_connector_ack, cb, 2, 0, 1);
235 case UDI_GFX_PROP_INPUT:
237 gfxhelpers_return_range_fixed(udi_gfx_range_connector_ack, cb, 0);
239 case UDI_GFX_PROP_WIDTH:
240 /* qemu restricts to 8 step */
241 gfxhelpers_return_range_simple(udi_gfx_range_connector_ack, cb,
242 BOCHSGA_MIN_WIDTH, rdata->limits.max_width, 8);
244 case UDI_GFX_PROP_HEIGHT:
245 /* step of 8 for neatness */
246 gfxhelpers_return_range_simple(udi_gfx_range_connector_ack, cb,
247 BOCHSGA_MIN_HEIGHT, rdata->limits.max_height, 8);
249 case UDI_GFX_PROP_CONNECTOR_TYPE:
250 gfxhelpers_return_range_fixed(udi_gfx_range_connector_ack, cb, UDI_GFX_CONNECTOR_HIDDEN);
252 case UDI_GFX_PROP_SIGNAL:
253 gfxhelpers_return_range_fixed(udi_gfx_range_connector_ack, cb, UDI_GFX_SIGNAL_INTEGRATED);
256 CONTIN(bochsga_gfx_range_connector_req, udi_log_write,
257 (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
258 (udi_status_t status)
260 udi_gfx_range_cb_t *cb = UDI_MCB(cb, udi_gfx_range_cb_t);
261 udi_gfx_range_connector_ack(cb);
264 /* --- Engine Manipulation --- */
265 void bochsga_gfx_set_engine_req(udi_gfx_state_cb_t *cb, udi_ubit32_t value)
267 udi_cb_t *gcb = UDI_GCB(cb);
268 rdata_t *rdata = gcb->context;
270 if( cb->subsystem >= N_ENGINES ) {
271 udi_gfx_get_engine_ack(cb, 0);
275 engine_t *engine = &rdata->engines[cb->subsystem];
277 switch(cb->attribute)
279 case UDI_GFX_PROP_WIDTH:
280 engine->width = value;
281 udi_gfx_set_engine_ack(cb);
283 case UDI_GFX_PROP_HEIGHT:
284 engine->height = value;
285 udi_gfx_set_engine_ack(cb);
288 CONTIN(bochsga_gfx_set_engine_req, udi_log_write,
289 (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
290 (udi_status_t status)
292 udi_gfx_state_cb_t *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
293 udi_gfx_set_engine_ack(cb);
295 void bochsga_gfx_get_engine_req(udi_gfx_state_cb_t *cb)
297 udi_cb_t *gcb = UDI_GCB(cb);
298 rdata_t *rdata = gcb->context;
300 if( cb->subsystem >= N_ENGINES ) {
301 udi_gfx_get_engine_ack(cb, 0);
305 const engine_t *engine = &rdata->engines[cb->subsystem];
307 switch(cb->attribute)
309 case UDI_GFX_PROP_ENABLE:
310 udi_gfx_get_engine_ack(cb, 1);
313 case UDI_GFX_PROP_INPUT:
314 udi_gfx_get_engine_ack(cb, -1);
317 case UDI_GFX_PROP_WIDTH:
318 udi_gfx_get_engine_ack(cb, engine->width);
320 case UDI_GFX_PROP_HEIGHT:
321 udi_gfx_get_engine_ack(cb, engine->height);
324 case UDI_GFX_PROP_STOCK_FORMAT:
325 udi_gfx_get_engine_ack(cb, UDI_GFX_STOCK_FORMAT_R8G8B8);
328 CONTIN(bochsga_gfx_get_engine_req, udi_log_write,
329 (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
330 (udi_status_t status)
332 udi_gfx_state_cb_t *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
333 udi_gfx_get_engine_ack(cb, 0);
335 void bochsga_gfx_range_engine_req(udi_gfx_range_cb_t *cb)
337 udi_cb_t *gcb = UDI_GCB(cb);
338 rdata_t *rdata = gcb->context;
341 if( cb->subsystem >= N_ENGINES ) {
342 udi_gfx_range_engine_ack(cb);
346 //engine_t *engine = &rdata->engines[cb->subsystem];
348 switch(cb->attribute)
350 case UDI_GFX_PROP_ENABLE:
351 gfxhelpers_return_range_fixed(udi_gfx_range_engine_ack, cb, 1);
353 case UDI_GFX_PROP_INPUT:
354 gfxhelpers_return_range_fixed(udi_gfx_range_engine_ack, cb, -1);
357 case UDI_GFX_PROP_STOCK_FORMAT:
358 gfxhelpers_return_range_fixed(udi_gfx_range_engine_ack, cb, UDI_GFX_STOCK_FORMAT_B8G8R8);
361 CONTIN(bochsga_gfx_range_engine_req, udi_log_write,
362 (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
363 (udi_status_t status)
365 udi_gfx_range_cb_t *cb = UDI_MCB(cb, udi_gfx_range_cb_t);
366 udi_gfx_range_engine_ack( cb );
368 void bochsga_gfx_get_engine_operator_req(udi_gfx_range_cb_t *cb)
370 /* TODO: Get Engine operator */
371 udi_gfx_get_engine_operator_ack(cb, 0, 0,0,0);
373 void bochsga_gfx_connector_command_req(udi_gfx_command_cb_t *cb)
375 /* Need to parse the GLX stream */
376 udi_gfx_connector_command_ack(cb);
378 void bochsga_gfx_engine_command_req(udi_gfx_command_cb_t *cb)
380 /* Need to parse the GLX stream */
381 udi_gfx_engine_command_ack(cb);
383 void bochsga_gfx_buffer_info_req(udi_gfx_buffer_info_cb_t *cb)
385 udi_cb_t *gcb = UDI_GCB(cb);
386 switch(cb->buffer_index)
389 udi_gfx_buffer_info_ack(cb, 1024, 768, 24, 0);
394 CONTIN(bochsga_gfx_buffer_info_req, udi_log_write,
395 (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_BUFUNK, __func__, cb->buffer_index),
396 (udi_status_t status)
398 udi_gfx_buffer_info_cb_t *cb = UDI_MCB(gcb, udi_gfx_buffer_info_cb_t);
399 udi_gfx_buffer_info_ack(cb, 0,0,0,0);
401 void bochsga_gfx_buffer_write_req(udi_gfx_buffer_cb_t *cb)
404 void bochsga_gfx_buffer_read_req(udi_gfx_buffer_cb_t *cb)
409 ====================================================================
411 ====================================================================
413 udi_mgmt_ops_t bochsga_mgmt_ops = {
415 bochsga_enumerate_req,
417 bochsga_final_cleanup_req
419 udi_ubit8_t bochsga_mgmt_op_flags[4] = {0,0,0,0};
421 udi_bus_device_ops_t bochsga_bus_dev_ops = {
422 bochsga_bus_dev_channel_event_ind,
423 bochsga_bus_dev_bus_bind_ack,
424 bochsga_bus_dev_bus_unbind_ack,
425 bochsga_bus_dev_intr_attach_ack,
426 bochsga_bus_dev_intr_detach_ack
428 udi_ubit8_t bochsga_bus_dev_ops_flags[5] = {0};
429 /* - GFX provider ops */
430 udi_gfx_provider_ops_t bochsga_gfx_ops = {
431 bochsga_gfx_channel_event_ind,
432 bochsga_gfx_bind_req,
433 bochsga_gfx_unbind_req,
434 bochsga_gfx_set_connector_req,
435 bochsga_gfx_set_engine_req,
436 bochsga_gfx_get_connector_req,
437 bochsga_gfx_get_engine_req,
438 bochsga_gfx_range_connector_req,
439 bochsga_gfx_range_engine_req,
440 bochsga_gfx_get_engine_operator_req,
441 bochsga_gfx_connector_command_req,
442 bochsga_gfx_engine_command_req,
443 bochsga_gfx_buffer_info_req,
444 bochsga_gfx_buffer_read_req,
445 bochsga_gfx_buffer_write_req,
447 udi_ubit8_t bochsga_gfx_ops_flags[10] = {0};
449 udi_primary_init_t bochsga_pri_init = {
450 .mgmt_ops = &bochsga_mgmt_ops,
451 .mgmt_op_flags = bochsga_mgmt_op_flags,
452 .mgmt_scratch_requirement = 0,
453 .enumeration_attr_list_length = 0,
454 .rdata_size = sizeof(rdata_t),
455 .child_data_size = 0,
456 .per_parent_paths = 0
458 udi_ops_init_t bochsga_ops_list[] = {
460 BOCHSGA_OPS_DEV, BOCHSGA_META_BUS, UDI_BUS_DEVICE_OPS_NUM,
462 (udi_ops_vector_t*)&bochsga_bus_dev_ops,
463 bochsga_bus_dev_ops_flags
466 BOCHSGA_OPS_GFX, BOCHSGA_META_GFX, UDI_GFX_PROVIDER_OPS_NUM,
468 (udi_ops_vector_t*)&bochsga_gfx_ops,
469 bochsga_gfx_ops_flags
473 udi_cb_init_t bochsga_cb_init_list[] = {
474 {BOCHSGA_CB_BUS_BIND, BOCHSGA_META_BUS, UDI_BUS_BIND_CB_NUM, 0, 0,NULL},
475 {BOCHSGA_CB_GFX_BIND, BOCHSGA_META_GFX, UDI_GFX_BIND_CB_NUM, 0, 0,NULL},
476 {BOCHSGA_CB_GFX_STATE, BOCHSGA_META_GFX, UDI_GFX_STATE_CB_NUM, 0, 0,NULL},
477 {BOCHSGA_CB_GFX_RANGE, BOCHSGA_META_GFX, UDI_GFX_RANGE_CB_NUM, 0, 0,NULL},
478 {BOCHSGA_CB_GFX_COMMAND, BOCHSGA_META_GFX, UDI_GFX_COMMAND_CB_NUM, 0, 0,NULL},
481 const udi_init_t udi_init_info = {
482 .primary_init_info = &bochsga_pri_init,
483 .ops_init_list = bochsga_ops_list,
484 .cb_init_list = bochsga_cb_init_list,