Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Convert shadow paging to use 32 PAE (Remove 32 Bit Restrictions)
[palacios.git] / palacios / src / devices / cirrus_gfx_card.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2009, Robert Deloatch <rtdeloatch@gmail.com>
11  * Copyright (c) 2009, Steven Jaconette <stevenjaconette2007@u.northwestern.edu> 
12  * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org> 
13  * All rights reserved.
14  *
15  * Author: Robdert Deloatch <rtdeloatch@gmail.com>
16  *         Steven Jaconette <stevenjaconette2007@u.northwestern.edu>
17  *
18  * This is free software.  You are permitted to use,
19  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20  */
21
22 #include <devices/cirrus_gfx_card.h>
23 #include <palacios/vmm.h>
24 #include <palacios/vmm_emulator.h>
25 #include <palacios/vmm_decoder.h>
26 #include <palacios/vm_guest_mem.h>
27 #include <palacios/vmm_decoder.h>
28 #include <palacios/vmm_paging.h>
29 #include <palacios/vmm_instr_emulator.h>
30 #include <palacios/vm_guest_mem.h>
31 #include <interfaces/vmm_socket.h>
32 #include <palacios/vmm_host_events.h>
33 #include <devices/pci.h>
34 #include <devices/pci_types.h>
35
36 //#include "network_console.h"
37
38
39
40 /* #ifndef DEBUG_CIRRUS_GFX_CARD
41 #undef PrintDebug
42 #define PrintDebug(fmt, args...)
43 #endif */
44
45
46 #define START_ADDR 0xA0000
47 #define END_ADDR 0xC0000
48
49 #define SIZE_OF_REGION (END_ADDR - START_ADDR)
50
51 #define PASSTHROUGH 1
52 #define PORT_OFFSET 0x3B0
53
54 struct video_internal {
55     addr_t video_memory_pa;
56     uint8_t * video_memory;
57     
58     struct vm_device * pci_bus;
59     struct pci_device * pci_dev;
60
61     int client_fd;
62
63     uint_t screen_bottom;
64     uint_t ports[44];
65     uint8_t reg_3C4[256];
66     uint8_t reg_3CE[256];
67     uint16_t start_addr_offset;
68     uint16_t old_start_addr_offset;
69     uint16_t cursor_addr;
70     uint8_t reg_3D5[25];
71     
72 };
73
74 void video_do_in(uint16_t port, void * src, uint_t length){
75 #if PASSTHROUGH
76     uint_t i;
77     switch (length) {
78         case 1:
79             ((uint8_t *)src)[0] = v3_inb(port);
80             break;
81         case 2:
82             ((uint16_t *)src)[0] = v3_inw(port);
83             break;
84         case 4:
85             ((uint32_t *)src)[0] = v3_indw(port);
86             break;
87         default:
88             for (i = 0; i < length; i++) { 
89                 ((uint8_t *)src)[i] = v3_inb(port);
90             }
91     }
92 #endif
93 }
94
95 void video_do_out(uint16_t port, void * src, uint_t length){
96 #if PASSTHROUGH
97     uint_t i;
98     switch (length) {
99         case 1:
100             v3_outb(port,((uint8_t *)src)[0]);
101             break;
102         case 2:
103             v3_outw(port,((uint16_t *)src)[0]);
104             break;
105         case 4:
106             v3_outdw(port,((uint32_t *)src)[0]);
107             break;
108         default:
109             for (i = 0; i < length; i++) { 
110                 v3_outb(port, ((uint8_t *)src)[i]);
111             }
112     }
113 #endif
114 }
115
116 static int video_write_mem(struct guest_info * core, addr_t guest_addr, void * dest, uint_t length, void * priv_data) {
117     struct vm_device * dev = (struct vm_device *)priv_data;
118     struct video_internal * data = (struct video_internal *)dev->private_data;
119     addr_t write_offset = guest_addr - START_ADDR;
120 //    uint_t difference = 0x18000;
121 //    int i = 0;
122
123     /*
124     PrintDebug(info->vm_info, info, "\n\nInside Video Write Memory.\n\n");
125     PrintDebug(info->vm_info, info, "Guest address: %p length = %d\n", (void *)guest_addr, length);
126
127     PrintDebug(info->vm_info, info, "Write offset: 0x%x\n", (uint_t)write_offset);
128     PrintDebug(info->vm_info, info, "Video_Memory: ");
129
130     for (i = 0; i < length; i += 2) {
131         PrintDebug(info->vm_info, info, "%c", ((char *)(V3_VAddr((void *)guest_addr)))[i]);
132     }
133     */
134 #if PASSTHROUGH
135     memcpy(data->video_memory + write_offset, V3_VAddr((void*)guest_addr), length);
136 #endif
137
138
139 /*    if (send_update(data->client_fd, data->video_memory + difference, write_offset-difference, data->start_addr_offset, length) == -1) {
140         PrintError(info->vm_info, info, "Error sending update to client\n");
141         return -1;
142     }
143 */
144     // PrintDebug(info->vm_info, info, " Done.\n");
145     return length;
146 }
147
148 static int video_read_port(struct guest_info * dev, uint16_t port, void * dest, uint_t length, void * priv_data ) {
149     PrintDebug(info->vm_info, info, "Video: Read port 0x%x\n",port);
150     video_do_in(port, dest, length);
151     return length;
152 }
153
154 static int video_read_port_generic(struct guest_info * dev, uint16_t port, void * dest, uint_t length, void * priv_data) {
155     memset(dest, 0, length);
156     video_do_in(port, dest, length);
157     return length;
158 }
159
160
161 static int video_write_port(struct guest_info * dev, uint16_t port, void * dest, uint_t length, void * priv_data) {
162     
163       PrintDebug(info->vm_info, info, "Video: write port 0x%x...Wrote: ", port);
164       uint_t i;
165       for(i = 0; i < length; i++){
166       PrintDebug(info->vm_info, info, "%x", ((uint8_t*)dest)[i]);
167       }
168       PrintDebug(info->vm_info, info, "...Done\n");
169     video_do_out(port, dest, length);
170     return length;
171 }
172
173 static int video_write_port_store(struct guest_info * dev, uint16_t port, void * dest, uint_t length, void * priv_data) {
174     
175       PrintDebug(info->vm_info, info, "Entering video_write_port_store...port 0x%x\n", port);
176       uint_t i;
177       for(i = 0; i < length; i++){
178       PrintDebug(info->vm_info, info, "%x", ((uint8_t*)dest)[i]);
179       }
180       PrintDebug(info->vm_info, info, "...Done\n"); 
181     
182     struct video_internal * video_state = (struct video_internal *)priv_data;
183
184     video_state->ports[port - PORT_OFFSET] = 0;
185     memcpy(video_state->ports + (port - PORT_OFFSET), dest, length); 
186     video_do_out(port, dest, length);
187
188     return length;
189 }
190
191 static int video_write_port_3D5(struct guest_info * dev, uint16_t port, void * dest, uint_t length, void * priv_data) {
192     struct video_internal * video_state = (struct video_internal *)priv_data;
193     uint8_t new_start = 0;
194     uint_t index = 0;
195
196     PrintDebug(info->vm_info, info, "Video: write port 0x%x...Wrote: ", port);
197     {
198         uint_t i = 0;
199         for (i = 0; i < length; i++){
200             PrintDebug(info->vm_info, info, "%x", ((uint8_t*)dest)[i]);
201         }
202         PrintDebug(info->vm_info, info, "...Done\n");
203     }
204
205     video_state->ports[port - PORT_OFFSET] = 0;
206
207     memcpy(video_state->ports + (port - PORT_OFFSET), dest, length);
208
209     memcpy(&(video_state->reg_3D5[index]), dest, length);
210
211     index = video_state->ports[port - 1 - PORT_OFFSET];
212
213     // JRL: Add length check
214     new_start = *((uint8_t *)dest);
215
216
217     switch (index) {
218         case 0x0c:
219             video_state->old_start_addr_offset = video_state->start_addr_offset;
220
221             video_state->start_addr_offset = (new_start << 8);
222
223             break;
224         case 0x0d: {
225             int diff = 0;
226
227             video_state->start_addr_offset += new_start;
228
229             diff = video_state->start_addr_offset - video_state->old_start_addr_offset;
230             diff /= 80;
231
232             PrintDebug(info->vm_info, info, "Scroll lines = %d\n", diff);
233
234 //          send_scroll(video_state->client_fd, diff, video_state->video_memory);
235
236             break;
237         }
238         case 0x0E:
239             video_state->cursor_addr = new_start << 8;
240
241             break;
242         case 0x0F: {
243             uint_t x = 0;
244             uint_t y = 0;
245
246             video_state->cursor_addr += new_start;
247            
248             x = ((video_state->cursor_addr) % 80) + 1;
249             y = (((video_state->cursor_addr) / 80) - ((video_state->start_addr_offset / 80))) + 1;
250             
251             PrintDebug(info->vm_info, info, "New Cursor Location; X=%d Y=%d\n", x, y);
252             
253 //          send_cursor_update(video_state->client_fd, x, y);
254             break;
255         }
256         default:
257             break;
258     }
259
260     video_do_out(port, dest, length);
261
262     return length;
263 }
264
265
266 static int video_write_port_3C5(struct guest_info * dev, uint16_t port, void * dest, uint_t length, void * priv_data ) {
267     struct video_internal * video_state = (struct video_internal *)priv_data;
268     uint_t index = 0;
269
270
271     PrintDebug(info->vm_info, info, "Entering write_port_3C5....port 0x%x\n", port);
272     {
273         uint_t i = 0;
274         for(i = 0; i < length; i++){
275             PrintDebug(info->vm_info, info, "%x", ((uint8_t*)dest)[i]);
276         }
277         PrintDebug(info->vm_info, info, "...Done\n");
278     }
279
280     video_state->ports[port - PORT_OFFSET] = 0;
281     memcpy(video_state->ports + (port - PORT_OFFSET), dest, length); 
282
283     index = video_state->ports[port - 1 - PORT_OFFSET];
284
285     memcpy(&(video_state->reg_3C4[index]), dest, length);
286     video_do_out(port, dest, length);
287
288     return length;
289 }
290
291 static int video_write_port_3CF(struct guest_info * dev, uint16_t port, void * dest, uint_t length, void * priv_data) {
292     struct video_internal * video_state = (struct video_internal *)priv_data;
293
294     PrintDebug(info->vm_info, info, "Entering write_port_3CF....port 0x%x\n", port);
295
296     {
297         uint_t i = 0;
298         for(i = 0; i < length; i++){
299             PrintDebug(info->vm_info, info, "%x", ((uint8_t*)dest)[i]);
300         }
301         PrintDebug(info->vm_info, info, "...Done\n");
302     }
303
304     video_state->ports[port - PORT_OFFSET] = 0;
305     memcpy(video_state->ports + (port - PORT_OFFSET), dest, length); 
306
307     uint_t index = video_state->ports[port - 1 - PORT_OFFSET];
308     memcpy(&(video_state->reg_3CE[index]), dest, length);
309     video_do_out(port, dest, length);
310     return length;
311 }
312
313 static int video_write_port_3D4(struct guest_info * dev, uint16_t port, void * dest, uint_t length, void * priv_data){
314     struct video_internal * video_state = (struct video_internal *)priv_data;
315
316 #if 1
317     if (length == 1) {
318
319         video_state->ports[port - PORT_OFFSET] = 0;
320         memcpy(video_state->ports + (port - PORT_OFFSET), dest, length);
321
322     } else if (length == 2) {
323         uint16_t new_start = *((uint16_t *)dest);
324         uint16_t cursor_start = *((uint16_t *)dest);;
325
326         //Updating the cursor
327         if ((cursor_start & 0x00FF) == 0x000E) {
328
329             cursor_start = (cursor_start & 0xFF00);
330             video_state->cursor_addr = cursor_start;
331
332         } else if ((cursor_start & 0x00FF) == 0x000F) {
333             uint_t x = 0;
334             uint_t y = 0;
335
336             video_state->cursor_addr += ((cursor_start >> 8) & 0x00FF);
337
338             x = ((video_state->cursor_addr) % 80) + 1;
339             y = (((video_state->cursor_addr) / 80) - ((video_state->start_addr_offset / 80))) + 1;
340
341             PrintDebug(info->vm_info, info, "New Cursor Location; X=%d Y=%d\n", x, y);
342
343 //          send_cursor_update(video_state->client_fd, x, y);
344         }
345
346         //Checking to see if scrolling is needed
347         if ((new_start & 0x00FF) == 0x000C) {
348
349             video_state->old_start_addr_offset = video_state->start_addr_offset;
350             new_start = (new_start & 0xFF00);
351             video_state->start_addr_offset = new_start;
352
353         } else if ((new_start & 0x00FF) == 0x000D) {
354             int diff = 0;
355
356             video_state->start_addr_offset += ((new_start >> 8) & 0x00FF);
357
358             diff =  video_state->start_addr_offset - video_state->old_start_addr_offset;
359             diff /= 80;
360
361             PrintDebug(info->vm_info, info, "Scroll lines = %d\n", diff);
362
363 //          send_scroll(video_state->client_fd, diff, video_state->video_memory+0x18000);
364         }
365     } else {
366         // JRL ??
367         return -1;
368     }
369 #endif 
370     video_do_out(port, dest, length);
371     return length;
372 }
373
374 static int video_write_mem_region(struct guest_info * core, addr_t guest_addr, void * dest, uint_t length, void * priv_data) {;
375     PrintDebug(info->vm_info, info, "Video write mem region guest_addr: 0x%p, src: 0x%p, length: %d, Value?= %x\n", (void *)guest_addr, dest, length, *((uint32_t *)V3_VAddr((void *)guest_addr)));
376     return length;
377 }
378
379 static int video_read_mem_region(struct guest_info * core, addr_t guest_addr, void * dest, uint_t length, void * priv_data){
380     PrintDebug(info->vm_info, info, "Video:  Within video_read_mem_region\n");
381     return length;
382 }
383
384 static int video_write_io_region(struct guest_info * core, addr_t guest_addr, void * dest, uint_t length, void * priv_data){
385     PrintDebug(info->vm_info, info, "Video:  Within video_write_io_region\n");
386     return length;
387 }
388
389 static int video_read_io_region(struct guest_info * core, addr_t guest_addr, void * dest, uint_t length, void * priv_data){
390     PrintDebug(info->vm_info, info, "Video:  Within video_read_io_region\n");
391     return length;
392 }
393
394 static int cirrus_gfx_card_free(struct vm_device * dev) {
395     v3_unhook_mem(dev->vm, V3_MEM_CORE_ANY, START_ADDR);
396     return 0;
397 }
398
399 /*
400 static int cirrus_gfx_card_reset_device(struct vm_device * dev) {
401     PrintDebug(info->vm_info, info, "Video: reset device\n");
402     return 0;
403 }
404
405 static int cirrus_gfx_card_start_device(struct vm_device * dev) {
406     PrintDebug(info->vm_info, info, "Video: start device\n");
407     return 0;
408 }
409
410 static int cirrus_gfx_card_stop_device(struct vm_device * dev) {
411     PrintDebug(info->vm_info, info, "Video: stop device\n");
412     return 0;
413 }
414 */
415 static struct v3_device_ops dev_ops = {
416     .free = (int (*)(void *))cirrus_gfx_card_free,
417 //    .reset = cirrus_gfx_card_reset_device,
418 //    .start = cirrus_gfx_card_start_device,
419 //    .stop = cirrus_gfx_card_stop_device,
420 };
421
422 static int cirrus_gfx_card_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg){
423     struct video_internal * video_state = (struct video_internal *)V3_Malloc(sizeof(struct video_internal));
424 //    struct vm_device * pci_bus = v3_find_dev(vm, (char *)cfg_data);
425     struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
426     char * dev_id = v3_cfg_val(cfg, "ID");
427
428
429     if (!video_state) {
430         PrintError(info->vm_info, info, "Cannot allocate state in cirrus gfx\n");
431         return -1;
432     }
433
434     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, video_state);
435
436     if (dev == NULL) {
437         PrintError(info->vm_info, info, "Could not attach device %s\n", dev_id);
438         V3_Free(video_state)
439         return -1;
440     }
441
442     PrintDebug(info->vm_info, info, "video: init_device\n");
443     PrintDebug(info->vm_info, info, "Num Pages=%d\n", SIZE_OF_REGION / 4096);
444
445     video_state->video_memory_pa = (addr_t)V3_AllocPages(SIZE_OF_REGION / 4096);
446     if (!video_state->video_memory_pa) { 
447         PrintError(info->vm_info, info, "Cannot allocate video memory\n");
448         V3_Free(video_state);
449         return -1;
450     }
451
452     video_state->video_memory = V3_VAddr((void *)video_state->video_memory_pa);
453
454     memset(video_state->video_memory, 0, SIZE_OF_REGION);
455
456
457     v3_dev_hook_io(dev, 0x3b0, &video_read_port, &video_write_port);
458     v3_dev_hook_io(dev, 0x3b1, &video_read_port, &video_write_port);
459     v3_dev_hook_io(dev, 0x3b2, &video_read_port, &video_write_port);
460     v3_dev_hook_io(dev, 0x3b3, &video_read_port, &video_write_port);
461     v3_dev_hook_io(dev, 0x3b4, &video_read_port, &video_write_port);
462     v3_dev_hook_io(dev, 0x3b5, &video_read_port, &video_write_port);
463     v3_dev_hook_io(dev, 0x3b6, &video_read_port, &video_write_port);
464     v3_dev_hook_io(dev, 0x3b7, &video_read_port, &video_write_port);
465     v3_dev_hook_io(dev, 0x3b8, &video_read_port, &video_write_port);
466     v3_dev_hook_io(dev, 0x3b9, &video_read_port, &video_write_port);
467     v3_dev_hook_io(dev, 0x3ba, &video_read_port, &video_write_port);
468     v3_dev_hook_io(dev, 0x3bb, &video_read_port, &video_write_port);
469     v3_dev_hook_io(dev, 0x3c0, &video_read_port, &video_write_port_store);
470     v3_dev_hook_io(dev, 0x3c1, &video_read_port, &video_write_port);
471     v3_dev_hook_io(dev, 0x3c2, &video_read_port, &video_write_port_store);
472     v3_dev_hook_io(dev, 0x3c3, &video_read_port, &video_write_port);
473     v3_dev_hook_io(dev, 0x3c4, &video_read_port, &video_write_port_store);
474     v3_dev_hook_io(dev, 0x3c5, &video_read_port, &video_write_port_3C5);
475     v3_dev_hook_io(dev, 0x3c6, &video_read_port, &video_write_port_store);
476     v3_dev_hook_io(dev, 0x3c7, &video_read_port, &video_write_port);
477     v3_dev_hook_io(dev, 0x3c8, &video_read_port, &video_write_port_store);
478     v3_dev_hook_io(dev, 0x3c9, &video_read_port, &video_write_port_store);
479     v3_dev_hook_io(dev, 0x3ca, &video_read_port, &video_write_port);
480     v3_dev_hook_io(dev, 0x3cb, &video_read_port, &video_write_port);
481     v3_dev_hook_io(dev, 0x3cc, &video_read_port, &video_write_port);
482     v3_dev_hook_io(dev, 0x3cd, &video_read_port, &video_write_port);
483     v3_dev_hook_io(dev, 0x3ce, &video_read_port, &video_write_port_store);
484     v3_dev_hook_io(dev, 0x3cf, &video_read_port, &video_write_port_3CF);
485     v3_dev_hook_io(dev, 0x3d0, &video_read_port, &video_write_port);
486     v3_dev_hook_io(dev, 0x3d1, &video_read_port, &video_write_port);
487     v3_dev_hook_io(dev, 0x3d2, &video_read_port, &video_write_port);
488     v3_dev_hook_io(dev, 0x3d3, &video_read_port, &video_write_port);
489     v3_dev_hook_io(dev, 0x3d4, &video_read_port, &video_write_port_3D4);
490     v3_dev_hook_io(dev, 0x3d5, &video_read_port, &video_write_port_3D5);
491     v3_dev_hook_io(dev, 0x3d6, &video_read_port, &video_write_port);
492     v3_dev_hook_io(dev, 0x3d7, &video_read_port, &video_write_port);
493     v3_dev_hook_io(dev, 0x3d8, &video_read_port, &video_write_port);
494     v3_dev_hook_io(dev, 0x3d9, &video_read_port, &video_write_port);
495     v3_dev_hook_io(dev, 0x3da, &video_read_port_generic, &video_write_port);
496     v3_dev_hook_io(dev, 0x3db, &video_read_port, &video_write_port);
497     v3_dev_hook_io(dev, 0x3dc, &video_read_port, &video_write_port);
498     v3_dev_hook_io(dev, 0x3dd, &video_read_port, &video_write_port);
499     v3_dev_hook_io(dev, 0x3de, &video_read_port, &video_write_port);
500     v3_dev_hook_io(dev, 0x3df, &video_read_port, &video_write_port);
501
502
503     PrintDebug(info->vm_info, info, "PA of array: %p\n", (void *)video_state->video_memory_pa);
504
505
506 #if PASSTHROUGH
507     if (v3_hook_write_mem(vm, V3_MEM_CORE_ANY, START_ADDR, END_ADDR, START_ADDR, &video_write_mem, dev) == -1){
508         PrintDebug(info->vm_info, info, "\n\nVideo Hook failed.\n\n");
509     }
510 #else
511     if (v3_hook_write_mem(vm, V3_MEM_CORE_ANY, START_ADDR, END_ADDR, video_memory_pa, &video_write_mem, dev) == -1){
512         PrintDebug(info->vm_info, info, "\n\nVideo Hook failed.\n\n");
513     }
514 #endif
515
516     PrintDebug(info->vm_info, info, "Video: Getting client connection\n");
517
518     //video_state->client_fd = get_client_connection(vm);
519
520     PrintDebug(info->vm_info, info, "Video: Client connection established\n");
521
522     video_state->screen_bottom = 25;
523
524     video_state->pci_bus = pci_bus;
525
526     if (video_state->pci_bus == NULL) {
527         PrintError(info->vm_info, info, "Could not find PCI device\n");
528         return -1;
529     } else {
530         struct v3_pci_bar bars[6];
531         struct pci_device * pci_dev = NULL;
532
533         int i;
534         for (i = 0; i < 6; i++) {
535             bars[i].type = PCI_BAR_NONE;
536         }
537
538         bars[0].type = PCI_BAR_MEM32;
539         bars[0].num_pages = 8192;
540         bars[0].default_base_addr = 0xf0000000;
541
542         bars[0].mem_read = video_read_mem_region;
543         bars[0].mem_write = video_write_mem_region;
544
545         bars[1].type = PCI_BAR_MEM32;
546         bars[1].num_pages = 1;
547         bars[1].default_base_addr = 0xf2000000;
548     
549         bars[1].mem_read = video_read_io_region;
550         bars[1].mem_write = video_write_io_region;
551         //-1 Means autoassign
552         //                                                     Not sure if STD
553         pci_dev = v3_pci_register_device(video_state->pci_bus, PCI_STD_DEVICE, 0,
554                                          //or0  1st null could be pci_config_update
555                                          -1, 0, "CIRRUS_GFX_CARD", bars, NULL, NULL, 
556                                          NULL, NULL, dev);
557
558         if (pci_dev == NULL) {
559             PrintError(info->vm_info, info, "Failed to register VIDEO %d with PCI\n", i);
560             return -1;
561         } else{
562             PrintDebug(info->vm_info, info, "Registering PCI_VIDEO succeeded\n");
563         }
564         //Need to set some pci_dev->config_header.vendor_id type variables
565
566         pci_dev->config_header.vendor_id = 0x1013;
567         pci_dev->config_header.device_id = 0x00B8;
568         pci_dev->config_header.revision = 0x00;
569
570         //If we treat video as a VGA device than below is correct
571         //If treated as a VGA compatible controller, which has mapping
572         //0xA0000-0xB0000 and I/O addresses 0x3B0-0x3BB than change
573         //#define from VGA to 0
574
575         //pci_dev->config_header.class = 0x00;
576         //pci_dev->config_header.subclass = 0x01;
577
578         pci_dev->config_header.class = 0x03;
579         pci_dev->config_header.subclass = 0x00;
580         pci_dev->config_header.prog_if = 0x00;
581
582
583         //We have a subsystem ID, but optional to provide:  1AF4:1100
584         pci_dev->config_header.subsystem_vendor_id = 0x1AF4;
585         pci_dev->config_header.subsystem_id = 0x1100;
586         //pci_dev->config_header.header_type = 0x00;
587         pci_dev->config_header.command = 0x03;
588         video_state->pci_dev = pci_dev;
589     }
590
591     PrintDebug(info->vm_info, info, "Video: init complete\n");
592     return 0;
593 }
594
595 device_register("CIRRUS_GFX_CARD", cirrus_gfx_card_init)