1/*
2 * Copyright 2008 Red Hat, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23/** \file qxl_driver.c
24 * \author Adam Jackson <ajax@redhat.com>
25 * \author Søren Sandmann <sandmann@redhat.com>
26 *
27 * This is qxl, a driver for the Qumranet paravirtualized graphics device
28 * in qemu.
29 */
30
31#ifdef HAVE_CONFIG_H
32#include "config.h"
33#endif
34
35#include <unistd.h>
36#include <string.h>
37#include <stdio.h>
38#include <errno.h>
39#include <time.h>
40#include <stdlib.h>
41
42#include <xf86Crtc.h>
43#include <xf86RandR12.h>
44
45#include "qxl.h"
46#include "assert.h"
47#include "qxl_option_helpers.h"
48#include <spice/protocol.h>
49
50#ifdef XSPICE
51#include "spiceqxl_driver.h"
52#include "spiceqxl_main_loop.h"
53#include "spiceqxl_display.h"
54#include "spiceqxl_inputs.h"
55#include "spiceqxl_io_port.h"
56#include "spiceqxl_spice_server.h"
57#include "spiceqxl_audio.h"
58#include "spiceqxl_smartcard.h"
59#include "spiceqxl_vdagent.h"
60#endif /* XSPICE */
61
62#include "dfps.h"
63
64extern void compat_init_scrn (ScrnInfoPtr);
65
66#define BREAKPOINT()   do { __asm__ __volatile__ ("int $03"); } while (0)
67
68#ifdef XSPICE
69static char filter_str[] = "filter";
70static char auto_str[]   = "auto";
71static char auto_glz_str[]   = "auto_glz";
72static char spice_vdagent_virtio_path_default[] = "/tmp/xspice-virtio";
73static char spice_vdagent_uinput_path_default[] = "/tmp/xspice-uinput";
74#endif
75static char driver_name[] = QXL_DRIVER_NAME;
76static const OptionInfoRec DefaultOptions[] =
77{
78    { OPTION_ENABLE_IMAGE_CACHE,
79      "EnableImageCache",         OPTV_BOOLEAN, { 1 }, FALSE },
80    { OPTION_ENABLE_FALLBACK_CACHE,
81      "EnableFallbackCache",      OPTV_BOOLEAN, { 1 }, FALSE },
82    { OPTION_ENABLE_SURFACES,
83      "EnableSurfaces",           OPTV_BOOLEAN, { 1 }, FALSE },
84    { OPTION_DEBUG_RENDER_FALLBACKS,
85      "DebugRenderFallbacks",     OPTV_BOOLEAN, { 0 }, FALSE },
86    { OPTION_NUM_HEADS,
87      "NumHeads",                 OPTV_INTEGER, { 4 }, FALSE },
88    { OPTION_SPICE_DEFERRED_FPS,
89      "SpiceDeferredFPS",         OPTV_INTEGER, { 0 }, FALSE},
90#ifdef XSPICE
91    { OPTION_SPICE_PORT,
92      "SpicePort",                OPTV_INTEGER,   {5900}, FALSE },
93    { OPTION_SPICE_TLS_PORT,
94      "SpiceTlsPort",             OPTV_INTEGER,   {0}, FALSE},
95    { OPTION_SPICE_ADDR,
96      "SpiceAddr",                OPTV_STRING,    {0}, FALSE},
97    { OPTION_SPICE_X509_DIR,
98      "SpiceX509Dir",             OPTV_STRING,    {0}, FALSE},
99    { OPTION_SPICE_SASL,
100      "SpiceSasl",                OPTV_BOOLEAN,   {0}, FALSE},
101    { OPTION_SPICE_AGENT_MOUSE,
102      "SpiceAgentMouse",          OPTV_BOOLEAN,   {0}, TRUE },
103    { OPTION_SPICE_DISABLE_TICKETING,
104      "SpiceDisableTicketing",    OPTV_BOOLEAN,   {0}, FALSE},
105    { OPTION_SPICE_PASSWORD,
106      "SpicePassword",            OPTV_STRING,    {0}, FALSE},
107    { OPTION_SPICE_X509_KEY_FILE,
108      "SpiceX509KeyFile",         OPTV_STRING,    {0}, FALSE},
109    { OPTION_SPICE_STREAMING_VIDEO,
110      "SpiceStreamingVideo",      OPTV_STRING,    {.str = filter_str}, FALSE},
111    { OPTION_SPICE_PLAYBACK_COMPRESSION,
112      "SpicePlaybackCompression", OPTV_BOOLEAN,   {1}, FALSE},
113    { OPTION_SPICE_ZLIB_GLZ_WAN_COMPRESSION,
114      "SpiceZlibGlzWanCompression", OPTV_STRING,  {.str = auto_str}, FALSE},
115    { OPTION_SPICE_JPEG_WAN_COMPRESSION,
116      "SpiceJpegWanCompression",  OPTV_STRING,    {.str = auto_str}, FALSE},
117    { OPTION_SPICE_IMAGE_COMPRESSION,
118      "SpiceImageCompression",    OPTV_STRING,    {.str = auto_glz_str}, FALSE},
119    { OPTION_SPICE_DISABLE_COPY_PASTE,
120      "SpiceDisableCopyPaste",    OPTV_BOOLEAN,   {0}, FALSE},
121    { OPTION_SPICE_IPV4_ONLY,
122      "SpiceIPV4Only",            OPTV_BOOLEAN,   {0}, FALSE},
123    { OPTION_SPICE_IPV6_ONLY,
124      "SpiceIPV6Only",            OPTV_BOOLEAN,   {0}, FALSE},
125    { OPTION_SPICE_X509_CERT_FILE,
126      "SpiceX509CertFile",        OPTV_STRING,    {0}, FALSE},
127    { OPTION_SPICE_X509_KEY_PASSWORD,
128      "SpiceX509KeyPassword",     OPTV_STRING,    {0}, FALSE},
129    { OPTION_SPICE_TLS_CIPHERS,
130      "SpiceTlsCiphers",          OPTV_STRING,    {0}, FALSE},
131    { OPTION_SPICE_CACERT_FILE,
132      "SpiceCacertFile",          OPTV_STRING,    {0}, FALSE},
133    { OPTION_SPICE_DH_FILE,
134      "SpiceDhFile",              OPTV_STRING,    {0}, FALSE},
135    { OPTION_SPICE_EXIT_ON_DISCONNECT,
136      "SpiceExitOnDisconnect",    OPTV_BOOLEAN,   {0}, FALSE},
137    { OPTION_SPICE_PLAYBACK_FIFO_DIR,
138      "SpicePlaybackFIFODir",     OPTV_STRING,    {0}, FALSE},
139    { OPTION_SPICE_VDAGENT_ENABLED,
140      "SpiceVdagentEnabled",      OPTV_BOOLEAN,   {0}, FALSE},
141    { OPTION_SPICE_VDAGENT_VIRTIO_PATH,
142      "SpiceVdagentVirtioPath",   OPTV_STRING,    {.str = spice_vdagent_virtio_path_default}, FALSE},
143    { OPTION_SPICE_VDAGENT_UINPUT_PATH,
144      "SpiceVdagentUinputPath",   OPTV_STRING,    {.str = spice_vdagent_uinput_path_default}, FALSE},
145    { OPTION_SPICE_VDAGENT_UID,
146      "SpiceVdagentUid",          OPTV_INTEGER,    {0}, FALSE},
147    { OPTION_SPICE_VDAGENT_GID,
148      "SpiceVdagentGid",          OPTV_INTEGER,    {0}, FALSE},
149    { OPTION_FRAME_BUFFER_SIZE,
150      "FrameBufferSize",          OPTV_INTEGER,    {DEFAULT_FRAME_BUFFER_SIZE}, FALSE},
151    { OPTION_SURFACE_BUFFER_SIZE,
152      "SurfaceBufferSize",        OPTV_INTEGER,    {DEFAULT_SURFACE_BUFFER_SIZE}, FALSE},
153    { OPTION_COMMAND_BUFFER_SIZE,
154      "CommandBufferSize",        OPTV_INTEGER,    {DEFAULT_COMMAND_BUFFER_SIZE}, FALSE},
155    { OPTION_SPICE_SMARTCARD_FILE,
156      "SpiceSmartcardFile",       OPTV_STRING,    {0}, FALSE},
157    { OPTION_SPICE_VIDEO_CODECS,
158      "SpiceVideoCodecs",         OPTV_STRING,    {0}, FALSE},
159#endif
160
161    { -1, NULL, OPTV_NONE, {0}, FALSE }
162};
163
164static const OptionInfoRec *
165qxl_available_options (int chipid, int busid)
166{
167    return DefaultOptions;
168}
169
170/* Having a single monitors config struct allocated on the device avoids any
171 * possible fragmentation. Since X is single threaded there is no danger
172 * in us changing it between issuing the io and getting the interrupt to signal
173 * spice-server is done reading it.
174 */
175#define MAX_MONITORS_NUM 16
176
177void
178qxl_allocate_monitors_config (qxl_screen_t *qxl)
179{
180    qxl->monitors_config = (QXLMonitorsConfig *)(void *)
181	((unsigned long)qxl->ram + qxl->rom->ram_header_offset - qxl->monitors_config_size);
182}
183
184static Bool
185qxl_blank_screen (ScreenPtr pScreen, int mode)
186{
187    return TRUE;
188}
189
190#ifdef XSPICE
191static void
192unmap_memory_helper (qxl_screen_t *qxl)
193{
194    free (qxl->ram);
195    free (qxl->vram);
196    free (qxl->rom);
197}
198
199static void
200map_memory_helper (qxl_screen_t *qxl)
201{
202    qxl->ram = calloc (qxl->ram_size, 1);
203    qxl->ram_physical = qxl->ram;
204    qxl->vram = calloc (qxl->vram_size, 1);
205    qxl->vram_physical = qxl->vram;
206    qxl->rom = calloc (ROM_SIZE, 1);
207
208    init_qxl_rom (qxl, ROM_SIZE);
209}
210
211#else /* Default */
212
213static void
214unmap_memory_helper (qxl_screen_t *qxl)
215{
216#ifdef XSERVER_LIBPCIACCESS
217    if (qxl->ram)
218	pci_device_unmap_range (qxl->pci, qxl->ram, qxl->pci->regions[0].size);
219    if (qxl->vram)
220	pci_device_unmap_range (qxl->pci, qxl->vram, qxl->pci->regions[1].size);
221    if (qxl->rom)
222	pci_device_unmap_range (qxl->pci, qxl->rom, qxl->pci->regions[2].size);
223    if (qxl->io)
224	pci_device_close_io (qxl->pci, qxl->io);
225#else
226    if (qxl->ram)
227	xf86UnMapVidMem (scrnIndex, qxl->ram, (1 << qxl->pci->size[0]));
228    if (qxl->vram)
229	xf86UnMapVidMem (scrnIndex, qxl->vram, (1 << qxl->pci->size[1]));
230    if (qxl->rom)
231	xf86UnMapVidMem (scrnIndex, qxl->rom, (1 << qxl->pci->size[2]));
232#endif
233}
234
235static void
236map_memory_helper (qxl_screen_t *qxl)
237{
238#ifdef XSERVER_LIBPCIACCESS
239    pci_device_map_range (qxl->pci, qxl->pci->regions[0].base_addr,
240                          qxl->pci->regions[0].size,
241                          PCI_DEV_MAP_FLAG_WRITABLE | PCI_DEV_MAP_FLAG_WRITE_COMBINE,
242                          &qxl->ram);
243    qxl->ram_physical = u64_to_pointer (qxl->pci->regions[0].base_addr);
244    qxl->ram_size = qxl->pci->regions[0].size;
245
246    pci_device_map_range (qxl->pci, qxl->pci->regions[1].base_addr,
247                          qxl->pci->regions[1].size,
248                          PCI_DEV_MAP_FLAG_WRITABLE,
249                          &qxl->vram);
250    qxl->vram_physical = u64_to_pointer (qxl->pci->regions[1].base_addr);
251    qxl->vram_size = qxl->pci->regions[1].size;
252
253    pci_device_map_range (qxl->pci, qxl->pci->regions[2].base_addr,
254                          qxl->pci->regions[2].size, 0,
255                          (void **)&qxl->rom);
256
257    qxl->io = pci_device_open_io(qxl->pci,
258                                qxl->pci->regions[3].base_addr,
259                                qxl->pci->regions[3].size);
260    qxl->io_base = qxl->pci->regions[3].base_addr;
261#else
262    qxl->ram = xf86MapPciMem (scrnIndex, VIDMEM_FRAMEBUFFER,
263                              qxl->pci_tag, qxl->pci->memBase[0],
264                              (1 << qxl->pci->size[0]));
265    qxl->ram_physical = (void *)qxl->pci->memBase[0];
266
267    qxl->vram = xf86MapPciMem (scrnIndex, VIDMEM_MMIO | VIDMEM_MMIO_32BIT,
268                               qxl->pci_tag, qxl->pci->memBase[1],
269                               (1 << qxl->pci->size[1]));
270    qxl->vram_physical = (void *)qxl->pci->memBase[1];
271    qxl->vram_size = (1 << qxl->pci->size[1]);
272
273    qxl->rom = xf86MapPciMem (scrnIndex, VIDMEM_MMIO | VIDMEM_MMIO_32BIT,
274                              qxl->pci_tag, qxl->pci->memBase[2],
275                              (1 << qxl->pci->size[2]));
276
277    qxl->io_base = qxl->pci->ioBase[3];
278#endif
279}
280
281#endif /* XSPICE */
282
283static void
284qxl_unmap_memory (qxl_screen_t *qxl)
285{
286#ifdef XSPICE
287    if (qxl->worker)
288    {
289        spice_server_vm_stop(qxl->spice_server);
290	qxl->worker_running = FALSE;
291    }
292#endif
293
294    if (qxl->mem)
295    {
296	qxl_mem_free_all (qxl->mem);
297	free(qxl->mem);
298	qxl->mem = NULL;
299    }
300
301    if (qxl->surf_mem) {
302	qxl_mem_free_all (qxl->surf_mem);
303	free(qxl->surf_mem);
304	qxl->surf_mem = NULL;
305    }
306
307    unmap_memory_helper (qxl);
308    qxl->ram = qxl->ram_physical = qxl->vram = qxl->rom = NULL;
309
310    qxl->num_modes = 0;
311    qxl->modes = NULL;
312}
313
314#ifdef QXLDRV_RESIZABLE_SURFACE0
315static void
316qxl_dump_ring_stat (qxl_screen_t *qxl)
317{
318    int cmd_prod, cursor_prod, cmd_cons, cursor_cons;
319    int release_prod, release_cons;
320
321    cmd_prod = qxl_ring_prod (qxl->command_ring);
322    cursor_prod = qxl_ring_prod (qxl->cursor_ring);
323    cmd_cons = qxl_ring_cons (qxl->command_ring);
324    cursor_cons = qxl_ring_cons (qxl->cursor_ring);
325    release_prod = qxl_ring_prod (qxl->release_ring);
326    release_cons = qxl_ring_cons (qxl->release_ring);
327
328    ErrorF ("%s: Cmd %d/%d, Cur %d/%d, Rel %d/%d\n",
329            __func__, cmd_cons, cmd_prod, cursor_cons, cursor_prod,
330            release_cons, release_prod);
331}
332
333#endif
334
335/* To resize surface0 we need to ensure qxl->mem is empty. We can do that by:
336 * - fast:
337 *   - ooming until command ring is empty.
338 *   - flushing the release ring (>V10)
339 * - slow: calling update_area on all surfaces.
340 * This is done via already known code, so use that by default now.
341 */
342static int
343qxl_resize_surface0 (qxl_screen_t *qxl, long surface0_size)
344{
345    long ram_header_size = qxl->ram_size - qxl->rom->ram_header_offset;
346    long new_mem_size = qxl->ram_size -
347	(surface0_size + ram_header_size + qxl->monitors_config_size);
348
349    if (new_mem_size < 0)
350    {
351	ErrorF ("cannot resize surface0 to %ld, does not fit in BAR 0\n",
352	        surface0_size);
353	return 0;
354    }
355
356    ErrorF ("resizing surface0 to %ld\n", surface0_size);
357
358    if (qxl->mem)
359    {
360#ifdef QXLDRV_RESIZABLE_SURFACE0
361	void *surfaces;
362	qxl_dump_ring_stat (qxl);
363	qxl_io_flush_surfaces (qxl);
364	surfaces = qxl_surface_cache_evacuate_all (qxl->surface_cache);
365	qxl_io_destroy_all_surfaces (qxl); // redundant?
366	qxl_io_flush_release (qxl);
367	qxl_dump_ring_stat (qxl);
368	qxl_surface_cache_replace_all (qxl->surface_cache, surfaces);
369#else
370	ErrorF ("resizing surface0 compiled out\n");
371	return 0;
372#endif
373    }
374
375    /* surface0_area is still fixed to start of ram BAR */
376    qxl->surface0_size = surface0_size;
377
378    qxl->mem_size = new_mem_size;
379    qxl->mem = qxl_mem_create ((void *)((unsigned long)qxl->surface0_area + qxl->surface0_size),
380                               qxl->mem_size);
381    return 1;
382}
383
384static Bool
385qxl_map_memory (qxl_screen_t *qxl, int scrnIndex)
386{
387    map_memory_helper (qxl);
388
389    if (!qxl->ram || !qxl->vram || !qxl->rom)
390	return FALSE;
391
392    xf86DrvMsg (scrnIndex, X_INFO, "framebuffer at %p (%d KB)\n",
393                qxl->ram, qxl->rom->surface0_area_size / 1024);
394
395    xf86DrvMsg (scrnIndex, X_INFO, "command ram at %p (%d KB)\n",
396                (void *)((unsigned long)qxl->ram + qxl->rom->surface0_area_size),
397                (qxl->rom->num_pages * getpagesize ()) / 1024);
398
399    xf86DrvMsg (scrnIndex, X_INFO, "vram at %p (%ld KB)\n",
400                qxl->vram, qxl->vram_size / 1024);
401
402    xf86DrvMsg (scrnIndex, X_INFO, "rom at %p\n", qxl->rom);
403
404    /*
405     * Keep a hole for MonitorsConfig. This is not part of QXLRam to ensure
406     * the driver can change it without affecting the driver/device ABI.
407     */
408    qxl->monitors_config_size = (sizeof (QXLMonitorsConfig) +
409                                 sizeof (QXLHead) * MAX_MONITORS_NUM + getpagesize () - 1)
410	& ~(getpagesize () - 1);
411    qxl->num_modes = *(uint32_t *)((uint8_t *)qxl->rom + qxl->rom->modes_offset);
412    qxl->modes = (struct QXLMode *)(((uint8_t *)qxl->rom) + qxl->rom->modes_offset + 4);
413    qxl->surface0_area = qxl->ram;
414    qxl->surface0_size = 0;
415    qxl->mem = NULL;
416    if (!qxl_resize_surface0 (qxl, qxl->rom->surface0_area_size))
417	return FALSE;
418    qxl->surf_mem = qxl_mem_create ((void *)((unsigned long)qxl->vram), qxl->vram_size);
419    qxl_allocate_monitors_config (qxl);
420
421    return TRUE;
422}
423
424#ifdef XSPICE
425static void
426qxl_save_state (ScrnInfoPtr pScrn)
427{
428}
429
430static void
431qxl_restore_state (ScrnInfoPtr pScrn)
432{
433}
434
435#else /* QXL */
436static void
437qxl_save_state (ScrnInfoPtr pScrn)
438{
439    qxl_screen_t *qxl = pScrn->driverPrivate;
440
441    if (xf86IsPrimaryPci (qxl->pci))
442	vgaHWSaveFonts (pScrn, &qxl->vgaRegs);
443}
444
445static void
446qxl_restore_state (ScrnInfoPtr pScrn)
447{
448    qxl_screen_t *qxl = pScrn->driverPrivate;
449
450    if (xf86IsPrimaryPci (qxl->pci))
451	vgaHWRestoreFonts (pScrn, &qxl->vgaRegs);
452}
453
454#endif /* XSPICE */
455
456static Bool
457qxl_close_screen (CLOSE_SCREEN_ARGS_DECL)
458{
459    ScrnInfoPtr pScrn = xf86ScreenToScrn (pScreen);
460    qxl_screen_t *qxl = pScrn->driverPrivate;
461    Bool result;
462
463    ErrorF ("Disabling FB access for %d\n", pScrn->scrnIndex);
464#ifndef XF86_SCRN_INTERFACE
465    pScrn->EnableDisableFBAccess (scrnIndex, FALSE);
466#else
467    pScrn->EnableDisableFBAccess (pScrn, FALSE);
468#endif
469
470    pScreen->CreateScreenResources = qxl->create_screen_resources;
471    pScreen->CloseScreen = qxl->close_screen;
472
473    result = pScreen->CloseScreen (CLOSE_SCREEN_ARGS);
474
475#ifndef XSPICE
476    if (!xf86IsPrimaryPci (qxl->pci) && qxl->primary)
477	qxl_reset_and_create_mem_slots (qxl);
478#endif
479
480    if (pScrn->vtSema)
481    {
482	qxl_restore_state (pScrn);
483	qxl_mark_mem_unverifiable (qxl);
484	qxl_unmap_memory (qxl);
485    }
486    pScrn->vtSema = FALSE;
487
488    return result;
489}
490
491void
492qxl_set_screen_pixmap_header (ScreenPtr pScreen)
493{
494    ScrnInfoPtr pScrn = xf86ScreenToScrn (pScreen);
495    qxl_screen_t *qxl = pScrn->driverPrivate;
496    PixmapPtr pPixmap = pScreen->GetScreenPixmap (pScreen);
497
498    // TODO: don't ModifyPixmapHeader too early?
499
500    if (pPixmap)
501    {
502	pScreen->ModifyPixmapHeader (pPixmap,
503	                             qxl->primary_mode.x_res, qxl->primary_mode.y_res,
504	                             -1, -1,
505	                             qxl->primary_mode.x_res * qxl->bytes_per_pixel,
506	                             qxl_surface_get_host_bits(qxl->primary));
507    }
508    else
509    {
510	ErrorF ("pix: %p;\n", pPixmap);
511    }
512}
513
514static qxl_surface_t *
515qxl_create_primary(qxl_screen_t *qxl)
516{
517    struct QXLMode *pm = &qxl->primary_mode;
518    pm->id = 0x4242;
519    pm->x_res = qxl->virtual_x;
520    pm->y_res = qxl->virtual_y;
521    pm->bits = qxl->pScrn->bitsPerPixel;
522    pm->stride = qxl->virtual_x * pm->bits / 8;
523    pm->x_mili = 0; // TODO
524    pm->y_mili = 0; // TODO
525    pm->orientation = 0; // ? supported by us for single head usage? more TODO
526
527    return qxl_surface_cache_create_primary (qxl, &qxl->primary_mode);
528}
529
530Bool
531qxl_resize_primary_to_virtual (qxl_screen_t *qxl)
532{
533    long new_surface0_size;
534
535    if ((qxl->primary_mode.x_res == qxl->virtual_x &&
536         qxl->primary_mode.y_res == qxl->virtual_y) &&
537        qxl->device_primary == QXL_DEVICE_PRIMARY_CREATED)
538    {
539	return TRUE; /* empty Success */
540    }
541
542    ErrorF ("resizing primary to %dx%d\n", qxl->virtual_x, qxl->virtual_y);
543
544    if (!qxl->kms_enabled) {
545	new_surface0_size =
546	    qxl->virtual_x * qxl->pScrn->bitsPerPixel / 8 * qxl->virtual_y;
547
548	if (new_surface0_size > qxl->surface0_size)
549	{
550	    if (!qxl_resize_surface0 (qxl, new_surface0_size))
551	    {
552		ErrorF ("not resizing primary to virtual, leaving old virtual\n");
553		return FALSE;
554	    }
555	}
556    }
557
558    if (qxl->primary)
559    {
560	qxl_surface_kill (qxl->primary);
561	qxl_surface_cache_sanity_check (qxl->surface_cache);
562	qxl->bo_funcs->destroy_primary(qxl, qxl->primary_bo);
563    }
564
565    qxl->primary = qxl_create_primary(qxl);
566    qxl->bytes_per_pixel = (qxl->pScrn->bitsPerPixel + 7) / 8;
567
568    if (qxl->screen_resources_created)
569    {
570        ScreenPtr pScreen = qxl->pScrn->pScreen;
571	PixmapPtr root = pScreen->GetScreenPixmap (pScreen);
572
573        if (qxl->deferred_fps <= 0)
574        {
575            qxl_surface_t *surf;
576
577            if ((surf = get_surface (root)))
578                qxl_surface_kill (surf);
579
580            set_surface (root, qxl->primary);
581        }
582
583        qxl_set_screen_pixmap_header (pScreen);
584    }
585
586    ErrorF ("primary is %p\n", qxl->primary);
587    return TRUE;
588}
589
590Bool
591qxl_resize_primary (qxl_screen_t *qxl, uint32_t width, uint32_t height)
592{
593    qxl->virtual_x = width;
594    qxl->virtual_y = height;
595
596    if (qxl->vt_surfaces)
597    {
598	ErrorF ("%s: ignoring resize due to not being in control of VT\n",
599	        __FUNCTION__);
600	return FALSE;
601    }
602    return qxl_resize_primary_to_virtual (qxl);
603}
604
605static Bool
606qxl_switch_mode (SWITCH_MODE_ARGS_DECL)
607{
608    SCRN_INFO_PTR (arg);
609    qxl_screen_t *qxl = pScrn->driverPrivate;
610
611    ErrorF ("Ignoring display mode, ensuring recreation of primary\n");
612
613    return qxl_resize_primary_to_virtual (qxl);
614}
615
616static Bool
617qxl_create_screen_resources (ScreenPtr pScreen)
618{
619    ScrnInfoPtr    pScrn = xf86ScreenToScrn (pScreen);
620    qxl_screen_t * qxl = pScrn->driverPrivate;
621    Bool           ret;
622    PixmapPtr      pPixmap;
623    qxl_surface_t *surf;
624
625    pScreen->CreateScreenResources = qxl->create_screen_resources;
626    ret = pScreen->CreateScreenResources (pScreen);
627    pScreen->CreateScreenResources = qxl_create_screen_resources;
628
629    if (!ret)
630	return FALSE;
631
632    pPixmap = pScreen->GetScreenPixmap (pScreen);
633
634    if (qxl->deferred_fps <= 0)
635    {
636        qxl_set_screen_pixmap_header (pScreen);
637
638        if ((surf = get_surface (pPixmap)))
639            qxl_surface_kill (surf);
640
641        set_surface (pPixmap, qxl->primary);
642    }
643
644    qxl_create_desired_modes (qxl);
645    qxl_update_edid (qxl);
646
647    qxl->screen_resources_created = TRUE;
648    return TRUE;
649}
650
651#ifdef XSPICE
652
653static void
654spiceqxl_screen_init (ScrnInfoPtr pScrn, qxl_screen_t *qxl)
655{
656    // Init spice
657    if (!qxl->spice_server)
658    {
659	qxl->spice_server = xspice_get_spice_server ();
660	xspice_set_spice_server_options (qxl->options);
661	qxl->core = basic_event_loop_init ();
662	if (spice_server_init (qxl->spice_server, qxl->core) < 0) {
663            ErrorF ("failed to initialize server\n");
664            abort ();
665        }
666	qxl_add_spice_display_interface (qxl);
667	qxl_add_spice_playback_interface (qxl);
668	qxl_add_spice_smartcard_interface (qxl);
669	spiceqxl_vdagent_init (qxl);
670    }
671    else
672    {
673        /* Crashes result from invalid xorg_timer pointers in
674           our watch lists because Xorg clears all timers at server reset.
675           We would require a fairly substantial revamp of how the
676           spice server is started and operated to avoid this crash.  */
677        ErrorF("WARNING: XSPICE requires -noreset; crashes are now likely.\n");
678    }
679
680    if (! qxl->worker_running)
681    {
682        xspice_register_handlers();
683        spice_server_vm_start(qxl->spice_server);
684	qxl->worker_running = TRUE;
685    }
686}
687
688#endif
689
690Bool
691qxl_fb_init (qxl_screen_t *qxl, ScreenPtr pScreen)
692{
693    ScrnInfoPtr pScrn = qxl->pScrn;
694
695    if (!fbScreenInit (pScreen, qxl_surface_get_host_bits(qxl->primary),
696                       pScrn->virtualX, pScrn->virtualY,
697                       pScrn->xDpi, pScrn->yDpi, pScrn->virtualX,
698                       pScrn->bitsPerPixel))
699	return FALSE;
700
701    fbPictureInit (pScreen, NULL, 0);
702    return TRUE;
703}
704
705static Bool
706qxl_screen_init (SCREEN_INIT_ARGS_DECL)
707{
708    ScrnInfoPtr    pScrn = xf86ScreenToScrn (pScreen);
709    qxl_screen_t * qxl = pScrn->driverPrivate;
710    struct QXLRam *ram_header;
711    VisualPtr      visual;
712
713    CHECK_POINT ();
714
715    assert (qxl->pScrn == pScrn);
716
717    if (!qxl_map_memory (qxl, pScrn->scrnIndex))
718	return FALSE;
719
720#ifdef XSPICE
721    spiceqxl_screen_init (pScrn, qxl);
722#endif
723    ram_header = (void *)((unsigned long)qxl->ram + (unsigned long)qxl->rom->ram_header_offset);
724
725    printf ("ram_header at %d\n", qxl->rom->ram_header_offset);
726    printf ("surf0 size: %d\n", qxl->rom->surface0_area_size);
727
728    qxl_save_state (pScrn);
729    qxl_blank_screen (pScreen, SCREEN_SAVER_ON);
730
731    miClearVisualTypes ();
732    if (!miSetVisualTypes (pScrn->depth, miGetDefaultVisualMask (pScrn->depth),
733                           pScrn->rgbBits, pScrn->defaultVisual))
734	goto out;
735    if (!miSetPixmapDepths ())
736	goto out;
737
738#if 0
739    ErrorF ("allocated %d x %d  %p\n", pScrn->virtualX, pScrn->virtualY, qxl->fb);
740#endif
741
742    /* Set up resources */
743    qxl_reset_and_create_mem_slots (qxl);
744    ErrorF ("done reset\n");
745
746    qxl->surface_cache = qxl_surface_cache_create (qxl);
747    qxl->primary = qxl_create_primary(qxl);
748
749    if (!qxl_fb_init (qxl, pScreen))
750	goto out;
751
752    visual = pScreen->visuals + pScreen->numVisuals;
753    while (--visual >= pScreen->visuals)
754    {
755	if ((visual->class | DynamicClass) == DirectColor)
756	{
757	    visual->offsetRed = pScrn->offset.red;
758	    visual->offsetGreen = pScrn->offset.green;
759	    visual->offsetBlue = pScrn->offset.blue;
760	    visual->redMask = pScrn->mask.red;
761	    visual->greenMask = pScrn->mask.green;
762	    visual->blueMask = pScrn->mask.blue;
763	}
764    }
765
766    qxl->command_ring = qxl_ring_create ((struct qxl_ring_header *)&(ram_header->cmd_ring),
767                                         sizeof (struct QXLCommand),
768                                         QXL_COMMAND_RING_SIZE, QXL_IO_NOTIFY_CMD, qxl);
769    qxl->cursor_ring = qxl_ring_create ((struct qxl_ring_header *)&(ram_header->cursor_ring),
770                                        sizeof (struct QXLCommand),
771                                        QXL_CURSOR_RING_SIZE, QXL_IO_NOTIFY_CURSOR, qxl);
772    qxl->release_ring = qxl_ring_create ((struct qxl_ring_header *)&(ram_header->release_ring),
773                                         sizeof (uint64_t),
774                                         QXL_RELEASE_RING_SIZE, 0, qxl);
775
776    /* xf86DPMSInit (pScreen, xf86DPMSSet, 0); */
777
778    pScreen->SaveScreen = qxl_blank_screen;
779
780    qxl_uxa_init (qxl, pScreen);
781
782    uxa_set_fallback_debug (pScreen, qxl->debug_render_fallbacks);
783
784    DamageSetup (pScreen);
785
786    /* We need to set totalPixmapSize after setup_uxa and Damage,
787       as the privates size is not computed correctly until then
788     */
789#if (XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 12, 99, 901, 0))
790    pScreen->totalPixmapSize = BitmapBytePad ((sizeof (PixmapRec) + dixPrivatesSize (PRIVATE_PIXMAP) ) * 8);
791#else
792    pScreen->totalPixmapSize = BitmapBytePad((sizeof(PixmapRec) +
793			    dixScreenSpecificPrivatesSize(pScreen, PRIVATE_PIXMAP) ) * 8);
794#endif
795
796    miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
797    if (!miCreateDefColormap (pScreen))
798        goto out;
799
800    qxl->create_screen_resources = pScreen->CreateScreenResources;
801    pScreen->CreateScreenResources = qxl_create_screen_resources;
802
803    qxl->close_screen = pScreen->CloseScreen;
804    pScreen->CloseScreen = qxl_close_screen;
805
806    qxl_cursor_init (pScreen);
807
808    CHECK_POINT ();
809
810    pScreen->width = qxl->primary_mode.x_res;
811    pScreen->height = qxl->primary_mode.y_res;
812
813    if (!xf86CrtcScreenInit (pScreen))
814	return FALSE;
815
816    if (!qxl_resize_primary_to_virtual (qxl))
817	return FALSE;
818
819    /* Note: this must be done after DamageSetup() because it calls
820     * _dixInitPrivates. And if that has been called, DamageSetup()
821     * will assert.
822     */
823    if (!uxa_resources_init (pScreen))
824	return FALSE;
825    CHECK_POINT ();
826
827    /* fake transform support, to allow agent to switch crtc mode */
828    /* without X doing checks, see rrcrtc.c "Check screen size */
829    /* bounds" */
830    xf86RandR12SetTransformSupport (pScreen, TRUE);
831
832    if (qxl->deferred_fps)
833        dfps_start_ticker(qxl);
834
835    return TRUE;
836
837out:
838    return FALSE;
839}
840
841static Bool
842qxl_enter_vt (VT_FUNC_ARGS_DECL)
843{
844    SCRN_INFO_PTR (arg);
845    qxl_screen_t *qxl = pScrn->driverPrivate;
846
847    qxl_save_state (pScrn);
848
849    qxl_reset_and_create_mem_slots (qxl);
850
851    if (!qxl_resize_primary_to_virtual (qxl))
852	return FALSE;
853
854    if (qxl->mem)
855    {
856	qxl_mem_free_all (qxl->mem);
857    }
858
859    if (qxl->surf_mem)
860	qxl_mem_free_all (qxl->surf_mem);
861
862    if (qxl->vt_surfaces)
863    {
864	qxl_surface_cache_replace_all (qxl->surface_cache, qxl->vt_surfaces);
865
866	qxl->vt_surfaces = NULL;
867    }
868
869    qxl_create_desired_modes (qxl);
870
871    pScrn->EnableDisableFBAccess (XF86_SCRN_ARG (pScrn), TRUE);
872
873    return TRUE;
874}
875
876static void
877qxl_leave_vt (VT_FUNC_ARGS_DECL)
878{
879    SCRN_INFO_PTR (arg);
880    qxl_screen_t *qxl = pScrn->driverPrivate;
881
882    xf86_hide_cursors (pScrn);
883
884    pScrn->EnableDisableFBAccess (XF86_SCRN_ARG (pScrn), FALSE);
885
886    if (qxl->deferred_fps <= 0)
887        qxl->vt_surfaces = qxl_surface_cache_evacuate_all (qxl->surface_cache);
888
889    ioport_write (qxl, QXL_IO_RESET, 0);
890
891    qxl_restore_state (pScrn);
892    qxl->device_primary = QXL_DEVICE_PRIMARY_NONE;
893}
894
895static Bool
896qxl_color_setup (ScrnInfoPtr pScrn)
897{
898    int   scrnIndex = pScrn->scrnIndex;
899    Gamma gzeros = { 0.0, 0.0, 0.0 };
900    rgb   rzeros = { 0, 0, 0 };
901
902    if (!xf86SetDepthBpp (pScrn, 0, 0, 0, Support32bppFb))
903	return FALSE;
904
905    if (pScrn->depth != 15 && pScrn->depth != 24)
906    {
907	xf86DrvMsg (scrnIndex, X_ERROR, "Depth %d is not supported\n",
908	            pScrn->depth);
909	return FALSE;
910    }
911    xf86PrintDepthBpp (pScrn);
912
913    if (!xf86SetWeight (pScrn, rzeros, rzeros))
914	return FALSE;
915
916    if (!xf86SetDefaultVisual (pScrn, -1))
917	return FALSE;
918
919    if (!xf86SetGamma (pScrn, gzeros))
920	return FALSE;
921
922    return TRUE;
923}
924
925static void
926print_modes (qxl_screen_t *qxl, int scrnIndex)
927{
928    int i;
929
930    for (i = 0; i < qxl->num_modes; ++i)
931    {
932	struct QXLMode *m = qxl->modes + i;
933
934	xf86DrvMsg (scrnIndex, X_INFO,
935	            "%d: %dx%d, %d bits, stride %d, %dmm x %dmm, orientation %d\n",
936	            m->id, m->x_res, m->y_res, m->bits, m->stride, m->x_mili,
937	            m->y_mili, m->orientation);
938    }
939}
940
941#ifndef XSPICE
942static Bool
943qxl_check_device (ScrnInfoPtr pScrn, qxl_screen_t *qxl)
944{
945    int            scrnIndex = pScrn->scrnIndex;
946    struct QXLRom *rom = qxl->rom;
947    struct QXLRam *ram_header = (void *)((unsigned long)qxl->ram + rom->ram_header_offset);
948
949    CHECK_POINT ();
950
951    if (rom->magic != 0x4f525851)   /* "QXRO" little-endian */
952    {
953	xf86DrvMsg (scrnIndex, X_ERROR, "Bad ROM signature %x\n", rom->magic);
954	return FALSE;
955    }
956
957    xf86DrvMsg (scrnIndex, X_INFO, "Device version %d.%d\n",
958                rom->id, rom->update_id);
959
960    xf86DrvMsg (scrnIndex, X_INFO, "Compression level %d, log level %d\n",
961                rom->compression_level,
962                rom->log_level);
963
964    xf86DrvMsg (scrnIndex, X_INFO, "%d io pages at 0x%lx\n",
965                rom->num_pages, (unsigned long)qxl->ram);
966
967    xf86DrvMsg (scrnIndex, X_INFO, "RAM header offset: 0x%x\n", rom->ram_header_offset);
968
969    if (ram_header->magic != 0x41525851)   /* "QXRA" little-endian */
970    {
971	xf86DrvMsg (scrnIndex, X_ERROR, "Bad RAM signature %x at %p\n",
972	            ram_header->magic,
973	            &ram_header->magic);
974	return FALSE;
975    }
976
977    xf86DrvMsg (scrnIndex, X_INFO, "Correct RAM signature %x\n",
978                ram_header->magic);
979    return TRUE;
980}
981
982#endif /* !XSPICE */
983
984Bool
985qxl_pre_init_common(ScrnInfoPtr pScrn)
986{
987    int           scrnIndex = pScrn->scrnIndex;
988    qxl_screen_t *qxl = pScrn->driverPrivate;
989
990    if (!qxl_color_setup (pScrn))
991	goto out;
992
993    /* option parsing and card differentiation */
994    xf86CollectOptions (pScrn, NULL);
995    memcpy (qxl->options, DefaultOptions, sizeof (DefaultOptions));
996    xf86ProcessOptions (scrnIndex, pScrn->options, qxl->options);
997
998    qxl->enable_image_cache =
999        get_bool_option (qxl->options, OPTION_ENABLE_IMAGE_CACHE, "QXL_ENABLE_IMAGE_CACHE");
1000    qxl->enable_fallback_cache =
1001        get_bool_option (qxl->options, OPTION_ENABLE_FALLBACK_CACHE, "QXL_ENABLE_FALLBACK_CACHE");
1002    qxl->enable_surfaces =
1003        get_bool_option (qxl->options, OPTION_ENABLE_SURFACES, "QXL_ENABLE_SURFACES");
1004    qxl->debug_render_fallbacks =
1005        get_bool_option (qxl->options, OPTION_DEBUG_RENDER_FALLBACKS, "QXL_DEBUG_RENDER_FALLBACKS");
1006    qxl->num_heads =
1007        get_int_option (qxl->options, OPTION_NUM_HEADS, "QXL_NUM_HEADS");
1008    if (qxl->num_heads == 0) {
1009        xf86DrvMsg (scrnIndex, X_INFO, "QXL_NUM_HEADS not configured, defaulting to 1\n");
1010        qxl->num_heads = 1;
1011    }
1012
1013    qxl->deferred_fps = get_int_option(qxl->options, OPTION_SPICE_DEFERRED_FPS, "XSPICE_DEFERRED_FPS");
1014    if (qxl->deferred_fps > 0)
1015        xf86DrvMsg(scrnIndex, X_INFO, "Deferred FPS: %d\n", qxl->deferred_fps);
1016    else
1017        xf86DrvMsg(scrnIndex, X_INFO, "Deferred Frames: Disabled\n");
1018
1019    xf86DrvMsg (scrnIndex, X_INFO, "Offscreen Surfaces: %s\n",
1020                qxl->enable_surfaces ? "Enabled" : "Disabled");
1021    xf86DrvMsg (scrnIndex, X_INFO, "Image Cache: %s\n",
1022                qxl->enable_image_cache ? "Enabled" : "Disabled");
1023    xf86DrvMsg (scrnIndex, X_INFO, "Fallback Cache: %s\n",
1024                qxl->enable_fallback_cache ? "Enabled" : "Disabled");
1025
1026    return TRUE;
1027out:
1028    return FALSE;
1029}
1030
1031static Bool
1032qxl_pre_init (ScrnInfoPtr pScrn, int flags)
1033{
1034    int           scrnIndex = pScrn->scrnIndex;
1035    qxl_screen_t *qxl = NULL;
1036    ClockRangePtr clockRanges = NULL;
1037    //int *linePitches = NULL;
1038    //DisplayModePtr mode;
1039    unsigned int max_x, max_y;
1040#ifdef XSPICE
1041    const char *playback_fifo_dir;
1042    const char *smartcard_file;
1043#endif
1044
1045    /* In X server 1.7.5, Xorg -configure will cause this
1046     * function to get called without a confScreen.
1047     */
1048    if (!pScrn->confScreen)
1049	return FALSE;
1050
1051    CHECK_POINT ();
1052
1053    qxl_mem_init();
1054
1055    /* zaphod mode is for suckers and i choose not to implement it */
1056    if (xf86IsEntityShared (pScrn->entityList[0]))
1057    {
1058	xf86DrvMsg (scrnIndex, X_ERROR, "No Zaphod mode for you\n");
1059	return FALSE;
1060    }
1061
1062    if (!pScrn->driverPrivate)
1063	pScrn->driverPrivate = xnfcalloc (sizeof (qxl_screen_t), 1);
1064
1065    qxl = pScrn->driverPrivate;
1066    qxl->device_primary = QXL_DEVICE_PRIMARY_UNDEFINED;
1067    qxl->pScrn = pScrn;
1068    qxl->x_modes = NULL;
1069    qxl->entity = xf86GetEntityInfo (pScrn->entityList[0]);
1070    qxl->kms_enabled = FALSE;
1071    xorg_list_init(&qxl->ums_bos);
1072
1073#ifndef XSPICE
1074    qxl->pci = xf86GetPciInfoForEntity (qxl->entity->index);
1075#ifndef XSERVER_LIBPCIACCESS
1076    qxl->pci_tag = pciTag (qxl->pci->bus, qxl->pci->device, qxl->pci->func);
1077#endif
1078    if (qxl->pci->revision < 4)
1079    {
1080	ErrorF ("Ignoring monitor config, device revision < 4\n");
1081    }
1082#endif /* XSPICE */
1083    pScrn->monitor = pScrn->confScreen->monitor;
1084
1085    qxl_ums_setup_funcs(qxl);
1086
1087    if (!qxl_pre_init_common(pScrn))
1088	goto out;
1089
1090#ifdef XSPICE
1091    playback_fifo_dir = get_str_option(qxl->options, OPTION_SPICE_PLAYBACK_FIFO_DIR,
1092               "XSPICE_PLAYBACK_FIFO_DIR");
1093    if (playback_fifo_dir)
1094        strncpy(qxl->playback_fifo_dir, playback_fifo_dir, sizeof(qxl->playback_fifo_dir));
1095    else
1096        qxl->playback_fifo_dir[0] = '\0';
1097
1098    smartcard_file = get_str_option(qxl->options, OPTION_SPICE_SMARTCARD_FILE,
1099               "XSPICE_SMARTCARD_FILE");
1100    if (smartcard_file)
1101        strncpy(qxl->smartcard_file, smartcard_file, sizeof(qxl->smartcard_file));
1102    else
1103        qxl->smartcard_file[0] = '\0';
1104
1105    qxl->surface0_size =
1106        get_int_option (qxl->options, OPTION_FRAME_BUFFER_SIZE, "QXL_FRAME_BUFFER_SIZE") << 20L;
1107    qxl->vram_size =
1108        get_int_option (qxl->options, OPTION_SURFACE_BUFFER_SIZE, "QXL_SURFACE_BUFFER_SIZE") << 20L;
1109    qxl->ram_size =
1110        get_int_option (qxl->options, OPTION_COMMAND_BUFFER_SIZE, "QXL_COMMAND_BUFFER_SIZE") << 20L;
1111#endif
1112
1113    if (!qxl_map_memory (qxl, scrnIndex))
1114	goto out;
1115
1116#ifndef XSPICE
1117    if (!qxl_check_device (pScrn, qxl))
1118	goto out;
1119#else
1120    xspice_init_qxl_ram (qxl); /* initialize the rings */
1121#endif
1122
1123#define DIV_ROUND_UP(n, a) (((n) + (a) - 1) / (a))
1124#define BYTES_TO_KB(bytes) DIV_ROUND_UP(bytes, 1024)
1125#define PAGES_TO_KB(pages) ((pages) * getpagesize() / 1024)
1126
1127    pScrn->videoRam = PAGES_TO_KB(qxl->rom->num_pages)
1128                      - BYTES_TO_KB(qxl->monitors_config_size);
1129    xf86DrvMsg (scrnIndex, X_INFO, "%d KB of video RAM\n", pScrn->videoRam);
1130    xf86DrvMsg (scrnIndex, X_INFO, "%d surfaces\n", qxl->rom->n_surfaces);
1131
1132    /* ddc stuff here */
1133
1134    clockRanges = xnfcalloc (sizeof (ClockRange), 1);
1135    clockRanges->next = NULL;
1136    clockRanges->minClock = 10000;
1137    clockRanges->maxClock = 400000;
1138    clockRanges->clockIndex = -1;
1139    clockRanges->interlaceAllowed = clockRanges->doubleScanAllowed = 0;
1140    clockRanges->ClockMulFactor = clockRanges->ClockDivFactor = 1;
1141    pScrn->progClock = TRUE;
1142
1143    /* override QXL monitor stuff */
1144    if (pScrn->monitor->nHsync <= 0)
1145    {
1146	pScrn->monitor->hsync[0].lo =  29.0;
1147	pScrn->monitor->hsync[0].hi = 160.0;
1148	pScrn->monitor->nHsync = 1;
1149    }
1150    if (pScrn->monitor->nVrefresh <= 0)
1151    {
1152	pScrn->monitor->vrefresh[0].lo = 50;
1153	pScrn->monitor->vrefresh[0].hi = 75;
1154	pScrn->monitor->nVrefresh = 1;
1155    }
1156
1157    qxl_initialize_x_modes (qxl, pScrn, &max_x, &max_y);
1158
1159    CHECK_POINT ();
1160
1161    xf86PruneDriverModes (pScrn);
1162
1163    qxl_init_randr (pScrn, qxl);
1164
1165    xf86SetDpi (pScrn, 0, 0);
1166
1167    if (!xf86LoadSubModule (pScrn, "fb")
1168#ifndef XSPICE
1169        || !xf86LoadSubModule (pScrn, "ramdac")
1170        || !xf86LoadSubModule (pScrn, "vgahw")
1171#endif
1172        )
1173    {
1174	goto out;
1175    }
1176
1177    print_modes (qxl, scrnIndex);
1178
1179#ifndef XSPICE
1180    /* VGA hardware initialisation */
1181    if (!vgaHWGetHWRec (pScrn))
1182	return FALSE;
1183    vgaHWSetStdFuncs (VGAHWPTR (pScrn));
1184#endif
1185
1186    /* hate */
1187    qxl_unmap_memory (qxl);
1188
1189    CHECK_POINT ();
1190
1191    xf86DrvMsg (scrnIndex, X_INFO, "PreInit complete\n");
1192#ifdef GIT_VERSION
1193    xf86DrvMsg (scrnIndex, X_INFO, "git commit %s\n", GIT_VERSION);
1194#endif
1195    return TRUE;
1196
1197out:
1198    if (clockRanges)
1199	free (clockRanges);
1200    if (qxl)
1201	free (qxl);
1202
1203    return FALSE;
1204}
1205
1206#ifndef XSPICE
1207#ifdef XSERVER_LIBPCIACCESS
1208enum qxl_class
1209{
1210    CHIP_QXL_1,
1211};
1212
1213static const struct pci_id_match qxl_device_match[] = {
1214    {
1215	PCI_VENDOR_RED_HAT, PCI_CHIP_QXL_0100, PCI_MATCH_ANY, PCI_MATCH_ANY,
1216	0x00000000, 0x00000000, CHIP_QXL_1
1217    },
1218    {
1219	PCI_VENDOR_RED_HAT, PCI_CHIP_QXL_01FF, PCI_MATCH_ANY, PCI_MATCH_ANY,
1220	0x00000000, 0x00000000, CHIP_QXL_1
1221    },
1222
1223    { 0 },
1224};
1225#endif
1226
1227static SymTabRec qxlChips[] = {
1228    { PCI_CHIP_QXL_0100, "QXL 1", },
1229    { -1, NULL }
1230};
1231
1232#ifndef XSERVER_LIBPCIACCESS
1233static PciChipsets qxlPciChips[] = {
1234    { PCI_CHIP_QXL_0100, PCI_CHIP_QXL_0100, RES_SHARED_VGA },
1235    { -1, -1, RES_UNDEFINED }
1236};
1237#endif
1238#endif /* !XSPICE */
1239
1240static void
1241qxl_identify (int flags)
1242{
1243#ifndef XSPICE
1244    xf86PrintChipsets ("qxl", "Driver for QXL virtual graphics", qxlChips);
1245#endif
1246}
1247
1248static void
1249qxl_init_scrn (ScrnInfoPtr pScrn, Bool kms)
1250{
1251    pScrn->driverVersion    = 0;
1252    pScrn->driverName       = driver_name;
1253    pScrn->name             = driver_name;
1254
1255    if (kms) {
1256#if !defined(XSPICE) && defined(XF86DRM_MODE)
1257	pScrn->PreInit          = qxl_pre_init_kms;
1258	pScrn->ScreenInit       = qxl_screen_init_kms;
1259	pScrn->EnterVT          = qxl_enter_vt_kms;
1260	pScrn->LeaveVT          = qxl_leave_vt_kms;
1261#endif
1262    } else {
1263	pScrn->PreInit          = qxl_pre_init;
1264	pScrn->ScreenInit       = qxl_screen_init;
1265	pScrn->EnterVT          = qxl_enter_vt;
1266	pScrn->LeaveVT          = qxl_leave_vt;
1267    }
1268    pScrn->SwitchMode       = qxl_switch_mode;
1269    pScrn->ValidMode        = NULL;
1270}
1271
1272#if defined(XF86DRM_MODE) && !defined(XSPICE)
1273static char *
1274CreatePCIBusID(const struct pci_device *dev)
1275{
1276    char *busID;
1277
1278    if (asprintf(&busID, "pci:%04x:%02x:%02x.%d",
1279                 dev->domain, dev->bus, dev->dev, dev->func) == -1)
1280        return NULL;
1281
1282    return busID;
1283}
1284
1285static Bool qxl_kernel_mode_enabled(ScrnInfoPtr pScrn, struct pci_device *pci_dev)
1286{
1287    char *busIdString;
1288    int ret;
1289
1290    busIdString = CreatePCIBusID(pci_dev);
1291    ret = drmCheckModesettingSupported(busIdString);
1292    free(busIdString);
1293    if (ret) {
1294      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
1295		   "[KMS] drm report modesetting isn't supported.\n");
1296	return FALSE;
1297    }
1298
1299    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
1300		   "[KMS] Kernel modesetting enabled.\n");
1301    return TRUE;
1302}
1303#else
1304#define qxl_kernel_mode_enabled(x, y) FALSE
1305#endif
1306
1307#ifdef XSPICE
1308static Bool
1309qxl_probe (struct _DriverRec *drv, int flags)
1310{
1311    ScrnInfoPtr   pScrn;
1312    int           entityIndex;
1313    EntityInfoPtr pEnt;
1314    GDevPtr*      device;
1315
1316    if (flags & PROBE_DETECT)
1317	return TRUE;
1318
1319    pScrn = xf86AllocateScreen (drv, flags);
1320    qxl_init_scrn (pScrn, FALSE);
1321
1322    xf86MatchDevice (driver_name, &device);
1323    entityIndex = xf86ClaimNoSlot (drv, 0, device[0], TRUE);
1324    pEnt = xf86GetEntityInfo (entityIndex);
1325    pEnt->driver = drv;
1326
1327    xf86AddEntityToScreen (pScrn, entityIndex);
1328
1329    return TRUE;
1330}
1331
1332#else /* normal, not XSPICE */
1333#ifndef XSERVER_LIBPCIACCESS
1334static Bool
1335qxl_probe (DriverPtr drv, int flags)
1336{
1337    int      i, numUsed;
1338    int      numDevSections;
1339    int *    usedChips;
1340    GDevPtr *devSections;
1341
1342    if ((numDevSections = xf86MatchDevice (QXL_NAME, &devSections)) <= 0)
1343	return FALSE;
1344
1345    if (!xf86GetPciVideoInfo ())
1346	return FALSE;
1347
1348    numUsed = xf86MatchPciInstances (QXL_NAME, PCI_VENDOR_RED_HAT,
1349                                     qxlChips, qxlPciChips,
1350                                     devSections, numDevSections,
1351                                     drv, &usedChips);
1352
1353    xfree (devSections);
1354
1355    if (numUsed < 0)
1356    {
1357	xfree (usedChips);
1358	return FALSE;
1359    }
1360
1361    if (flags & PROBE_DETECT)
1362    {
1363	xfree (usedChips);
1364	return TRUE;
1365    }
1366
1367    for (i = 0; i < numUsed; i++)
1368    {
1369	ScrnInfoPtr pScrn = NULL;
1370	if ((pScrn = xf86ConfigPciEntity (pScrn, 0, usedChips[i], qxlPciChips,
1371	                                  0, 0, 0, 0, 0)))
1372	    qxl_init_scrn (pScrn, FALSE);
1373    }
1374
1375    xfree (usedChips);
1376    return TRUE;
1377}
1378
1379#else /* pciaccess */
1380
1381static Bool
1382qxl_pci_probe (DriverPtr drv, int entity, struct pci_device *dev, intptr_t match)
1383{
1384    qxl_screen_t *qxl;
1385    ScrnInfoPtr   pScrn = xf86ConfigPciEntity (NULL, 0, entity, NULL, NULL,
1386                                               NULL, NULL, NULL, NULL);
1387    Bool kms = FALSE;
1388
1389    if (!pScrn)
1390	return FALSE;
1391
1392    if (dev) {
1393	if (qxl_kernel_mode_enabled(pScrn, dev)) {
1394	    kms = TRUE;
1395	}
1396    }
1397
1398    if (!pScrn->driverPrivate)
1399	pScrn->driverPrivate = xnfcalloc (sizeof (qxl_screen_t), 1);
1400    qxl = pScrn->driverPrivate;
1401    qxl->pci = dev;
1402
1403    qxl_init_scrn (pScrn, kms);
1404
1405    return TRUE;
1406}
1407
1408#define qxl_probe NULL
1409
1410#endif
1411
1412#ifdef XSERVER_PLATFORM_BUS
1413static Bool
1414qxl_platform_probe(DriverPtr driver, int entity, int flags,
1415                   struct xf86_platform_device *dev, intptr_t match_data)
1416{
1417    qxl_screen_t *qxl;
1418    ScrnInfoPtr pScrn;
1419    int scrnFlag = 0;
1420
1421    if (!dev->pdev)
1422        return FALSE;
1423
1424    if (flags & PLATFORM_PROBE_GPU_SCREEN)
1425        scrnFlag = XF86_ALLOCATE_GPU_SCREEN;
1426
1427    pScrn = xf86AllocateScreen(driver, scrnFlag);
1428    if (!pScrn)
1429	return FALSE;
1430
1431    if (xf86IsEntitySharable(entity))
1432        xf86SetEntityShared(entity);
1433
1434    xf86AddEntityToScreen(pScrn, entity);
1435
1436    qxl = pScrn->driverPrivate = xnfcalloc (sizeof (qxl_screen_t), 1);
1437    qxl->pci = dev->pdev;
1438    qxl->platform_dev = dev;
1439
1440    qxl_init_scrn (pScrn, qxl_kernel_mode_enabled(pScrn, dev->pdev));
1441
1442    return TRUE;
1443}
1444#endif /* XSERVER_PLATFORM_BUS */
1445
1446#endif /* XSPICE */
1447
1448static Bool
1449qxl_driver_func(ScrnInfoPtr pScrn, xorgDriverFuncOp op, void *data)
1450{
1451    xorgHWFlags *hw_flags;
1452
1453    switch (op) {
1454    case GET_REQUIRED_HW_INTERFACES:
1455        hw_flags = data;
1456#ifdef XSPICE
1457        *hw_flags = HW_SKIP_CONSOLE;
1458#else
1459        *hw_flags = HW_IO | HW_MMIO;
1460#endif
1461        return TRUE;
1462#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,902,0)
1463    case SUPPORTS_SERVER_FDS:
1464        return TRUE;
1465#endif
1466    default:
1467        return FALSE;
1468    }
1469}
1470
1471static DriverRec qxl_driver = {
1472    0,
1473    driver_name,
1474    qxl_identify,
1475    qxl_probe,
1476    qxl_available_options,
1477    NULL,
1478    0,
1479    qxl_driver_func,
1480#ifdef XSPICE
1481    NULL,
1482    NULL,
1483    NULL,
1484#else
1485#ifdef XSERVER_LIBPCIACCESS
1486    qxl_device_match,
1487    qxl_pci_probe,
1488#else
1489    NULL,
1490    NULL,
1491#endif
1492#ifdef XSERVER_PLATFORM_BUS
1493    qxl_platform_probe,
1494#else
1495    NULL,
1496#endif
1497#endif /* XSPICE */
1498};
1499
1500static pointer
1501qxl_setup (pointer module, pointer opts, int *errmaj, int *errmin)
1502{
1503    static Bool loaded = FALSE;
1504
1505    if (!loaded)
1506    {
1507	loaded = TRUE;
1508	xf86AddDriver (&qxl_driver, module, HaveDriverFuncs);
1509#ifdef XSPICE
1510	xspice_add_input_drivers (module);
1511#endif
1512	return (void *)1;
1513    }
1514    else
1515    {
1516	if (errmaj)
1517	    *errmaj = LDR_ONCEONLY;
1518
1519	return NULL;
1520    }
1521}
1522
1523static XF86ModuleVersionInfo qxl_module_info =
1524{
1525    driver_name,
1526    MODULEVENDORSTRING,
1527    MODINFOSTRING1,
1528    MODINFOSTRING2,
1529    XORG_VERSION_CURRENT,
1530    PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
1531    ABI_CLASS_VIDEODRV,
1532    ABI_VIDEODRV_VERSION,
1533    MOD_CLASS_VIDEODRV,
1534    { 0, 0, 0, 0 }
1535};
1536
1537_X_EXPORT XF86ModuleData
1538#ifdef XSPICE
1539spiceqxlModuleData
1540#else
1541qxlModuleData
1542#endif
1543= {
1544    &qxl_module_info,
1545    qxl_setup,
1546    NULL
1547};
1548