UDI - Added checks on UDI_[NIC|PHYSIO]_VERSION
[tpg/acess2.git] / UDI / drivers / gfx_bochs / bochsga_core.c
1 /*
2  * UDI Bochs Graphics Driver
3  * By John Hodge (thePowersGang)
4  *
5  * bochsga_core.c
6  * - Core Code
7  */
8 #define UDI_VERSION     0x101
9 #define UDI_PHYSIO_VERSION      0x101
10 #define UDI_GFX_VERSION 0x101
11 #include <udi.h>
12 #include <udi_physio.h>
13 #include <udi_gfx.h>
14 #define DEBUG_ENABLED   1
15 #include "../helpers.h"
16 #include "../helpers_gfx.h"
17 #include "bochsga_common.h"
18
19 // --- Management Metalang
20 void bochsga_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level)
21 {
22         rdata_t *rdata = UDI_GCB(cb)->context;
23         //udi_trace_write(rdata->init_context, UDI_TREVENT_LOCAL_PROC_ENTRY, 0, );
24
25         // TODO: Set up region data     
26
27         udi_usage_res(cb);
28 }
29
30 void bochsga_enumerate_req(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level)
31 {
32         rdata_t *rdata = UDI_GCB(cb)->context;
33         udi_instance_attr_list_t *attr_list = cb->attr_list;
34         
35         switch(enumeration_level)
36         {
37         case UDI_ENUMERATE_START:
38         case UDI_ENUMERATE_START_RESCAN:
39                 cb->attr_valid_length = attr_list - cb->attr_list;
40                 udi_enumerate_ack(cb, UDI_ENUMERATE_OK, BOCHSGA_OPS_GFX);
41                 break;
42         case UDI_ENUMERATE_NEXT:
43                 udi_enumerate_ack(cb, UDI_ENUMERATE_DONE, 0);
44                 break;
45         }
46 }
47 void bochsga_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID)
48 {
49 }
50 void bochsga_final_cleanup_req(udi_mgmt_cb_t *cb)
51 {
52 }
53 // ---
54 void bochsga_bus_dev_channel_event_ind(udi_channel_event_cb_t *cb);
55 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);
56 void bochsga_bus_dev_bind__pio_map(udi_cb_t *cb, udi_pio_handle_t new_pio_handle);
57 void bochsga_bus_dev_bind__intr_chanel(udi_cb_t *gcb, udi_channel_t new_channel);
58 void bochsga_bus_dev_bus_unbind_ack(udi_bus_bind_cb_t *cb);
59
60 void bochsga_bus_dev_channel_event_ind(udi_channel_event_cb_t *cb)
61 {
62         udi_cb_t        *gcb = UDI_GCB(cb);
63         rdata_t *rdata = gcb->context;
64         
65         switch(cb->event)
66         {
67         case UDI_CHANNEL_CLOSED:
68                 break;
69         case UDI_CHANNEL_BOUND: {
70                 rdata->active_cb = gcb;
71                 udi_bus_bind_cb_t *bus_bind_cb = UDI_MCB(cb->params.parent_bound.bind_cb, udi_bus_bind_cb_t);
72                 udi_bus_bind_req( bus_bind_cb );
73                 // continue at bochsga_bus_dev_bus_bind_ack
74                 return; }
75         }
76 }
77 void bochsga_bus_dev_bus_bind_ack(udi_bus_bind_cb_t *cb,
78         udi_dma_constraints_t dma_constraints, udi_ubit8_t perferred_endianness, udi_status_t status)
79 {
80         udi_cb_t        *gcb = UDI_GCB(cb);
81         rdata_t *rdata = gcb->context;
82         
83         // Set up PIO handles
84         rdata->init.pio_index = -1;
85         bochsga_bus_dev_bind__pio_map(gcb, UDI_NULL_PIO_HANDLE);
86         // V V V V
87 }
88 void bochsga_bus_dev_bind__pio_map(udi_cb_t *gcb, udi_pio_handle_t new_pio_handle)
89 {
90         rdata_t *rdata = gcb->context;
91         if( rdata->init.pio_index != -1 )
92         {
93                 rdata->pio_handles[rdata->init.pio_index] = new_pio_handle;
94         }
95         
96         rdata->init.pio_index ++;
97         if( rdata->init.pio_index < N_PIO )
98         {
99                 const struct s_pio_ops  *ops = &bochsga_pio_ops[rdata->init.pio_index];
100                 udi_pio_map(bochsga_bus_dev_bind__pio_map, gcb,
101                         ops->regset_idx, ops->base_offset, ops->length,
102                         ops->trans_list, ops->list_length,
103                         UDI_PIO_LITTLE_ENDIAN, 0, 0
104                         );
105                 return ;
106         }
107         
108         udi_channel_event_complete( UDI_MCB(rdata->active_cb, udi_channel_event_cb_t), UDI_OK);
109         // = = = = =
110 }
111 void bochsga_bus_dev_bus_unbind_ack(udi_bus_bind_cb_t *cb)
112 {
113 }
114 void bochsga_bus_dev_intr_attach_ack(udi_intr_attach_cb_t *intr_attach_cb, udi_status_t status)
115 {
116 }
117 void bochsga_bus_dev_intr_detach_ack(udi_intr_detach_cb_t *intr_detach_cb)
118 {
119 }
120 // ---
121 // GFX Provider ops
122 void bochsga_gfx_channel_event_ind(udi_channel_event_cb_t *cb)
123 {
124         // No operation
125 }
126 void bochsga_gfx_bind_req(udi_gfx_bind_cb_t *cb)
127 {
128         // TODO: ACK bind if nothing already bound
129 }
130 void bochsga_gfx_unbind_req(udi_gfx_bind_cb_t *cb)
131 {
132         // TODO: Release internal state?
133 }
134 void bochsga_gfx_set_connector_req$pio(udi_cb_t *gcb, udi_buf_t *new_buf, udi_status_t status, udi_ubit16_t result)
135 {
136         udi_gfx_state_cb_t *cb = UDI_MCB(gcb, udi_gfx_state_cb_t);
137         udi_gfx_set_connector_ack(cb);
138 }
139 void bochsga_gfx_set_connector_req(udi_gfx_state_cb_t *cb, udi_ubit32_t value)
140 {
141         udi_cb_t        *gcb = UDI_GCB(cb);
142         rdata_t *rdata = gcb->context;
143         
144         switch(cb->attribute)
145         {
146         case UDI_GFX_PROP_ENABLE:
147                 if( rdata->output_enable != !!value )
148                 {
149                         rdata->output_enable = !!value;
150                         udi_pio_trans(bochsga_gfx_set_connector_req$pio, gcb,
151                                 rdata->pio_handles[BOCHSGA_PIO_ENABLE], rdata->output_enable, NULL, &rdata->outputstate);
152                         return ;
153                 }
154                 udi_gfx_set_connector_ack(cb);
155                 return;
156         // Change input engine
157         // - 
158         case UDI_GFX_PROP_INPUT:
159                 if( rdata->outputstate.engine != value )
160                 {
161                         // Validate
162                         if( !(0 <= value && value <= N_ENGINES) ) {
163                                 udi_gfx_set_connector_ack(cb /*, UDI_STAT_NOT_SUPPORTED*/);
164                                 return ;
165                         }
166                         
167                         // Change saved bitdepth (requires cycling enable)
168                         rdata->outputstate.engine = value;
169                         rdata->outputstate.bitdepth = bochsga_engine_defs[value].bitdepth;
170                 }
171                 udi_gfx_set_connector_ack(cb);
172                 return;
173         // Alter output dimensions
174         case UDI_GFX_PROP_WIDTH:
175                 if( value % 8 != 0 ) {
176                         // Qemu doesn't like resolutions not a multiple of 8
177                         return ;
178                 }
179                 if( !(320 <= value && value <= rdata->limits.max_width) ) {
180                         return ;
181                 } 
182                 rdata->outputstate.width = value;
183                 udi_pio_trans(bochsga_gfx_set_connector_req$pio, gcb,
184                         rdata->pio_handles[BOCHSGA_PIO_ENABLE], rdata->output_enable, NULL, &rdata->outputstate);
185                 return;
186         case UDI_GFX_PROP_HEIGHT:
187                 if( !(240 <= value && value <= rdata->limits.max_height) ) {
188                         return ;
189                 } 
190                 rdata->outputstate.height = value;
191                 udi_pio_trans(bochsga_gfx_set_connector_req$pio, gcb,
192                         rdata->pio_handles[BOCHSGA_PIO_ENABLE], rdata->output_enable, NULL, &rdata->outputstate);
193                 return;
194         }
195         CONTIN(bochsga_gfx_set_connector_req, udi_log_write,
196                 (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
197                 (udi_status_t status)
198                 );
199         udi_gfx_state_cb_t      *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
200         udi_gfx_set_connector_ack(cb /*, UDI_STAT_NOT_SUPPORTED*/);
201 }
202 void bochsga_gfx_get_connector_req(udi_gfx_state_cb_t *cb)
203 {
204         udi_cb_t        *gcb = UDI_GCB(cb);
205         rdata_t *rdata = gcb->context;
206         
207         switch(cb->attribute)
208         {
209         case UDI_GFX_PROP_ENABLE:
210                 udi_gfx_get_connector_ack(cb, !!rdata->output_enable);
211                 return;
212         case UDI_GFX_PROP_INPUT:
213                 udi_gfx_get_connector_ack(cb, rdata->outputstate.bitdepth/8-1);
214                 return;
215         case UDI_GFX_PROP_WIDTH:
216                 udi_gfx_get_connector_ack(cb, rdata->outputstate.width);
217                 return;
218         case UDI_GFX_PROP_HEIGHT:
219                 udi_gfx_get_connector_ack(cb, rdata->outputstate.height);
220                 return;
221         case UDI_GFX_PROP_CONNECTOR_TYPE:
222                 udi_gfx_get_connector_ack(cb, UDI_GFX_CONNECTOR_HIDDEN);
223                 return;
224         case UDI_GFX_PROP_SIGNAL:
225                 udi_gfx_get_connector_ack(cb, UDI_GFX_SIGNAL_INTEGRATED);
226                 return;
227         }
228         CONTIN(bochsga_gfx_get_connector_req, udi_log_write,
229                 (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
230                 (udi_status_t status)
231                 );
232         udi_gfx_state_cb_t      *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
233         udi_gfx_get_connector_ack(cb, 0);
234 }
235 void bochsga_gfx_range_connector_req(udi_gfx_range_cb_t *cb)
236 {
237         udi_cb_t        *gcb = UDI_GCB(cb);
238         rdata_t *rdata = gcb->context;
239         
240         switch(cb->attribute)
241         {
242         case UDI_GFX_PROP_ENABLE:
243                 // 2 values: 0 and 1
244                 gfxhelpers_return_range_set(udi_gfx_range_connector_ack, cb, 2, 0, 1);
245                 return;
246         case UDI_GFX_PROP_INPUT:
247                 // 0--3 with a step of 1
248                 gfxhelpers_return_range_simple(udi_gfx_range_connector_ack, cb, 0, 3, 1);
249                 return;
250         case UDI_GFX_PROP_WIDTH:
251                 gfxhelpers_return_range_simple(udi_gfx_range_connector_ack, cb,
252                         BOCHSGA_MIN_WIDTH, rdata->limits.max_width, 8); // qemu restricts to 8 step
253                 return;
254         case UDI_GFX_PROP_HEIGHT:
255                 gfxhelpers_return_range_simple(udi_gfx_range_connector_ack, cb,
256                         BOCHSGA_MIN_HEIGHT, rdata->limits.max_height, 8); // step of 8 for neatness
257                 return;
258         case UDI_GFX_PROP_CONNECTOR_TYPE:
259                 gfxhelpers_return_range_fixed(udi_gfx_range_connector_ack, cb, UDI_GFX_CONNECTOR_HIDDEN);
260                 return;
261         case UDI_GFX_PROP_SIGNAL:
262                 gfxhelpers_return_range_fixed(udi_gfx_range_connector_ack, cb, UDI_GFX_SIGNAL_INTEGRATED);
263                 return;
264         }
265         CONTIN(bochsga_gfx_range_connector_req, udi_log_write,
266                 (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
267                 (udi_status_t status)
268                 );
269         udi_gfx_range_cb_t      *cb = UDI_MCB(cb, udi_gfx_range_cb_t);
270         udi_gfx_range_connector_ack(cb);
271 }
272 // --- Engine Manipulation ---
273 void bochsga_gfx_set_engine_req(udi_gfx_state_cb_t *cb, udi_ubit32_t value)
274 {
275         udi_cb_t        *gcb = UDI_GCB(cb);
276         rdata_t *rdata = gcb->context;
277         
278         if( cb->subsystem >= N_ENGINES ) {
279                 udi_gfx_get_engine_ack(cb, 0);
280                 return;
281         }
282         
283         engine_t *engine = &rdata->engines[cb->subsystem];
284         
285         switch(cb->attribute)
286         {
287         case UDI_GFX_PROP_WIDTH:
288                 engine->width = value;
289                 udi_gfx_set_engine_ack(cb);
290                 return;
291         case UDI_GFX_PROP_HEIGHT:
292                 engine->height = value;
293                 udi_gfx_set_engine_ack(cb);
294                 return;
295         case UDI_GFX_PROP_OPERATOR_INDEX:
296                 if( value >= bochsga_engine_defs[cb->subsystem].op_map.op_count ) {
297                         // Bad value
298                         udi_gfx_set_engine_ack(cb);
299                         return;
300                 }
301                 engine->op_idx = value;
302                 udi_gfx_set_engine_ack(cb);
303                 return;
304         }
305         CONTIN(bochsga_gfx_set_engine_req, udi_log_write,
306                 (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
307                 (udi_status_t status)
308                 );
309         udi_gfx_state_cb_t      *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
310         udi_gfx_set_engine_ack(cb);
311 }
312 void bochsga_gfx_get_engine_req(udi_gfx_state_cb_t *cb)
313 {
314         udi_cb_t        *gcb = UDI_GCB(cb);
315         rdata_t *rdata = gcb->context;
316         
317         if( cb->subsystem >= N_ENGINES ) {
318                 udi_gfx_get_engine_ack(cb, 0);
319                 return;
320         }
321         
322         const engine_t *engine = &rdata->engines[cb->subsystem];
323         const engine_static_t *engine_def = &bochsga_engine_defs[cb->subsystem];
324         
325         switch(cb->attribute)
326         {
327         case UDI_GFX_PROP_ENABLE:
328                 udi_gfx_get_engine_ack(cb, 1);
329                 return;
330         
331         case UDI_GFX_PROP_INPUT:
332                 udi_gfx_get_engine_ack(cb, -1);
333                 return;
334         
335         case UDI_GFX_PROP_WIDTH:
336                 udi_gfx_get_engine_ack(cb, engine->width);
337                 return;
338         case UDI_GFX_PROP_HEIGHT:
339                 udi_gfx_get_engine_ack(cb, engine->height);
340                 return;
341         
342         case UDI_GFX_PROP_OPERATOR_INDEX:
343                 udi_gfx_get_engine_ack(cb, engine->op_idx);
344                 return;
345         case UDI_GFX_PROP_OPERATOR_OPCODE:
346         case UDI_GFX_PROP_OPERATOR_ARG_1:
347         case UDI_GFX_PROP_OPERATOR_ARG_2:
348         case UDI_GFX_PROP_OPERATOR_ARG_3:
349                 udi_gfx_get_engine_ack(cb, gfxhelpers_get_engine_op(&engine_def->op_map, engine->op_idx, cb->attribute));
350                 return;
351         }
352         CONTIN(bochsga_gfx_get_engine_req, udi_log_write,
353                 (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
354                 (udi_status_t status)
355                 );
356         udi_gfx_state_cb_t      *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
357         udi_gfx_get_engine_ack(cb, 0);
358 }
359 void bochsga_gfx_range_engine_req(udi_gfx_range_cb_t *cb)
360 {
361         udi_cb_t        *gcb = UDI_GCB(cb);
362         rdata_t *rdata = gcb->context;
363         
364         if( cb->subsystem >= N_ENGINES ) {
365                 udi_gfx_range_engine_ack(cb);
366                 return;
367         }
368         
369         engine_t *engine = &rdata->engines[cb->subsystem];
370         const engine_static_t *engine_def = &bochsga_engine_defs[cb->subsystem];
371         
372         switch(cb->attribute)
373         {
374         case UDI_GFX_PROP_ENABLE:
375                 gfxhelpers_return_range_fixed(udi_gfx_range_engine_ack, cb, 1);
376                 return;
377         case UDI_GFX_PROP_INPUT:
378                 gfxhelpers_return_range_fixed(udi_gfx_range_engine_ack, cb, -1);
379                 return;
380         
381         case UDI_GFX_PROP_OPERATOR_INDEX:
382                 gfxhelpers_return_range_simple(udi_gfx_range_engine_ack, cb, 0, engine->op_idx-1, 1);
383                 return;
384         case UDI_GFX_PROP_OPERATOR_OPCODE:
385         case UDI_GFX_PROP_OPERATOR_ARG_1:
386         case UDI_GFX_PROP_OPERATOR_ARG_2:
387         case UDI_GFX_PROP_OPERATOR_ARG_3:
388                 gfxhelpers_return_range_fixed(udi_gfx_range_engine_ack, cb,
389                         gfxhelpers_get_engine_op(&engine_def->op_map, engine->op_idx, cb->attribute));
390                 return;
391         }
392         CONTIN(bochsga_gfx_range_engine_req, udi_log_write,
393                 (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_PROPUNK, __func__, cb->attribute),
394                 (udi_status_t status)
395                 );
396         udi_gfx_range_cb_t *cb = UDI_MCB(cb, udi_gfx_range_cb_t);
397         udi_gfx_range_engine_ack( cb );
398 }
399 void bochsga_gfx_command_req(udi_gfx_command_cb_t *cb)
400 {
401         // Need to parse the GLX stream
402 }
403
404 // ====================================================================
405 // - Management ops
406 udi_mgmt_ops_t  bochsga_mgmt_ops = {
407         bochsga_usage_ind,
408         bochsga_enumerate_req,
409         bochsga_devmgmt_req,
410         bochsga_final_cleanup_req
411 };
412 udi_ubit8_t     bochsga_mgmt_op_flags[4] = {0,0,0,0};
413 // - Bus Ops
414 udi_bus_device_ops_t    bochsga_bus_dev_ops = {
415         bochsga_bus_dev_channel_event_ind,
416         bochsga_bus_dev_bus_bind_ack,
417         bochsga_bus_dev_bus_unbind_ack,
418         bochsga_bus_dev_intr_attach_ack,
419         bochsga_bus_dev_intr_detach_ack
420 };
421 udi_ubit8_t     bochsga_bus_dev_ops_flags[5] = {0};
422 // - GFX provider ops
423 udi_gfx_provider_ops_t  bochsga_gfx_ops = {
424         bochsga_gfx_channel_event_ind,
425         bochsga_gfx_bind_req,
426         bochsga_gfx_unbind_req,
427         bochsga_gfx_set_connector_req,
428         bochsga_gfx_set_engine_req,
429         bochsga_gfx_get_connector_req,
430         bochsga_gfx_get_engine_req,
431         bochsga_gfx_range_connector_req,
432         bochsga_gfx_range_engine_req,
433         bochsga_gfx_command_req
434 };
435 udi_ubit8_t     bochsga_gfx_ops_flags[10] = {0};
436 // --
437 udi_primary_init_t      bochsga_pri_init = {
438         .mgmt_ops = &bochsga_mgmt_ops,
439         .mgmt_op_flags = bochsga_mgmt_op_flags,
440         .mgmt_scratch_requirement = 0,
441         .enumeration_attr_list_length = 0,
442         .rdata_size = sizeof(rdata_t),
443         .child_data_size = 0,
444         .per_parent_paths = 0
445 };
446 udi_ops_init_t  bochsga_ops_list[] = {
447         {
448                 BOCHSGA_OPS_DEV, BOCHSGA_META_BUS, UDI_BUS_DEVICE_OPS_NUM,
449                 0,
450                 (udi_ops_vector_t*)&bochsga_bus_dev_ops,
451                 bochsga_bus_dev_ops_flags
452         },
453         {
454                 BOCHSGA_OPS_GFX, BOCHSGA_META_GFX, UDI_GFX_PROVIDER_OPS_NUM,
455                 0,
456                 (udi_ops_vector_t*)&bochsga_gfx_ops,
457                 bochsga_gfx_ops_flags
458         },
459         {0}
460 };
461 udi_cb_init_t bochsga_cb_init_list[] = {
462         {BOCHSGA_CB_BUS_BIND,    BOCHSGA_META_BUS, UDI_BUS_BIND_CB_NUM, 0, 0,NULL},
463         {BOCHSGA_CB_GFX_BIND,    BOCHSGA_META_GFX, UDI_GFX_BIND_CB_NUM, 0, 0,NULL},
464         {BOCHSGA_CB_GFX_STATE,   BOCHSGA_META_GFX, UDI_GFX_STATE_CB_NUM, 0, 0,NULL},
465         {BOCHSGA_CB_GFX_RANGE,   BOCHSGA_META_GFX, UDI_GFX_RANGE_CB_NUM, 0, 0,NULL},
466         {BOCHSGA_CB_GFX_COMMAND, BOCHSGA_META_GFX, UDI_GFX_COMMAND_CB_NUM, 0, 0,NULL},
467         {0}
468 };
469 const udi_init_t        udi_init_info = {
470         .primary_init_info = &bochsga_pri_init,
471         .ops_init_list = bochsga_ops_list,
472         .cb_init_list = bochsga_cb_init_list,
473 };

UCC git Repository :: git.ucc.asn.au