NOTE: The UDI gfx binding is not finalised, and there are staged changes to the spec.
--- /dev/null
+/*
+ * UDI Bochs Graphics Driver
+ * By John Hodge (thePowersGang)
+ *
+ * bochsga_common.c
+ * - Common definitions
+ */
+#ifndef _BOCHSGA_COMMON_H_
+#define _BOCHSGA_COMMON_H_
+
+/**
+ * Definitions to match udiprops.txt
+ * \{
+ */
+#define BOCHSGA_META_BUS 1
+#define BOCHSGA_META_GFX 2
+
+#define BOCHSGA_OPS_DEV 1
+#define BOCHSGA_OPS_GFX 2
+
+#define BOCHSGA_CB_BUS_BIND 1
+#define BOCHSGA_CB_GFX_BIND 2
+#define BOCHSGA_CB_GFX_STATE 3
+#define BOCHSGA_CB_GFX_RANGE 4
+#define BOCHSGA_CB_GFX_COMMAND 5
+
+#define BOCHSGA_MSGNUM_PROPUNK 1001
+/**
+ * \}
+ */
+
+#include "bochsga_pio.h"
+#include "bochsga_engines.h"
+
+typedef struct {
+ udi_ubit32_t width;
+ udi_ubit32_t height;
+ udi_index_t op_idx;
+} engine_t;
+
+/**
+ * Region data
+ */
+typedef struct
+{
+ udi_cb_t *active_cb;
+ struct {
+ udi_index_t pio_index;
+ } init;
+
+ udi_pio_handle_t pio_handles[N_PIO];
+
+ udi_boolean_t output_enable;
+ struct {
+ udi_ubit32_t width;
+ udi_ubit32_t height;
+ udi_ubit8_t bitdepth;
+ udi_index_t engine;
+ } outputstate;
+ struct {
+ udi_ubit32_t max_width; // 1024 or 1280
+ udi_ubit32_t max_height; // 768 or 1024
+ } limits;
+
+ engine_t engines[N_ENGINES];
+} rdata_t;
+
+#define BOCHSGA_MIN_WIDTH 360
+#define BOCHSGA_MIN_HEIGHT 240
+
+#endif
+
--- /dev/null
+/*
+ * UDI Bochs Graphics Driver
+ * By John Hodge (thePowersGang)
+ *
+ * bochsga_core.c
+ * - Core Code
+ */
+#define UDI_VERSION 0x101
+#define UDI_GFX_VERSION 0x101
+#include <udi.h>
+#include <udi_physio.h>
+#include <udi_gfx.h>
+#define DEBUG_ENABLED 1
+#include "../helpers.h"
+#include "../helpers_gfx.h"
+#include "bochsga_common.h"
+
+// --- Management Metalang
+void bochsga_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level)
+{
+ rdata_t *rdata = UDI_GCB(cb)->context;
+ //udi_trace_write(rdata->init_context, UDI_TREVENT_LOCAL_PROC_ENTRY, 0, );
+
+ // TODO: Set up region data
+
+ udi_usage_res(cb);
+}
+
+void bochsga_enumerate_req(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level)
+{
+ rdata_t *rdata = UDI_GCB(cb)->context;
+ udi_instance_attr_list_t *attr_list = cb->attr_list;
+
+ switch(enumeration_level)
+ {
+ case UDI_ENUMERATE_START:
+ case UDI_ENUMERATE_START_RESCAN:
+ cb->attr_valid_length = attr_list - cb->attr_list;
+ udi_enumerate_ack(cb, UDI_ENUMERATE_OK, BOCHSGA_OPS_GFX);
+ break;
+ case UDI_ENUMERATE_NEXT:
+ udi_enumerate_ack(cb, UDI_ENUMERATE_DONE, 0);
+ break;
+ }
+}
+void bochsga_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID)
+{
+}
+void bochsga_final_cleanup_req(udi_mgmt_cb_t *cb)
+{
+}
+// ---
+void bochsga_bus_dev_channel_event_ind(udi_channel_event_cb_t *cb);
+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);
+void bochsga_bus_dev_bind__pio_map(udi_cb_t *cb, udi_pio_handle_t new_pio_handle);
+void bochsga_bus_dev_bind__intr_chanel(udi_cb_t *gcb, udi_channel_t new_channel);
+void bochsga_bus_dev_bus_unbind_ack(udi_bus_bind_cb_t *cb);
+
+void bochsga_bus_dev_channel_event_ind(udi_channel_event_cb_t *cb)
+{
+ udi_cb_t *gcb = UDI_GCB(cb);
+ rdata_t *rdata = gcb->context;
+
+ switch(cb->event)
+ {
+ case UDI_CHANNEL_CLOSED:
+ break;
+ case UDI_CHANNEL_BOUND: {
+ rdata->active_cb = gcb;
+ udi_bus_bind_cb_t *bus_bind_cb = UDI_MCB(cb->params.parent_bound.bind_cb, udi_bus_bind_cb_t);
+ udi_bus_bind_req( bus_bind_cb );
+ // continue at bochsga_bus_dev_bus_bind_ack
+ return; }
+ }
+}
+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)
+{
+ udi_cb_t *gcb = UDI_GCB(cb);
+ rdata_t *rdata = gcb->context;
+
+ // Set up PIO handles
+ rdata->init.pio_index = -1;
+ bochsga_bus_dev_bind__pio_map(gcb, UDI_NULL_PIO_HANDLE);
+ // V V V V
+}
+void bochsga_bus_dev_bind__pio_map(udi_cb_t *gcb, udi_pio_handle_t new_pio_handle)
+{
+ rdata_t *rdata = gcb->context;
+ if( rdata->init.pio_index != -1 )
+ {
+ rdata->pio_handles[rdata->init.pio_index] = new_pio_handle;
+ }
+
+ rdata->init.pio_index ++;
+ if( rdata->init.pio_index < N_PIO )
+ {
+ const struct s_pio_ops *ops = &bochsga_pio_ops[rdata->init.pio_index];
+ udi_pio_map(bochsga_bus_dev_bind__pio_map, gcb,
+ ops->regset_idx, ops->base_offset, ops->length,
+ ops->trans_list, ops->list_length,
+ UDI_PIO_LITTLE_ENDIAN, 0, 0
+ );
+ return ;
+ }
+
+ udi_channel_event_complete( UDI_MCB(rdata->active_cb, udi_channel_event_cb_t), UDI_OK);
+ // = = = = =
+}
+void bochsga_bus_dev_bus_unbind_ack(udi_bus_bind_cb_t *cb)
+{
+}
+void bochsga_bus_dev_intr_attach_ack(udi_intr_attach_cb_t *intr_attach_cb, udi_status_t status)
+{
+}
+void bochsga_bus_dev_intr_detach_ack(udi_intr_detach_cb_t *intr_detach_cb)
+{
+}
+// ---
+// GFX Provider ops
+void bochsga_gfx_channel_event_ind(udi_channel_event_cb_t *cb)
+{
+ // No operation
+}
+void bochsga_gfx_bind_req(udi_gfx_bind_cb_t *cb)
+{
+ // TODO: ACK bind if nothing already bound
+}
+void bochsga_gfx_unbind_req(udi_gfx_bind_cb_t *cb)
+{
+ // TODO: Release internal state?
+}
+void bochsga_gfx_set_connector_req$pio(udi_cb_t *gcb, udi_buf_t *new_buf, udi_status_t status, udi_ubit16_t result)
+{
+ udi_gfx_state_cb_t *cb = UDI_MCB(gcb, udi_gfx_state_cb_t);
+ udi_gfx_set_connector_ack(cb);
+}
+void bochsga_gfx_set_connector_req(udi_gfx_state_cb_t *cb, udi_ubit32_t value)
+{
+ udi_cb_t *gcb = UDI_GCB(cb);
+ rdata_t *rdata = gcb->context;
+
+ switch(cb->attribute)
+ {
+ case UDI_GFX_PROP_ENABLE:
+ if( rdata->output_enable != !!value )
+ {
+ rdata->output_enable = !!value;
+ udi_pio_trans(bochsga_gfx_set_connector_req$pio, gcb,
+ rdata->pio_handles[BOCHSGA_PIO_ENABLE], rdata->output_enable, NULL, &rdata->outputstate);
+ return ;
+ }
+ udi_gfx_set_connector_ack(cb);
+ return;
+ // Change input engine
+ // -
+ case UDI_GFX_PROP_INPUT:
+ if( rdata->outputstate.engine != value )
+ {
+ // Validate
+ if( !(0 <= value && value <= N_ENGINES) ) {
+ udi_gfx_set_connector_ack(cb /*, UDI_STAT_NOT_SUPPORTED*/);
+ return ;
+ }
+
+ // Change saved bitdepth (requires cycling enable)
+ rdata->outputstate.engine = value;
+ rdata->outputstate.bitdepth = bochsga_engine_defs[value].bitdepth;
+ }
+ udi_gfx_set_connector_ack(cb);
+ return;
+ // Alter output dimensions
+ case UDI_GFX_PROP_WIDTH:
+ if( value % 8 != 0 ) {
+ // Qemu doesn't like resolutions not a multiple of 8
+ return ;
+ }
+ if( !(320 <= value && value <= rdata->limits.max_width) ) {
+ return ;
+ }
+ rdata->outputstate.width = value;
+ udi_pio_trans(bochsga_gfx_set_connector_req$pio, gcb,
+ rdata->pio_handles[BOCHSGA_PIO_ENABLE], rdata->output_enable, NULL, &rdata->outputstate);
+ return;
+ case UDI_GFX_PROP_HEIGHT:
+ if( !(240 <= value && value <= rdata->limits.max_height) ) {
+ return ;
+ }
+ rdata->outputstate.height = value;
+ udi_pio_trans(bochsga_gfx_set_connector_req$pio, gcb,
+ rdata->pio_handles[BOCHSGA_PIO_ENABLE], rdata->output_enable, NULL, &rdata->outputstate);
+ return;
+ }
+ CONTIN(bochsga_gfx_set_connector_req, udi_log_write,
+ (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
+ (udi_status_t status)
+ );
+ udi_gfx_state_cb_t *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
+ udi_gfx_set_connector_ack(cb /*, UDI_STAT_NOT_SUPPORTED*/);
+}
+void bochsga_gfx_get_connector_req(udi_gfx_state_cb_t *cb)
+{
+ udi_cb_t *gcb = UDI_GCB(cb);
+ rdata_t *rdata = gcb->context;
+
+ switch(cb->attribute)
+ {
+ case UDI_GFX_PROP_ENABLE:
+ udi_gfx_get_connector_ack(cb, !!rdata->output_enable);
+ return;
+ case UDI_GFX_PROP_INPUT:
+ udi_gfx_get_connector_ack(cb, rdata->outputstate.bitdepth/8-1);
+ return;
+ case UDI_GFX_PROP_WIDTH:
+ udi_gfx_get_connector_ack(cb, rdata->outputstate.width);
+ return;
+ case UDI_GFX_PROP_HEIGHT:
+ udi_gfx_get_connector_ack(cb, rdata->outputstate.height);
+ return;
+ case UDI_GFX_PROP_CONNECTOR_TYPE:
+ udi_gfx_get_connector_ack(cb, UDI_GFX_CONNECTOR_HIDDEN);
+ return;
+ case UDI_GFX_PROP_SIGNAL:
+ udi_gfx_get_connector_ack(cb, UDI_GFX_SIGNAL_INTEGRATED);
+ return;
+ }
+ CONTIN(bochsga_gfx_get_connector_req, udi_log_write,
+ (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
+ (udi_status_t status)
+ );
+ udi_gfx_state_cb_t *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
+ udi_gfx_get_connector_ack(cb, 0);
+}
+void bochsga_gfx_range_connector_req(udi_gfx_range_cb_t *cb)
+{
+ udi_cb_t *gcb = UDI_GCB(cb);
+ rdata_t *rdata = gcb->context;
+
+ switch(cb->attribute)
+ {
+ case UDI_GFX_PROP_ENABLE:
+ // 2 values: 0 and 1
+ gfxhelpers_return_range_set(udi_gfx_range_connector_ack, cb, 2, 0, 1);
+ return;
+ case UDI_GFX_PROP_INPUT:
+ // 0--3 with a step of 1
+ gfxhelpers_return_range_simple(udi_gfx_range_connector_ack, cb, 0, 3, 1);
+ return;
+ case UDI_GFX_PROP_WIDTH:
+ gfxhelpers_return_range_simple(udi_gfx_range_connector_ack, cb,
+ BOCHSGA_MIN_WIDTH, rdata->limits.max_width, 8); // qemu restricts to 8 step
+ return;
+ case UDI_GFX_PROP_HEIGHT:
+ gfxhelpers_return_range_simple(udi_gfx_range_connector_ack, cb,
+ BOCHSGA_MIN_HEIGHT, rdata->limits.max_height, 8); // step of 8 for neatness
+ return;
+ case UDI_GFX_PROP_CONNECTOR_TYPE:
+ gfxhelpers_return_range_fixed(udi_gfx_range_connector_ack, cb, UDI_GFX_CONNECTOR_HIDDEN);
+ return;
+ case UDI_GFX_PROP_SIGNAL:
+ gfxhelpers_return_range_fixed(udi_gfx_range_connector_ack, cb, UDI_GFX_SIGNAL_INTEGRATED);
+ return;
+ }
+ CONTIN(bochsga_gfx_range_connector_req, udi_log_write,
+ (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
+ (udi_status_t status)
+ );
+ udi_gfx_range_cb_t *cb = UDI_MCB(cb, udi_gfx_range_cb_t);
+ udi_gfx_range_connector_ack(cb);
+}
+// --- Engine Manipulation ---
+void bochsga_gfx_set_engine_req(udi_gfx_state_cb_t *cb, udi_ubit32_t value)
+{
+ udi_cb_t *gcb = UDI_GCB(cb);
+ rdata_t *rdata = gcb->context;
+
+ if( cb->subsystem >= N_ENGINES ) {
+ udi_gfx_get_engine_ack(cb, 0);
+ return;
+ }
+
+ engine_t *engine = &rdata->engines[cb->subsystem];
+
+ switch(cb->attribute)
+ {
+ case UDI_GFX_PROP_WIDTH:
+ engine->width = value;
+ udi_gfx_set_engine_ack(cb);
+ return;
+ case UDI_GFX_PROP_HEIGHT:
+ engine->height = value;
+ udi_gfx_set_engine_ack(cb);
+ return;
+ case UDI_GFX_PROP_OPERATOR_INDEX:
+ if( value >= bochsga_engine_defs[cb->subsystem].op_map.op_count ) {
+ // Bad value
+ udi_gfx_set_engine_ack(cb);
+ return;
+ }
+ engine->op_idx = value;
+ udi_gfx_set_engine_ack(cb);
+ return;
+ }
+ CONTIN(bochsga_gfx_set_engine_req, udi_log_write,
+ (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
+ (udi_status_t status)
+ );
+ udi_gfx_state_cb_t *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
+ udi_gfx_set_engine_ack(cb);
+}
+void bochsga_gfx_get_engine_req(udi_gfx_state_cb_t *cb)
+{
+ udi_cb_t *gcb = UDI_GCB(cb);
+ rdata_t *rdata = gcb->context;
+
+ if( cb->subsystem >= N_ENGINES ) {
+ udi_gfx_get_engine_ack(cb, 0);
+ return;
+ }
+
+ const engine_t *engine = &rdata->engines[cb->subsystem];
+ const engine_static_t *engine_def = &bochsga_engine_defs[cb->subsystem];
+
+ switch(cb->attribute)
+ {
+ case UDI_GFX_PROP_ENABLE:
+ udi_gfx_get_engine_ack(cb, 1);
+ return;
+
+ case UDI_GFX_PROP_INPUT:
+ udi_gfx_get_engine_ack(cb, -1);
+ return;
+
+ case UDI_GFX_PROP_WIDTH:
+ udi_gfx_get_engine_ack(cb, engine->width);
+ return;
+ case UDI_GFX_PROP_HEIGHT:
+ udi_gfx_get_engine_ack(cb, engine->height);
+ return;
+
+ case UDI_GFX_PROP_OPERATOR_INDEX:
+ udi_gfx_get_engine_ack(cb, engine->op_idx);
+ return;
+ case UDI_GFX_PROP_OPERATOR_OPCODE:
+ case UDI_GFX_PROP_OPERATOR_ARG_1:
+ case UDI_GFX_PROP_OPERATOR_ARG_2:
+ case UDI_GFX_PROP_OPERATOR_ARG_3:
+ udi_gfx_get_engine_ack(cb, gfxhelpers_get_engine_op(&engine_def->op_map, engine->op_idx, cb->attribute));
+ return;
+ }
+ CONTIN(bochsga_gfx_get_engine_req, udi_log_write,
+ (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
+ (udi_status_t status)
+ );
+ udi_gfx_state_cb_t *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
+ udi_gfx_get_engine_ack(cb, 0);
+}
+void bochsga_gfx_range_engine_req(udi_gfx_range_cb_t *cb)
+{
+ udi_cb_t *gcb = UDI_GCB(cb);
+ rdata_t *rdata = gcb->context;
+
+ if( cb->subsystem >= N_ENGINES ) {
+ udi_gfx_range_engine_ack(cb);
+ return;
+ }
+
+ engine_t *engine = &rdata->engines[cb->subsystem];
+ const engine_static_t *engine_def = &bochsga_engine_defs[cb->subsystem];
+
+ switch(cb->attribute)
+ {
+ case UDI_GFX_PROP_ENABLE:
+ gfxhelpers_return_range_fixed(udi_gfx_range_engine_ack, cb, 1);
+ return;
+ case UDI_GFX_PROP_INPUT:
+ gfxhelpers_return_range_fixed(udi_gfx_range_engine_ack, cb, -1);
+ return;
+
+ case UDI_GFX_PROP_OPERATOR_INDEX:
+ gfxhelpers_return_range_simple(udi_gfx_range_engine_ack, cb, 0, engine->op_idx-1, 1);
+ return;
+ case UDI_GFX_PROP_OPERATOR_OPCODE:
+ case UDI_GFX_PROP_OPERATOR_ARG_1:
+ case UDI_GFX_PROP_OPERATOR_ARG_2:
+ case UDI_GFX_PROP_OPERATOR_ARG_3:
+ gfxhelpers_return_range_fixed(udi_gfx_range_engine_ack, cb,
+ gfxhelpers_get_engine_op(&engine_def->op_map, engine->op_idx, cb->attribute));
+ return;
+ }
+ CONTIN(bochsga_gfx_range_engine_req, udi_log_write,
+ (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
+ (udi_status_t status)
+ );
+ udi_gfx_range_cb_t *cb = UDI_MCB(cb, udi_gfx_range_cb_t);
+ udi_gfx_range_engine_ack( cb );
+}
+void bochsga_gfx_command_req(udi_gfx_command_cb_t *cb)
+{
+ // Need to parse the GLX stream
+}
+
+// ====================================================================
+// - Management ops
+udi_mgmt_ops_t bochsga_mgmt_ops = {
+ bochsga_usage_ind,
+ bochsga_enumerate_req,
+ bochsga_devmgmt_req,
+ bochsga_final_cleanup_req
+};
+udi_ubit8_t bochsga_mgmt_op_flags[4] = {0,0,0,0};
+// - Bus Ops
+udi_bus_device_ops_t bochsga_bus_dev_ops = {
+ bochsga_bus_dev_channel_event_ind,
+ bochsga_bus_dev_bus_bind_ack,
+ bochsga_bus_dev_bus_unbind_ack,
+ bochsga_bus_dev_intr_attach_ack,
+ bochsga_bus_dev_intr_detach_ack
+};
+udi_ubit8_t bochsga_bus_dev_ops_flags[5] = {0};
+// - GFX provider ops
+udi_gfx_provider_ops_t bochsga_gfx_ops = {
+ bochsga_gfx_channel_event_ind,
+ bochsga_gfx_bind_req,
+ bochsga_gfx_unbind_req,
+ bochsga_gfx_set_connector_req,
+ bochsga_gfx_set_engine_req,
+ bochsga_gfx_get_connector_req,
+ bochsga_gfx_get_engine_req,
+ bochsga_gfx_range_connector_req,
+ bochsga_gfx_range_engine_req,
+ bochsga_gfx_command_req
+};
+udi_ubit8_t bochsga_gfx_ops_flags[10] = {0};
+// --
+udi_primary_init_t bochsga_pri_init = {
+ .mgmt_ops = &bochsga_mgmt_ops,
+ .mgmt_op_flags = bochsga_mgmt_op_flags,
+ .mgmt_scratch_requirement = 0,
+ .enumeration_attr_list_length = 0,
+ .rdata_size = sizeof(rdata_t),
+ .child_data_size = 0,
+ .per_parent_paths = 0
+};
+udi_ops_init_t bochsga_ops_list[] = {
+ {
+ BOCHSGA_OPS_DEV, BOCHSGA_META_BUS, UDI_BUS_DEVICE_OPS_NUM,
+ 0,
+ (udi_ops_vector_t*)&bochsga_bus_dev_ops,
+ bochsga_bus_dev_ops_flags
+ },
+ {
+ BOCHSGA_OPS_GFX, BOCHSGA_META_GFX, UDI_GFX_PROVIDER_OPS_NUM,
+ 0,
+ (udi_ops_vector_t*)&bochsga_gfx_ops,
+ bochsga_gfx_ops_flags
+ },
+ {0}
+};
+udi_cb_init_t bochsga_cb_init_list[] = {
+ {BOCHSGA_CB_BUS_BIND, BOCHSGA_META_BUS, UDI_BUS_BIND_CB_NUM, 0, 0,NULL},
+ {BOCHSGA_CB_GFX_BIND, BOCHSGA_META_GFX, UDI_GFX_BIND_CB_NUM, 0, 0,NULL},
+ {BOCHSGA_CB_GFX_STATE, BOCHSGA_META_GFX, UDI_GFX_STATE_CB_NUM, 0, 0,NULL},
+ {BOCHSGA_CB_GFX_RANGE, BOCHSGA_META_GFX, UDI_GFX_RANGE_CB_NUM, 0, 0,NULL},
+ {BOCHSGA_CB_GFX_COMMAND, BOCHSGA_META_GFX, UDI_GFX_COMMAND_CB_NUM, 0, 0,NULL},
+ {0}
+};
+const udi_init_t udi_init_info = {
+ .primary_init_info = &bochsga_pri_init,
+ .ops_init_list = bochsga_ops_list,
+ .cb_init_list = bochsga_cb_init_list,
+};
--- /dev/null
+/*
+ *
+ */
+
+#define BOCHSGA_ENGINE_PROP_BUFFER (UDI_GFX_PROP_CUSTOM+0)
+
+// === CONSTANTS ===
+const gfxhelpers_op_t bochsga_engine_ops_8bpp[] = {
+};
+const gfxhelpers_op_t bochsga_engine_ops_32bpp[] = {
+ {UDI_GFX_OPERATOR_RGB, 1, 2, 3}, // #0 Output RGB from ops #1,#2,#3
+ {UDI_GFX_OPERATOR_SEG, 4, 16, 8}, // #1 Extract 8 bits from bit 16 of #4
+ {UDI_GFX_OPERATOR_SEG, 4, 8, 8}, // #2 8 bits from ofs 8 of #4
+ {UDI_GFX_OPERATOR_SEG, 4, 0, 8}, // #3 8 bits from ofs 0 of #4
+ {UDI_GFX_OPERATOR_BUFFER, 5, 6, 32}, // #4 32 bits from buffer #5 ofs #6
+ {UDI_GFX_OPERATOR_ATTR, 0, BOCHSGA_ENGINE_PROP_BUFFER, 0}, // #5 Buffer index
+ {UDI_GFX_OPERATOR_MAD, 7, 8, 9}, // #6 Get offset (#8 * #7 + #9)
+ {UDI_GFX_OPERATOR_ATTR, 0, UDI_GFX_PROP_SOURCE_WIDTH, 0}, // #7 Read buffer width
+ {UDI_GFX_OPERATOR_Y, 0, 0, 0}, // #8 Y coordinate
+ {UDI_GFX_OPERATOR_X, 0, 0, 0} // #9 X coordinate
+};
+
+typedef struct {
+ udi_ubit8_t bitdepth;
+ gfxhelpers_op_map_t op_map;
+} engine_static_t;
+
+const engine_static_t bochsga_engine_defs[] = {
+ {.bitdepth = 8, .op_map = {ARRAY_COUNT(bochsga_engine_ops_8bpp), bochsga_engine_ops_8bpp}},
+ {.bitdepth = 16},
+ {.bitdepth = 24},
+ {.bitdepth = 32, .op_map = {ARRAY_COUNT(bochsga_engine_ops_8bpp), bochsga_engine_ops_32bpp}},
+};
+#define N_ENGINES ARRAY_COUNT(bochsga_engine_defs)
--- /dev/null
+/*
+ * TODO
+ */
+#ifndef _BOCHSGA_PIO_H_
+#define _BOCHSGA_PIO_H_
+
+udi_pio_trans_t bochsga_pio_enable[] = {
+ {UDI_PIO_END_IMM, UDI_PIO_2BYTE, 0},
+ };
+
+enum {
+ BOCHSGA_PIO_ENABLE,
+};
+
+const struct s_pio_ops bochsga_pio_ops[] = {
+ [BOCHSGA_PIO_ENABLE] = UDIH_PIO_OPS_ENTRY(bochsga_pio_enable, 0, UDI_PCI_BAR_2, 0x400, 0xB*2),
+// UDIH_PIO_OPS_ENTRY(bochsga_pio_enable, 0, UDI_PCI_BAR_2, 0x400, 0xB*2),
+ };
+#define N_PIO (sizeof(bochsga_pio_ops)/sizeof(struct s_pio_ops))
+
+#endif
+
--- /dev/null
+properties_version 0x101
+supplier 1
+contact 2
+name 3
+shortname bochsga
+release 5 1.0
+
+requires udi 0x101
+requires udi_physio 0x101
+requires udi_bridge 0x101
+requires udi_gfx 0x101
+
+meta 1 udi_bridge
+meta 2 udi_gfx
+#meta 3 udi_gio
+
+parent_bind_ops 1 0 1 1 # bridge, rgn 0, ops 1, cb 1
+child_bind_ops 2 0 2 # Provider
+#parent_bind_ops 3 0 2 3 # GIO bound to 3D provider
+
+#enumerates 102 1 1 3 gio_type string software3d
+
+# - Classic non-PCI version
+device 100 1 bus string system sysbus_io_addr_lo ubit32 0x01CE sysbus_io_size ubit32 2 sysbys_mem_addr_lo ubit32 0xE0000000 sysbus_mem_size 0x400000
+# - PCI Version (Non-indexed registers at offset 0x500 in BAR2 MMIO)
+device 101 1 bus string pci pci_vendor_id ubit32 0x1234 pci_device_id ubit32 0x1111 pci_base_class ubit32 0x03 pci_sub_clais ubit32 0x00 pci_prog_if ubit32 0x00
+
+# Messages
+message 1 John Hodge (thePowersGang)
+message 3 Bochs Graphics Adapter
+message 5 BochsGA
+message 100 BochsGA ISA Device
+message 101 BochsGA PCI Device
+
+message 1001 "Unknown property passed to %s: %i"
+
+module bochsga
+region 0
+
+# Source-only udiprops
+compile_options -Wall
+source_files bochsga_core.c
--- /dev/null
+/*
+ * UDI Driver helper macros
+ */
+#ifndef _UDI_HELPERS_H_
+#define _UDI_HELPERS_H_
+
+#if DEBUG_ENABLED
+# define DEBUG_OUT(fmt, v...) udi_debug_printf("%s: "fmt"\n", __func__ ,## v)
+#else
+# define DEBUG_OUT(...) do{}while(0)
+#endif
+
+#define ARRAY_COUNT(arr) (sizeof(arr)/sizeof(arr[0]))
+
+#define __EXPJOIN(a,b) a##b
+#define _EXPJOIN(a,b) __EXPJOIN(a,b)
+#define _EXPLODE(params...) params
+#define _ADDGCB(params...) (udi_cb_t *gcb, params)
+#define CONTIN(suffix, call, args, params) extern void _EXPJOIN(suffix##$,__LINE__) _ADDGCB params;\
+ call( _EXPJOIN(suffix##$,__LINE__), gcb, _EXPLODE args); } \
+ void _EXPJOIN(suffix##$,__LINE__) _ADDGCB params { \
+ rdata_t *rdata = gcb->context;
+
+/* Copied from http://projectudi.cvs.sourceforge.net/viewvc/projectudi/udiref/driver/udi_dpt/udi_dpt.h */
+#define UDIH_SET_ATTR_BOOLEAN(attr, name, val) \
+ udi_strcpy((attr)->attr_name, (name)); \
+ (attr)->attr_type = UDI_ATTR_BOOLEAN; \
+ (attr)->attr_length = sizeof(udi_boolean_t); \
+ UDI_ATTR32_SET((attr)->attr_value, (val))
+
+#define UDIH_SET_ATTR32(attr, name, val) \
+ udi_strcpy((attr)->attr_name, (name)); \
+ (attr)->attr_type = UDI_ATTR_UBIT32; \
+ (attr)->attr_length = sizeof(udi_ubit32_t); \
+ UDI_ATTR32_SET((attr)->attr_value, (val))
+
+#define UDIH_SET_ATTR_ARRAY8(attr, name, val, len) \
+ udi_strcpy((attr)->attr_name, (name)); \
+ (attr)->attr_type = UDI_ATTR_ARRAY8; \
+ (attr)->attr_length = (len); \
+ udi_memcpy((attr)->attr_value, (val), (len))
+
+#define UDIH_SET_ATTR_STRING(attr, name, val, len) \
+ udi_strcpy((attr)->attr_name, (name)); \
+ (attr)->attr_type = UDI_ATTR_STRING; \
+ (attr)->attr_length = (len); \
+ udi_strncpy_rtrim((char *)(attr)->attr_value, (val), (len))
+#define UDIH_SET_ATTR_STRFMT(attr, name, maxlen, fmt, v...) \
+ udi_strcpy((attr)->attr_name, (name)); \
+ (attr)->attr_type = UDI_ATTR_STRING; \
+ (attr)->attr_length = udi_snprintf((char *)(attr)->attr_value, (maxlen), (fmt) ,## v )
+
+/**
+ * \brief UDI PIO Helpers
+ */
+struct s_pio_ops {
+ udi_pio_trans_t *trans_list;
+ udi_ubit16_t list_length;
+ udi_ubit16_t pio_attributes;
+ udi_ubit32_t regset_idx;
+ udi_ubit32_t base_offset;
+ udi_ubit32_t length;
+};
+#define UDIH_PIO_OPS_ENTRY(list, attr, regset, base, len) {list, ARRAY_COUNT(list), attr, regset, base, len}
+#endif
--- /dev/null
+/*
+ * UDI Driver Helper Macros
+ *
+ * GFX-specific helpers
+ */
+#ifndef _HELPERS_GFX_H_
+#define _HELPERS_GFX_H_
+
+typedef struct {
+ udi_index_t op;
+ udi_ubit32_t arg_1;
+ udi_ubit32_t arg_2;
+ udi_ubit32_t arg_3;
+} gfxhelpers_op_t;
+
+typedef struct {
+ udi_index_t op_count;
+ const gfxhelpers_op_t *ops;
+} gfxhelpers_op_map_t;
+
+static inline udi_ubit32_t gfxhelpers_get_engine_op(
+ const gfxhelpers_op_map_t *map, udi_index_t index, udi_index_t prop
+ )
+{
+ if( index >= map->op_count ) {
+ return 0;
+ }
+ switch(prop) {
+ case UDI_GFX_PROP_OPERATOR_OPCODE: return map->ops[index].op;
+ case UDI_GFX_PROP_OPERATOR_ARG_1: return map->ops[index].arg_1;
+ case UDI_GFX_PROP_OPERATOR_ARG_2: return map->ops[index].arg_2;
+ case UDI_GFX_PROP_OPERATOR_ARG_3: return map->ops[index].arg_3;
+ }
+ return 0;
+}
+
+static inline void gfxhelpers_return_range_simple(
+ udi_gfx_range_connector_ack_op_t *callback, udi_gfx_range_cb_t *cb,
+ udi_ubit32_t min, udi_ubit32_t max, udi_ubit32_t step
+ )
+{
+
+}
+
+static inline void gfxhelpers_return_range_set(
+ udi_gfx_range_connector_ack_op_t *callback, udi_gfx_range_cb_t *cb,
+ udi_ubit32_t count, ...
+ )
+{
+
+}
+
+static inline void gfxhelpers_return_range_fixed(
+ udi_gfx_range_connector_ack_op_t *callback, udi_gfx_range_cb_t *cb,
+ udi_ubit32_t value
+ )
+{
+ gfxhelpers_return_range_simple(callback, cb, value, value, 1);
+}
+
+#endif
+
--- /dev/null
+
+
+- Indexed engine operator list (would be better as second set of calls)
+ > Arguments can be passed using custom attributes
+- GL-centric operations (would be better with read_buffer/write_buffer calls)
+- No status returned from operations most
+- Input data format specifcation
+ > Engine operator list specifies it, but in an abstract way (which would require quite smart code to determine)
+ > Doable though, but having a RO property on the engine that notes if it uses a standard pixel format would be nice
+
+
+Engine inspection API:
+> Readonly? Property for number of operations
+ - Readonly because modifcation of the count is not possible
+ - Attributes can be read, so that's your config mechanisim
+> udi_gfx_engine_getop_req(udi_gfx_state_cb_t *cb);
+> udi_gfx_engine_getop_ack(udi_gfx_state_cb_t *cb, udi_ubit8_t operation, udi_ubit32_t arg1, udi_ubit32_t arg2, udi_ubit32_t arg3);
+
+
+Buffer manipulation API:
+
+ struct {
+ udi_cb_t gcb;
+ udi_index_t buffer_idx;
+ udi_ubit32_t offset;
+ udi_buffer_t *data;
+ } udi_gfx_buffer_cb_t;
+
+> udi_gfx_buffer_write_req(udi_gfx_buffer_cb_t *cb);
+> udi_gfx_buffer_write_ack(udi_gfx_buffer_cb_t *cb, udi_status_t status);
+> (OPTIONAL) udi_gfx_buffer_read_req(udi_gfx_buffer_cb_t *cb);
--- /dev/null
+/**
+ * Summary: udi_gfx.h
+ * Contains the graphics metalanguage interface details
+ *
+ * Author:
+ * Marcel Sondaar
+ *
+ * License:
+ * <Public Domain>
+ *
+ * Source:
+ * https://www.d-rift.nl/combuster/mos3/?p=viewsource&file=/include/common/udi_gfx.h
+ */
+
+// note that the specification, and thus, the contents of this file is not fixed.
+
+#ifndef __UDI_GFX_H__
+#define __UDI_GFX_H__
+
+#include <udi.h>
+
+#ifndef UDI_GFX_VERSION
+#error "UDI_GFX_VERSION not defined."
+#elif UDI_GFX_VERSION != 0x101
+#error "UDI_GFX_VERSION not supported."
+#endif
+
+/**
+ * Enumeration: UDI_GFX_PROP
+ * Lists the various UDI properties
+ */
+
+// General state properties
+/* Constant: UDI_GFX_PROP_ENABLE
+ *
+ * Valid values:
+ * 0 - disabled
+ * 1 - enabled
+ *
+ * Ranges:
+ * Hardwired 1, or 0-1
+ *
+ * The connector or engine is enabled (nonzero) or disabled (zero). A disabled
+ * engine forwards all data from the previous stage unmodified. A disabled
+ * connector does not send any data over the connector. Drivers may power down
+ * the physical counterparts of disabled components to preserve power, and users
+ * should expect delays when enabling connectors or components representing
+ * framebuffers. Disabling is however not recommended for sprite layers, which
+ * may repeatedly be enabled and disabled. A disabled component can still have
+ * its state changed, and the driver must complete all commands and other state
+ * changes as expected, regardless of disabled or power state. The valid ranges
+ * reported for this property may be 1 (always enabled) or 0-1 (either enabled
+ * or disabled).
+ */
+#define UDI_GFX_PROP_ENABLE 0
+/* Constant: UDI_GFX_PROP_INPUT
+ *
+ * Valid values:
+ * Any valid engine ID, provided no dependency cycles are created, or -1
+ *
+ * Ranges:
+ * Any non-empty set of valid values. Often hardwired.
+ *
+ * Points to the engine that is processed before this unit. In the case of a
+ * connector, it points to the last engine in a pipeline, and each engine points
+ * to the next engine in the sequence. A value of -1 indicates a source that
+ * only yields black pixels. Implementations must not allow cyclic structures.
+ * Changing this value may reallocate resources, and engines that are no longer
+ * referenced may lose their data (but not their state) when it is not part of
+ * any pipeline. If preservation is required, the ENABLE state should be used
+ * instead. Valid ranges includes one or more from the list of engines and -1
+ * combined. In most cases, this property can not be modified.
+ */
+#define UDI_GFX_PROP_INPUT 1
+/* Constant: UDI_GFX_PROP_WIDTH
+ *
+ * Valid values:
+ * Any non-zero positive number.
+ *
+ * Ranges:
+ * Contains at least one valid value. Often only multiples of UNIT_WIDTH
+ * or a power of two are allowed. May be hardwired.
+ *
+ * Contains the amount of pixels in the horizontal direction. For connectors,
+ * this is the amount of data pixels rendered horizontally. For engines, this
+ * is the width in pixels of the image. Pixels requested from an engine outside
+ * the range (0..width-1) are defined according to the <UDI_GFX_PROP_CLIP>
+ * property. In some cases, hardware may support only fixed combinations of
+ * width and height. In such cases, changing the width will also change the
+ * height to a corresponding valid number. Valid ranges include any values
+ * strictly above zero. For connectors, expect large continuous ranges, large
+ * ranges with a certain modulus, a limited number of fixed values, or a
+ * constant value.
+ */
+#define UDI_GFX_PROP_WIDTH 2
+/* Constant: UDI_GFX_PROP_HEIGHT
+ *
+ * Valid values:
+ * Any non-zero positive number.
+ *
+ * Ranges:
+ * Contains at least one valid value. Often only multiples of UNIT_HEIGHT
+ * or a power of two are allowed. May be hardwired.
+ *
+ * Contains the amount of pixels in the vertical direction. Functions similar
+ * to the width property, but changing it will not alter the width property,
+ * and it's range at any time contains the valid range for the currently
+ * selected width.
+ */
+#define UDI_GFX_PROP_HEIGHT 3
+
+/* Constant: UDI_GFX_PROP_CUSTOM
+ * The first property index of the driver's custom range. These are not assigned
+ * directly assigned by the UDI specification, but may be specified in the
+ * operator tree.
+ */
+#define UDI_GFX_PROP_CUSTOM 1024
+
+// engine properties
+
+/* Constant: UDI_GFX_PROP_CLIP
+ *
+ * Valid values:
+ * 0 - points outside width x height are passed from next stage
+ * 1 - the engine's contents is tiled with size width x height
+ * 2 - points outside the width overflow into the y coordinate
+ * 3 - points outside the height overflow into the x coordinate
+ *
+ * Ranges:
+ * Hardwired zero for connectors. Any non-empty subset for engines, usually
+ * hardwired.
+ *
+ * For engines, contains the behaviour for pixels requested outside the width
+ * and height of the engine. Can be either 0 (pass from next stage), 1 (the
+ * coordinates are wrapped modulus the height and width), 2 (the coordinates
+ * overflow onto the next scanline horizontally, and wrap vertically), 3 (the
+ * coordinates overflow onto the next column vertically, and wrap horizontally).
+ * Valid ranges contain one or more of these options. For overlays and sprites,
+ * a value 0 is common. For framebuffers, 2 is the most common value. For
+ * connectors, this property is always 0 since they do not store pixel data
+ */
+#define UDI_GFX_PROP_CLIP 4
+
+/* Constant: UDI_GFX_PROP_UNIT_WIDTH
+ *
+ * Valid values:
+ * Any non-zero positive value
+ *
+ * Ranges:
+ * Any non-empty set of valid values. May be hardwired to 1 for
+ * framebuffers, or a range of small values for hardware scaling, or any
+ * larger hardwired number or set for tiling engines.
+ *
+ * Tiles are used to indicate that the hardware groups sets of pixels and have
+ * each group share certain properties, i.e. color or tile index, or share the
+ * same chroma subsample with only a different intensity. If the engine has no
+ * such grouping, or shares all properties over the entire contents, the value
+ * of this property should be 1. Some tile examples include rescaling, where a
+ * tile width of 2 indicates a pixel doubling in X direction, or in text mode
+ * where a tile width of 8 or 9 corresponds with the width of common bitmap
+ * fonts
+ */
+#define UDI_GFX_PROP_UNIT_WIDTH 5
+
+/* Constant: UDI_GFX_PROP_UNIT_HEIGHT
+ *
+ * Valid values:
+ * Any non-zero positive value
+ *
+ * Ranges:
+ * Any non-empty set of valid values. May be hardwired to 1 for
+ * framebuffers, or a range of small values for hardware scaling, or any
+ * larger hardwired number or set for tiling engines.
+ *
+ * See <UDI_GFX_PROP_UNIT_WIDTH>, but for the Y direction. Common values are
+ * 1-2 for framebuffers (doublescanning on or off), identical to the tile
+ * width, or mostly independent.
+ */
+#define UDI_GFX_PROP_UNIT_HEIGHT 6
+
+#define UDI_GFX_PROP_TRANSLATEX 7
+#define UDI_GFX_PROP_TRANSLATEY 8
+#define UDI_GFX_PROP_SOURCE_WIDTH 12
+#define UDI_GFX_PROP_SOURCE_HEIGHT 13
+#define UDI_GFX_PROP_GL_VERSION 14
+#define UDI_GFX_PROP_GLES_VERSION 15
+#define UDI_GFX_PROP_STATE_BLOCK 16
+/**
+ * Each engine consists of 1 or more operators
+ */
+#define UDI_GFX_PROP_OPERATOR_INDEX 17 //!< Index of operator to inspect/manipulate
+#define UDI_GFX_PROP_OPERATOR_OPCODE 18 //!< Operation performed by operator
+#define UDI_GFX_PROP_OPERATOR_ARG_1 19 //!< argument 1
+#define UDI_GFX_PROP_OPERATOR_ARG_2 20 //!< argument 2
+#define UDI_GFX_PROP_OPERATOR_ARG_3 21 //!< argument 3
+#define UDI_GFX_PROP_COLOR_BITS 22
+#define UDI_GFX_PROP_GL_TARGET 23
+#define UDI_GFX_PROP_INPUTX 25
+#define UDI_GFX_PROP_INPUTY 26
+
+// properties for removal:
+#define UDI_GFX_PROP_STORE_COUNT 24 // not generic
+#define UDI_GFX_PROP_STORE_WIDTH 9 // not generic
+#define UDI_GFX_PROP_STORE_HEIGHT 10 // not generic
+#define UDI_GFX_PROP_STORE_BITS 11 // not generic
+#define UDI_GFX_PROP_PALETTE 1024 // optional, can be derived from the operator tree
+#define UDI_GFX_PROP_BUFFER 1025 // optional, can be derived from the operator tree
+#define UDI_GFX_PROP_TILESHEET 1026 // optional, can be derived from the operator tree
+
+// connector properties
+#define UDI_GFX_PROP_SIGNAL 23
+#define UDI_GFX_PROP_CONNECTOR_TYPE 24
+#define UDI_GFX_PROP_VGA_H_FRONT_PORCH 25
+#define UDI_GFX_PROP_VGA_H_BACK_PORCH 26
+#define UDI_GFX_PROP_VGA_H_SYNC 27
+#define UDI_GFX_PROP_VGA_V_FRONT_PORCH 28
+#define UDI_GFX_PROP_VGA_V_BACK_PORCH 29
+#define UDI_GFX_PROP_VGA_V_SYNC 30
+#define UDI_GFX_PROP_DOT_CLOCK 31
+#define UDI_GFX_PROP_VGA_H_SYNC_POL 32
+#define UDI_GFX_PROP_VGA_V_SYNC_POL 33
+
+/**
+ * Enumeration: UDI_GFX_SIGNAL
+ * Lists the various signal types
+ */
+#define UDI_GFX_SIGNAL_HIDDEN 0
+#define UDI_GFX_SIGNAL_INTEGRATED 0
+#define UDI_GFX_SIGNAL_RGBHV 1
+#define UDI_GFX_SIGNAL_RGBS 2
+#define UDI_GFX_SIGNAL_RGSB 3
+#define UDI_GFX_SIGNAL_YPBPR 4
+#define UDI_GFX_SIGNAL_DVID 5
+#define UDI_GFX_SIGNAL_YUV 6
+#define UDI_GFX_SIGNAL_YIQ 7
+#define UDI_GFX_SIGNAL_Y_UV 8
+#define UDI_GFX_SIGNAL_Y_IQ 9
+#define UDI_GFX_SIGNAL_HDMI 10
+#define UDI_GFX_SIGNAL_TEXT 11
+#define UDI_GFX_SIGNAL_CUSTOM 12
+
+/**
+ * Enumeration: UDI_GFX_CONNECTOR
+ * Lists the various external connectors
+ */
+#define UDI_GFX_CONNECTOR_HIDDEN 0
+#define UDI_GFX_CONNECTOR_VGA 1
+#define UDI_GFX_CONNECTOR_DVI 2
+#define UDI_GFX_CONNECTOR_SVIDEO 3
+#define UDI_GFX_CONNECTOR_COMPONENT 4
+#define UDI_GFX_CONNECTOR_HDMI 5
+#define UDI_GFX_CONNECTOR_RF 6
+#define UDI_GFX_CONNECTOR_SCART 7
+#define UDI_GFX_CONNECTOR_COMPOSITE 8
+
+/**
+ * Enumeration: UDI_GFX_OPERATOR
+ * Lists the display output operator
+ *
+ * a1/a2/a3 represents taking the output of a previous operation
+ * v1/v2/v3 represents the literal value of that argument
+ */
+#define UDI_GFX_OPERATOR_RGB 0 // output = (color) red(a1) + green(a2) + blue(a3) (each component is UDI_GFX_PROP_COLOR_BITS
+#define UDI_GFX_OPERATOR_YUV 1 // output = (color) Y(a1) + U(a2) + V(a3)
+#define UDI_GFX_OPERATOR_YIQ 2 // output = (color) Y(a1) + I(a2) + Q(a3)
+#define UDI_GFX_OPERATOR_I 3 // output = (color) intensity(a1)
+#define UDI_GFX_OPERATOR_ALPHA 4 // output = (color) a1 + alpha(a2)
+#define UDI_GFX_OPERATOR_ADD 5 // output = a1 + a2 + v3
+#define UDI_GFX_OPERATOR_SUB 6 // output = a1 - a2 - v3
+#define UDI_GFX_OPERATOR_MUL 7 // output = a1 * a2
+#define UDI_GFX_OPERATOR_DIV 8 // output = a1 / a2
+#define UDI_GFX_OPERATOR_MAD 9 // output = a1 * a2 + a3
+#define UDI_GFX_OPERATOR_FRC 10 // output = (a1 * a2) / a3
+#define UDI_GFX_OPERATOR_SHR 11 // output = a1 >> (a2 + v3)
+#define UDI_GFX_OPERATOR_SHL 12 // output = a1 << (a2 + v3)
+#define UDI_GFX_OPERATOR_ROR 13 // output = a1 >> a2 (over a3 bits)
+#define UDI_GFX_OPERATOR_ROL 14 // output = a1 << a2 (over a3 bits)
+#define UDI_GFX_OPERATOR_SAR 15 // output = a1 >> a2 (width is a3 bits, i.e. empties are filled with bit a3-1)
+#define UDI_GFX_OPERATOR_SAL 16 // output = a1 <<< (a2 + v3) (empties filled with bit 0)
+#define UDI_GFX_OPERATOR_AND 17 // output = a1 & a2
+#define UDI_GFX_OPERATOR_OR 18 // output = a1 | a2 | v3
+#define UDI_GFX_OPERATOR_NOT 19 // output = ~a1
+#define UDI_GFX_OPERATOR_XOR 20 // output = a1 ^ a2 ^ v3
+#define UDI_GFX_OPERATOR_NEG 21 // output = -a1
+#define UDI_GFX_OPERATOR_SEG 22 // output = (a1 >> v2) & (2**v3-1) (select v3 bits starting from bit v2)
+#define UDI_GFX_OPERATOR_RANGE 23 // output = (a1 > a2) ? a2 : ((a1 < a3) ? a3 : a1)
+#define UDI_GFX_OPERATOR_CONST 24 // output = v1
+#define UDI_GFX_OPERATOR_ATTR 25 // output = property[a1 + v2]
+#define UDI_GFX_OPERATOR_SWITCH 26 // output = output[(a1 % v3) + v2]
+#define UDI_GFX_OPERATOR_BUFFER 27 // output = buffer[a1][a2] (buffer is v3 bits per entry)
+#define UDI_GFX_OPERATOR_X 28 // output = output x pixel
+#define UDI_GFX_OPERATOR_Y 29 // output = output y pixel
+#define UDI_GFX_OPERATOR_TX 30 // output = horizontal tile index belonging to output pixel
+#define UDI_GFX_OPERATOR_TY 31 // output = vertical tile index belonging to output pixel
+#define UDI_GFX_OPERATOR_TXOFF 32 // output = horizontal offset from start of tile
+#define UDI_GFX_OPERATOR_TYOFF 33 // output = vertical offset from start of tile
+#define UDI_GFX_OPERATOR_INPUT 34 // output = input engine[x][y] component v1
+#define UDI_GFX_OPERATOR_DINPUT 35 // output = input engine[a1][a2] component v3
+
+
+
+// Constant: UDI_GFX_PROVIDER_OPS_NUM
+// the ops number used for the graphics driver
+#define UDI_GFX_PROVIDER_OPS_NUM 1
+
+// Constant: UDI_GFX_CLIENT_OPS_NUM
+// the ops number used for the graphics application
+#define UDI_GFX_CLIENT_OPS_NUM 2
+
+// Structure: udi_gfx_bind_cb_t
+// Contains the operations of a driver binding request
+typedef struct {
+ // Variable: gcb
+ // The main control block
+ udi_cb_t gcb;
+} udi_gfx_bind_cb_t;
+#define UDI_GFX_BIND_CB_NUM 1
+
+// Function: udi_block_bind_req
+// function pointer prototype for connecting to a block device
+//
+// in:
+// cb - A pointer to a <udi_block_bind_cb_t>
+//
+typedef void udi_gfx_bind_req_op_t (udi_gfx_bind_cb_t *cb );
+udi_gfx_bind_req_op_t udi_gfx_bind_req;
+
+// Function: udi_gfx_bind_ack
+// function pointer prototype for acknowledging a connection request
+//
+// in:
+// cb - A pointer to a <udi_gfx_bind_cb_t>
+// sockets - The number of addressable socket components
+// engines - The number of addressable engine components
+// status - The result of the bind operation
+//
+typedef void udi_gfx_bind_ack_op_t (udi_gfx_bind_cb_t *cb, udi_index_t sockets, udi_index_t engines, udi_status_t status );
+udi_gfx_bind_ack_op_t udi_gfx_bind_ack;
+
+// Function: udi_gfx_unbind_req
+// function pointer prototype for disconnecting a block device
+//
+// in:
+// cb - A pointer to a <udi_block_bind_cb_t>
+//
+typedef void udi_gfx_unbind_req_op_t (udi_gfx_bind_cb_t *cb );
+udi_gfx_unbind_req_op_t udi_gfx_unbind_req;
+
+// Function: udi_gfx_unbind_ack
+// function pointer prototype for connecting to a block device
+//
+// in:
+// cb - A pointer to a <udi_gfx_bind_cb_t>
+//
+typedef void udi_gfx_unbind_ack_op_t (udi_gfx_bind_cb_t *cb );
+udi_gfx_unbind_ack_op_t udi_gfx_unbind_ack;
+
+// Structure: udi_gfx_state_cb_t
+// Contains the operations of a read/write transaction
+typedef struct {
+ // Variable: gcb
+ // The main control block
+ udi_cb_t gcb;
+ udi_ubit32_t subsystem;
+ udi_ubit32_t attribute;
+} udi_gfx_state_cb_t;
+#define UDI_GFX_STATE_CB_NUM 2
+
+// Function: udi_gfx_set_engine_req
+// function pointer prototype for setting an engine state
+//
+// in:
+// cb - A pointer to a <udi_gfx_state_cb_t>
+//
+typedef void udi_gfx_set_engine_req_op_t (udi_gfx_state_cb_t *cb, udi_ubit32_t value);
+udi_gfx_set_engine_req_op_t udi_gfx_set_engine_req;
+
+// Function: udi_gfx_set_connector_req
+// function pointer prototype for setting an connector state
+//
+// in:
+// cb - A pointer to a <udi_gfx_state_cb_t>
+//
+typedef void udi_gfx_set_connector_req_op_t (udi_gfx_state_cb_t *cb, udi_ubit32_t value);
+udi_gfx_set_connector_req_op_t udi_gfx_set_connector_req;
+
+// Function: udi_gfx_set_engine_ack
+// function pointer prototype for setting an engine state
+//
+// in:
+// cb - A pointer to a <udi_gfx_state_cb_t>
+//
+typedef void udi_gfx_set_engine_ack_op_t (udi_gfx_state_cb_t *cb );
+udi_gfx_set_engine_ack_op_t udi_gfx_set_engine_ack;
+
+// Function: udi_gfx_set_connector_ack
+// function pointer prototype for setting an engine state
+//
+// in:
+// cb - A pointer to a <udi_gfx_state_cb_t>
+//
+typedef void udi_gfx_set_connector_ack_op_t (udi_gfx_state_cb_t *cb );
+udi_gfx_set_connector_ack_op_t udi_gfx_set_connector_ack;
+
+// Function: udi_gfx_get_engine_req
+// function pointer prototype for setting an engine state
+//
+// in:
+// cb - A pointer to a <udi_gfx_state_cb_t>
+//
+typedef void udi_gfx_get_engine_req_op_t (udi_gfx_state_cb_t *cb );
+udi_gfx_get_engine_req_op_t udi_gfx_get_engine_req;
+
+// Function: udi_gfx_get_connector_req
+// function pointer prototype for setting an connector state
+//
+// in:
+// cb - A pointer to a <udi_gfx_state_cb_t>
+//
+typedef void udi_gfx_get_connector_req_op_t (udi_gfx_state_cb_t *cb );
+udi_gfx_get_connector_req_op_t udi_gfx_get_connector_req;
+
+// Function: udi_gfx_get_engine_ack
+// function pointer prototype for setting an engine state
+//
+// in:
+// cb - A pointer to a <udi_gfx_state_cb_t>
+//
+typedef void udi_gfx_get_engine_ack_op_t (udi_gfx_state_cb_t *cb, udi_ubit32_t value);
+udi_gfx_get_engine_ack_op_t udi_gfx_get_engine_ack;
+
+// Function: udi_gfx_get_connector_ack
+// function pointer prototype for setting an engine state
+//
+// in:
+// cb - A pointer to a <udi_gfx_state_cb_t>
+//
+typedef void udi_gfx_get_connector_ack_op_t (udi_gfx_state_cb_t *cb, udi_ubit32_t value);
+udi_gfx_get_connector_ack_op_t udi_gfx_get_connector_ack;
+
+
+// Structure: udi_gfx_range_cb_t
+// Contains the operations of a range request transaction
+typedef struct {
+ // Variable: gcb
+ // The main control block
+ udi_cb_t gcb;
+ udi_ubit32_t subsystem;
+ udi_ubit32_t attribute;
+ udi_buf_t * rangedata;
+} udi_gfx_range_cb_t;
+#define UDI_GFX_RANGE_CB_NUM 3
+
+// Function: udi_gfx_range_engine_req
+// function pointer prototype for getting an engine property range
+//
+// in:
+// cb - A pointer to a <udi_gfx_range_cb_t>
+//
+typedef void udi_gfx_range_engine_req_op_t (udi_gfx_range_cb_t *cb );
+udi_gfx_range_engine_req_op_t udi_gfx_range_engine_req;
+
+// Function: udi_gfx_range_connector_req
+// function pointer prototype for getting a connector property range
+//
+// in:
+// cb - A pointer to a <udi_gfx_range_cb_t>
+//
+typedef void udi_gfx_range_connector_req_op_t (udi_gfx_range_cb_t *cb );
+udi_gfx_range_connector_req_op_t udi_gfx_range_connector_req;
+
+// Function: udi_gfx_range_engine_ack
+// function pointer prototype for replying an engine property range
+//
+// in:
+// cb - A pointer to a <udi_gfx_range_cb_t>
+//
+typedef void udi_gfx_range_engine_ack_op_t (udi_gfx_range_cb_t *cb );
+udi_gfx_range_engine_ack_op_t udi_gfx_range_engine_ack;
+
+// Function: udi_gfx_range_connector_ack
+// function pointer prototype for replying a connector property range
+//
+// in:
+// cb - A pointer to a <udi_gfx_range_cb_t>
+//
+typedef void udi_gfx_range_connector_ack_op_t (udi_gfx_range_cb_t *cb );
+udi_gfx_range_connector_ack_op_t udi_gfx_range_connector_ack;
+
+
+// Structure: udi_gfx_command_cb_t
+// Contains the operations of a command sequence
+typedef struct {
+ // Variable: gcb
+ // The main control block
+ udi_cb_t gcb;
+ udi_buf_t * commanddata;
+} udi_gfx_command_cb_t;
+#define UDI_GFX_COMMAND_CB_NUM 4
+
+// Function: udi_gfx_command
+// function pointer prototype for sending command data
+//
+// in:
+// cb - A pointer to a <udi_gfx_command_cb_t>
+//
+typedef void udi_gfx_command_req_op_t (udi_gfx_command_cb_t *cb );
+udi_gfx_command_req_op_t udi_gfx_command_req;
+
+// Function: udi_gfx_command_ack
+// function pointer prototype for sending command data
+//
+// in:
+// cb - A pointer to a <udi_gfx_command_cb_t>
+//
+typedef void udi_gfx_command_ack_op_t (udi_gfx_command_cb_t *cb);
+udi_gfx_command_ack_op_t udi_gfx_command_ack;
+
+/* Structure: udi_gfx_provider_ops_t
+ The graphics metalanguage e*ntry points (provider side)
+ */
+typedef const struct {
+ udi_channel_event_ind_op_t *channel_event_ind_op;
+ udi_gfx_bind_req_op_t *gfx_bind_req_op;
+ udi_gfx_unbind_req_op_t *gfx_unbind_req_op;
+ udi_gfx_set_connector_req_op_t *gfx_set_connector_req_op;
+ udi_gfx_set_engine_req_op_t *gfx_set_engine_req_op;
+ udi_gfx_get_connector_req_op_t *gfx_get_connector_req_op;
+ udi_gfx_get_engine_req_op_t *gfx_get_engine_req_op;
+ udi_gfx_range_connector_req_op_t *gfx_range_connector_req_op;
+ udi_gfx_range_engine_req_op_t *gfx_range_engine_req_op;
+ udi_gfx_command_req_op_t *gfx_command_op;
+} udi_gfx_provider_ops_t;
+
+/* Structure: udi_gfx_client_ops_t
+ * The graphics metalanguage entry points (client side)
+ */
+typedef const struct {
+ udi_channel_event_ind_op_t *channel_event_ind_op;
+ udi_gfx_bind_ack_op_t *udi_gfx_bind_ack;
+ udi_gfx_unbind_ack_op_t *udi_gfx_unbind_ack;
+ udi_gfx_set_connector_ack_op_t *udi_gfx_set_connector_ack;
+ udi_gfx_set_engine_ack_op_t *udi_gfx_set_engine_ack;
+ udi_gfx_get_connector_ack_op_t *udi_gfx_get_connector_ack;
+ udi_gfx_get_engine_ack_op_t *udi_gfx_get_engine_ack;
+ udi_gfx_range_connector_ack_op_t *udi_gfx_range_connector_ack;
+ udi_gfx_range_engine_ack_op_t *udi_gfx_range_engine_ack;
+ udi_gfx_command_ack_op_t *udi_gfx_command_ack;
+} udi_gfx_client_ops_t;
+
+
+// temporary
+#ifndef UDI_ANNOY_ME
+void EngineReturnSimpleRange (int source, int index, int prop, int first, int last, int modulus);
+void ConnectorReturnSimpleRange (int source, int index, int prop, int first, int last, int modulus);
+void EngineReturnConstantRange (int source, int index, int prop, int value);
+void ConnectorReturnConstantRange (int source, int index, int prop, int value);
+void EngineReturnBooleanRange (int source, int index, int prop, int value1, int value2);
+void ConnectorReturnBooleanRange (int source, int index, int prop, int value1, int value2);
+#endif
+
+#endif
+