8f6dae8dafc1714f4c1702bdf123466ad5206f17
[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 #define UDI_PCI_VERSION 0x101
12 #include <udi.h>
13 #include <udi_physio.h>
14 #include <udi_gfx.h>
15 #include <udi_pci.h>
16 #define DEBUG_ENABLED   1
17 #include "../helpers.h"
18 #include "../helpers_gfx.h"
19 #include "bochsga_common.h"
20
21 /* --- Management Metalang -- */
22 void bochsga_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level)
23 {
24         //rdata_t       *rdata = UDI_GCB(cb)->context;
25         /*udi_trace_write(rdata->init_context, UDI_TREVENT_LOCAL_PROC_ENTRY, 0, );*/
26
27         /* TODO: Set up region data */
28
29         udi_usage_res(cb);
30 }
31
32 void bochsga_enumerate_req(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level)
33 {
34         //rdata_t       *rdata = UDI_GCB(cb)->context;
35         udi_instance_attr_list_t *attr_list = cb->attr_list;
36         
37         switch(enumeration_level)
38         {
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);
43                 break;
44         case UDI_ENUMERATE_NEXT:
45                 udi_enumerate_ack(cb, UDI_ENUMERATE_DONE, 0);
46                 break;
47         }
48 }
49 void bochsga_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID)
50 {
51 }
52 void bochsga_final_cleanup_req(udi_mgmt_cb_t *cb)
53 {
54 }
55 /* --- */
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);
61
62 void bochsga_bus_dev_channel_event_ind(udi_channel_event_cb_t *cb)
63 {
64         udi_cb_t        *gcb = UDI_GCB(cb);
65         rdata_t *rdata = gcb->context;
66         
67         switch(cb->event)
68         {
69         case UDI_CHANNEL_CLOSED:
70                 break;
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
76                 return; }
77         }
78 }
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)
81 {
82         udi_cb_t        *gcb = UDI_GCB(cb);
83         rdata_t *rdata = gcb->context;
84         
85         /* Set up PIO handles */
86         rdata->init.pio_index = -1;
87         bochsga_bus_dev_bind__pio_map(gcb, UDI_NULL_PIO_HANDLE);
88         /* V V V V */
89 }
90 void bochsga_bus_dev_bind__pio_map(udi_cb_t *gcb, udi_pio_handle_t new_pio_handle)
91 {
92         rdata_t *rdata = gcb->context;
93         if( rdata->init.pio_index != (udi_index_t)-1 )
94         {
95                 rdata->pio_handles[rdata->init.pio_index] = new_pio_handle;
96         }
97         
98         rdata->init.pio_index ++;
99         if( rdata->init.pio_index < N_PIO )
100         {
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
106                         );
107                 return ;
108         }
109         
110         udi_channel_event_complete( UDI_MCB(rdata->active_cb, udi_channel_event_cb_t), UDI_OK);
111         // = = = = =
112 }
113 void bochsga_bus_dev_bus_unbind_ack(udi_bus_bind_cb_t *cb)
114 {
115 }
116 void bochsga_bus_dev_intr_attach_ack(udi_intr_attach_cb_t *intr_attach_cb, udi_status_t status)
117 {
118 }
119 void bochsga_bus_dev_intr_detach_ack(udi_intr_detach_cb_t *intr_detach_cb)
120 {
121 }
122
123 /* ---  GFX Provider ops -- */
124 void bochsga_gfx_channel_event_ind(udi_channel_event_cb_t *cb)
125 {
126         /* No operation */
127 }
128 void bochsga_gfx_bind_req(udi_gfx_bind_cb_t *cb)
129 {
130         /* TODO: ACK bind if nothing already bound */
131 }
132 void bochsga_gfx_unbind_req(udi_gfx_bind_cb_t *cb)
133 {
134         /* TODO: Release internal state? */
135 }
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)
137 {
138         udi_gfx_state_cb_t *cb = UDI_MCB(gcb, udi_gfx_state_cb_t);
139         udi_gfx_set_connector_ack(cb);
140 }
141 void bochsga_gfx_set_connector_req(udi_gfx_state_cb_t *cb, udi_ubit32_t value)
142 {
143         udi_cb_t        *gcb = UDI_GCB(cb);
144         rdata_t *rdata = gcb->context;
145         
146         switch(cb->attribute)
147         {
148         case UDI_GFX_PROP_ENABLE:
149                 if( rdata->output_enable != !!value )
150                 {
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);
154                         return ;
155                 }
156                 udi_gfx_set_connector_ack(cb);
157                 return;
158         /* Change input engine */
159         case UDI_GFX_PROP_INPUT:
160                 udi_gfx_set_connector_ack(cb);
161                 return;
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 */
166                         return ;
167                 }
168                 if( !(320 <= value && value <= rdata->limits.max_width) ) {
169                         return ;
170                 } 
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);
174                 return;
175         case UDI_GFX_PROP_HEIGHT:
176                 if( !(240 <= value && value <= rdata->limits.max_height) ) {
177                         return ;
178                 } 
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);
182                 return;
183         }
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)
187                 );
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*/);
190 }
191 void bochsga_gfx_get_connector_req(udi_gfx_state_cb_t *cb)
192 {
193         udi_cb_t        *gcb = UDI_GCB(cb);
194         rdata_t *rdata = gcb->context;
195         
196         switch(cb->attribute)
197         {
198         case UDI_GFX_PROP_ENABLE:
199                 udi_gfx_get_connector_ack(cb, !!rdata->output_enable);
200                 return;
201         case UDI_GFX_PROP_INPUT:
202                 udi_gfx_get_connector_ack(cb, 0);
203                 return;
204         case UDI_GFX_PROP_WIDTH:
205                 udi_gfx_get_connector_ack(cb, rdata->outputstate.width);
206                 return;
207         case UDI_GFX_PROP_HEIGHT:
208                 udi_gfx_get_connector_ack(cb, rdata->outputstate.height);
209                 return;
210         case UDI_GFX_PROP_CONNECTOR_TYPE:
211                 udi_gfx_get_connector_ack(cb, UDI_GFX_CONNECTOR_HIDDEN);
212                 return;
213         case UDI_GFX_PROP_SIGNAL:
214                 udi_gfx_get_connector_ack(cb, UDI_GFX_SIGNAL_INTEGRATED);
215                 return;
216         }
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)
220                 );
221         udi_gfx_state_cb_t      *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
222         udi_gfx_get_connector_ack(cb, 0);
223 }
224 void bochsga_gfx_range_connector_req(udi_gfx_range_cb_t *cb)
225 {
226         udi_cb_t        *gcb = UDI_GCB(cb);
227         rdata_t *rdata = gcb->context;
228         
229         switch(cb->attribute)
230         {
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);
234                 return;
235         case UDI_GFX_PROP_INPUT:
236                 /* Fix 0 */
237                 gfxhelpers_return_range_fixed(udi_gfx_range_connector_ack, cb, 0);
238                 return;
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);
243                 return;
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);
248                 return;
249         case UDI_GFX_PROP_CONNECTOR_TYPE:
250                 gfxhelpers_return_range_fixed(udi_gfx_range_connector_ack, cb, UDI_GFX_CONNECTOR_HIDDEN);
251                 return;
252         case UDI_GFX_PROP_SIGNAL:
253                 gfxhelpers_return_range_fixed(udi_gfx_range_connector_ack, cb, UDI_GFX_SIGNAL_INTEGRATED);
254                 return;
255         }
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)
259                 );
260         udi_gfx_range_cb_t      *cb = UDI_MCB(cb, udi_gfx_range_cb_t);
261         udi_gfx_range_connector_ack(cb);
262 }
263
264 /* --- Engine Manipulation --- */
265 void bochsga_gfx_set_engine_req(udi_gfx_state_cb_t *cb, udi_ubit32_t value)
266 {
267         udi_cb_t        *gcb = UDI_GCB(cb);
268         rdata_t *rdata = gcb->context;
269         
270         if( cb->subsystem >= N_ENGINES ) {
271                 udi_gfx_get_engine_ack(cb, 0);
272                 return;
273         }
274         
275         engine_t *engine = &rdata->engines[cb->subsystem];
276         
277         switch(cb->attribute)
278         {
279         case UDI_GFX_PROP_WIDTH:
280                 engine->width = value;
281                 udi_gfx_set_engine_ack(cb);
282                 return;
283         case UDI_GFX_PROP_HEIGHT:
284                 engine->height = value;
285                 udi_gfx_set_engine_ack(cb);
286                 return;
287         }
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)
291                 );
292         udi_gfx_state_cb_t      *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
293         udi_gfx_set_engine_ack(cb);
294 }
295 void bochsga_gfx_get_engine_req(udi_gfx_state_cb_t *cb)
296 {
297         udi_cb_t        *gcb = UDI_GCB(cb);
298         rdata_t *rdata = gcb->context;
299         
300         if( cb->subsystem >= N_ENGINES ) {
301                 udi_gfx_get_engine_ack(cb, 0);
302                 return;
303         }
304         
305         const engine_t *engine = &rdata->engines[cb->subsystem];
306         
307         switch(cb->attribute)
308         {
309         case UDI_GFX_PROP_ENABLE:
310                 udi_gfx_get_engine_ack(cb, 1);
311                 return;
312         
313         case UDI_GFX_PROP_INPUT:
314                 udi_gfx_get_engine_ack(cb, -1);
315                 return;
316         
317         case UDI_GFX_PROP_WIDTH:
318                 udi_gfx_get_engine_ack(cb, engine->width);
319                 return;
320         case UDI_GFX_PROP_HEIGHT:
321                 udi_gfx_get_engine_ack(cb, engine->height);
322                 return;
323         
324         case UDI_GFX_PROP_STOCK_FORMAT:
325                 udi_gfx_get_engine_ack(cb, UDI_GFX_STOCK_FORMAT_R8G8B8);
326                 return;
327         }
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)
331                 );
332         udi_gfx_state_cb_t      *cb = UDI_MCB(cb, udi_gfx_state_cb_t);
333         udi_gfx_get_engine_ack(cb, 0);
334 }
335 void bochsga_gfx_range_engine_req(udi_gfx_range_cb_t *cb)
336 {
337         udi_cb_t        *gcb = UDI_GCB(cb);
338         rdata_t *rdata = gcb->context;
339         (void)rdata;
340         
341         if( cb->subsystem >= N_ENGINES ) {
342                 udi_gfx_range_engine_ack(cb);
343                 return;
344         }
345         
346         //engine_t *engine = &rdata->engines[cb->subsystem];
347         
348         switch(cb->attribute)
349         {
350         case UDI_GFX_PROP_ENABLE:
351                 gfxhelpers_return_range_fixed(udi_gfx_range_engine_ack, cb, 1);
352                 return;
353         case UDI_GFX_PROP_INPUT:
354                 gfxhelpers_return_range_fixed(udi_gfx_range_engine_ack, cb, -1);
355                 return;
356         
357         case UDI_GFX_PROP_STOCK_FORMAT:
358                 gfxhelpers_return_range_fixed(udi_gfx_range_engine_ack, cb, UDI_GFX_STOCK_FORMAT_B8G8R8);
359                 return;
360         }
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)
364                 );
365         udi_gfx_range_cb_t *cb = UDI_MCB(cb, udi_gfx_range_cb_t);
366         udi_gfx_range_engine_ack( cb );
367 }
368 void bochsga_gfx_get_engine_operator_req(udi_gfx_range_cb_t *cb)
369 {
370         /* TODO: Get Engine operator */
371         udi_gfx_get_engine_operator_ack(cb, 0, 0,0,0);
372 }
373 void bochsga_gfx_connector_command_req(udi_gfx_command_cb_t *cb)
374 {
375         /* Need to parse the GLX stream */
376         udi_gfx_connector_command_ack(cb);
377 }
378 void bochsga_gfx_engine_command_req(udi_gfx_command_cb_t *cb)
379 {
380         /* Need to parse the GLX stream */
381         udi_gfx_engine_command_ack(cb);
382 }
383 void bochsga_gfx_buffer_info_req(udi_gfx_buffer_info_cb_t *cb)
384 {
385         switch(cb->buffer_index)
386         {
387         case 0:
388                 udi_gfx_buffer_info_ack(cb, 1024, 768, 24, 0);
389                 return;
390         default:
391                 break;
392         }
393         CONTIN(bochsga_gfx_buffer_info_req, udi_log_write,
394                 (UDI_TREVENT_LOG, UDI_LOG_INFORMATION, BOCHSGA_OPS_GFX, 0, BOCHSGA_MSGNUM_BUFUNK, __func__, cb->buffer_index),
395                 (udi_status_t status)
396                 );
397         udi_gfx_buffer_info_cb_t *cb = UDI_MCB(gcb, udi_gfx_buffer_info_cb_t);
398         udi_gfx_buffer_info_ack(cb, 0,0,0,0);
399 }
400 void bochsga_gfx_buffer_write_req(udi_gfx_buffer_cb_t *cb)
401 {
402 }
403 void bochsga_gfx_buffer_read_req(udi_gfx_buffer_cb_t *cb)
404 {
405 }
406
407 /*
408 ====================================================================
409 Management ops
410 ====================================================================
411 */
412 udi_mgmt_ops_t  bochsga_mgmt_ops = {
413         bochsga_usage_ind,
414         bochsga_enumerate_req,
415         bochsga_devmgmt_req,
416         bochsga_final_cleanup_req
417 };
418 udi_ubit8_t     bochsga_mgmt_op_flags[4] = {0,0,0,0};
419 /* - Bus Ops */
420 udi_bus_device_ops_t    bochsga_bus_dev_ops = {
421         bochsga_bus_dev_channel_event_ind,
422         bochsga_bus_dev_bus_bind_ack,
423         bochsga_bus_dev_bus_unbind_ack,
424         bochsga_bus_dev_intr_attach_ack,
425         bochsga_bus_dev_intr_detach_ack
426 };
427 udi_ubit8_t     bochsga_bus_dev_ops_flags[5] = {0};
428 /* - GFX provider ops */
429 udi_gfx_provider_ops_t  bochsga_gfx_ops = {
430         bochsga_gfx_channel_event_ind,
431         bochsga_gfx_bind_req,
432         bochsga_gfx_unbind_req,
433         bochsga_gfx_set_connector_req,
434         bochsga_gfx_set_engine_req,
435         bochsga_gfx_get_connector_req,
436         bochsga_gfx_get_engine_req,
437         bochsga_gfx_range_connector_req,
438         bochsga_gfx_range_engine_req,
439         bochsga_gfx_get_engine_operator_req,
440         bochsga_gfx_connector_command_req,
441         bochsga_gfx_engine_command_req,
442         bochsga_gfx_buffer_info_req,
443         bochsga_gfx_buffer_read_req,
444         bochsga_gfx_buffer_write_req,
445 };
446 udi_ubit8_t     bochsga_gfx_ops_flags[10] = {0};
447 /* -- */
448 udi_primary_init_t      bochsga_pri_init = {
449         .mgmt_ops = &bochsga_mgmt_ops,
450         .mgmt_op_flags = bochsga_mgmt_op_flags,
451         .mgmt_scratch_requirement = 0,
452         .enumeration_attr_list_length = 0,
453         .rdata_size = sizeof(rdata_t),
454         .child_data_size = 0,
455         .per_parent_paths = 0
456 };
457 udi_ops_init_t  bochsga_ops_list[] = {
458         {
459                 BOCHSGA_OPS_DEV, BOCHSGA_META_BUS, UDI_BUS_DEVICE_OPS_NUM,
460                 0,
461                 (udi_ops_vector_t*)&bochsga_bus_dev_ops,
462                 bochsga_bus_dev_ops_flags
463         },
464         {
465                 BOCHSGA_OPS_GFX, BOCHSGA_META_GFX, UDI_GFX_PROVIDER_OPS_NUM,
466                 0,
467                 (udi_ops_vector_t*)&bochsga_gfx_ops,
468                 bochsga_gfx_ops_flags
469         },
470         {0}
471 };
472 udi_cb_init_t bochsga_cb_init_list[] = {
473         {BOCHSGA_CB_BUS_BIND,    BOCHSGA_META_BUS, UDI_BUS_BIND_CB_NUM, 0, 0,NULL},
474         {BOCHSGA_CB_GFX_BIND,    BOCHSGA_META_GFX, UDI_GFX_BIND_CB_NUM, 0, 0,NULL},
475         {BOCHSGA_CB_GFX_STATE,   BOCHSGA_META_GFX, UDI_GFX_STATE_CB_NUM, 0, 0,NULL},
476         {BOCHSGA_CB_GFX_RANGE,   BOCHSGA_META_GFX, UDI_GFX_RANGE_CB_NUM, 0, 0,NULL},
477         {BOCHSGA_CB_GFX_COMMAND, BOCHSGA_META_GFX, UDI_GFX_COMMAND_CB_NUM, 0, 0,NULL},
478         {0}
479 };
480 const udi_init_t        udi_init_info = {
481         .primary_init_info = &bochsga_pri_init,
482         .ops_init_list = bochsga_ops_list,
483         .cb_init_list = bochsga_cb_init_list,
484 };

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