X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=UDI%2Fdrivers%2Fgfx_bochs%2Fbochsga_core.c;fp=UDI%2Fdrivers%2Fgfx_bochs%2Fbochsga_core.c;h=c851b072e7a458f8c6295b3bfdde7312329942cd;hb=57ba49ade7a43d94ee2b4aa20f716df3b504c48c;hp=0000000000000000000000000000000000000000;hpb=721b84c825f9261526d7aa56f1ac812a56f8bd8f;p=tpg%2Facess2.git diff --git a/UDI/drivers/gfx_bochs/bochsga_core.c b/UDI/drivers/gfx_bochs/bochsga_core.c new file mode 100644 index 00000000..c851b072 --- /dev/null +++ b/UDI/drivers/gfx_bochs/bochsga_core.c @@ -0,0 +1,472 @@ +/* + * UDI Bochs Graphics Driver + * By John Hodge (thePowersGang) + * + * bochsga_core.c + * - Core Code + */ +#define UDI_VERSION 0x101 +#define UDI_GFX_VERSION 0x101 +#include +#include +#include +#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, +};