1 #define DEBUG_VERB 2
2 /*
3 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
4 * Copyright 2008 Red Hat, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
21 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * Except as contained in this notice, the name of Conectiva Linux shall
25 * not be used in advertising or otherwise to promote the sale, use or other
26 * dealings in this Software without prior written authorization from
27 * Conectiva Linux.
28 *
29 * Authors: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
30 * David Dawes <dawes@xfree86.org>
31 * Adam Jackson <ajax@redhat.com>
32 */
33
34 /*
35 * TODO:
36 * - Port to RANDR 1.2 setup to make mode selection slightly better
37 * - Port to RANDR 1.2 to drop the old-school DGA junk
38 * - VBE/SCI for secondary DDC method?
39 */
40
41 #ifdef HAVE_CONFIG_H
42 #include "config.h"
43 #endif
44
45 #include <string.h>
46 #include <unistd.h>
47 #include "vesa.h"
48
49 /* All drivers initialising the SW cursor need this */
50 #include "mipointer.h"
51
52 /* Colormap handling */
53 #include "micmap.h"
54 #include "xf86cmap.h"
55 #include "xf86Modes.h"
56
57 /* DPMS */
58 #ifdef HAVE_XEXTPROTO_71
59 #include <X11/extensions/dpmsconst.h>
60 #else
61 #define DPMS_SERVER
62 #include <X11/extensions/dpms.h>
63 #endif
64 #include "compat-api.h"
65
66 /* Mandatory functions */
67 static const OptionInfoRec * VESAAvailableOptions(int chipid, int busid);
68 static void VESAIdentify(int flags);
69 #if defined(XSERVER_LIBPCIACCESS) && !defined(HAVE_ISA)
70 #define VESAProbe NULL
71 #else
72 static Bool VESAProbe(DriverPtr drv, int flags);
73 #endif
74 #ifdef XSERVER_LIBPCIACCESS
75 static Bool VESAPciProbe(DriverPtr drv, int entity_num,
76 struct pci_device *dev, intptr_t match_data);
77 #endif
78 static Bool VESAPreInit(ScrnInfoPtr pScrn, int flags);
79 static Bool VESAScreenInit(SCREEN_INIT_ARGS_DECL);
80 static Bool VESAEnterVT(VT_FUNC_ARGS_DECL);
81 static void VESALeaveVT(VT_FUNC_ARGS_DECL);
82 static Bool VESACloseScreen(CLOSE_SCREEN_ARGS_DECL);
83 static Bool VESASaveScreen(ScreenPtr pScreen, int mode);
84
85 static Bool VESASwitchMode(SWITCH_MODE_ARGS_DECL);
86 static Bool VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
87 static void VESAAdjustFrame(ADJUST_FRAME_ARGS_DECL);
88 static void VESAFreeScreen(FREE_SCREEN_ARGS_DECL);
89 static void VESAFreeRec(ScrnInfoPtr pScrn);
90 static VESAPtr VESAGetRec(ScrnInfoPtr pScrn);
91
92 static void
93 VESADisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
94 int flags);
95
96 /* locally used functions */
97 #ifdef HAVE_ISA
98 static int VESAFindIsaDevice(GDevPtr dev);
99 #endif
100 static Bool VESAMapVidMem(ScrnInfoPtr pScrn);
101 static void VESAUnmapVidMem(ScrnInfoPtr pScrn);
102 static int VESABankSwitch(ScreenPtr pScreen, unsigned int iBank);
103 static void VESALoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
104 LOCO *colors, VisualPtr pVisual);
105 static void SaveFonts(ScrnInfoPtr pScrn);
106 static void RestoreFonts(ScrnInfoPtr pScrn);
107 static Bool
108 VESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function);
109
110 static void *
VESAWindowLinear(ScreenPtr pScreen,CARD32 row,CARD32 offset,int mode,CARD32 * size,void * closure)111 VESAWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode,
112 CARD32 *size, void *closure)
113 {
114 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
115 VESAPtr pVesa = VESAGetRec(pScrn);
116
117 *size = pVesa->maxBytesPerScanline;
118 return ((CARD8 *)pVesa->base + row * pVesa->maxBytesPerScanline + offset);
119 }
120
121 static void *
VESAWindowWindowed(ScreenPtr pScreen,CARD32 row,CARD32 offset,int mode,CARD32 * size,void * closure)122 VESAWindowWindowed(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode,
123 CARD32 *size, void *closure)
124 {
125 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
126 VESAPtr pVesa = VESAGetRec(pScrn);
127 VbeModeInfoBlock *data = ((VbeModeInfoData*)(pScrn->currentMode->Private))->data;
128 int window;
129
130 offset += pVesa->maxBytesPerScanline * row;
131 window = offset / (data->WinGranularity * 1024);
132 pVesa->windowAoffset = window * data->WinGranularity * 1024;
133 VESABankSwitch(pScreen, window);
134 *size = data->WinSize * 1024 - (offset - pVesa->windowAoffset);
135
136 return (void *)((unsigned long)pVesa->base +
137 (offset - pVesa->windowAoffset));
138 }
139
140 static void
vesaUpdatePacked(ScreenPtr pScreen,shadowBufPtr pBuf)141 vesaUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
142 {
143 shadowUpdatePacked(pScreen, pBuf);
144 }
145
146 static Bool VESADGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen);
147
148 enum GenericTypes
149 {
150 CHIP_VESA_GENERIC
151 };
152
153 #ifdef XSERVER_LIBPCIACCESS
154 static const struct pci_id_match vesa_device_match[] = {
155 {
156 PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY,
157 0x00030000, 0x00ffffff, CHIP_VESA_GENERIC
158 },
159
160 { 0, 0, 0 },
161 };
162 #endif
163
164 /* Supported chipsets */
165 static SymTabRec VESAChipsets[] =
166 {
167 {CHIP_VESA_GENERIC, "vesa"},
168 {-1, NULL}
169 };
170
171 #ifndef XSERVER_LIBPCIACCESS
172 static PciChipsets VESAPCIchipsets[] = {
173 { CHIP_VESA_GENERIC, PCI_CHIP_VGA, RES_SHARED_VGA },
174 { -1, -1, RES_UNDEFINED },
175 };
176 #endif
177
178 #ifdef HAVE_ISA
179 static IsaChipsets VESAISAchipsets[] = {
180 {CHIP_VESA_GENERIC, RES_EXCLUSIVE_VGA},
181 {-1, 0 }
182 };
183 #endif
184
185
186 /*
187 * This contains the functions needed by the server after loading the
188 * driver module. It must be supplied, and gets added the driver list by
189 * the Module Setup funtion in the dynamic case. In the static case a
190 * reference to this is compiled in, and this requires that the name of
191 * this DriverRec be an upper-case version of the driver name.
192 */
193 _X_EXPORT DriverRec VESA = {
194 VESA_VERSION,
195 VESA_DRIVER_NAME,
196 VESAIdentify,
197 VESAProbe,
198 VESAAvailableOptions,
199 NULL,
200 0,
201 NULL,
202
203 #ifdef XSERVER_LIBPCIACCESS
204 vesa_device_match,
205 VESAPciProbe
206 #endif
207 };
208
209
210 typedef enum {
211 OPTION_SHADOW_FB,
212 OPTION_DFLT_REFRESH,
213 OPTION_MODESET_CLEAR_SCREEN
214 } VESAOpts;
215
216 static const OptionInfoRec VESAOptions[] = {
217 { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE },
218 { OPTION_DFLT_REFRESH, "DefaultRefresh", OPTV_BOOLEAN, {0}, FALSE },
219 { OPTION_MODESET_CLEAR_SCREEN, "ModeSetClearScreen",
220 OPTV_BOOLEAN, {0}, FALSE },
221 { -1, NULL, OPTV_NONE, {0}, FALSE }
222 };
223
224 #ifdef XFree86LOADER
225
226 /* Module loader interface */
227 static MODULESETUPPROTO(vesaSetup);
228
229 static XF86ModuleVersionInfo vesaVersionRec =
230 {
231 VESA_DRIVER_NAME,
232 MODULEVENDORSTRING,
233 MODINFOSTRING1,
234 MODINFOSTRING2,
235 XORG_VERSION_CURRENT,
236 VESA_MAJOR_VERSION, VESA_MINOR_VERSION, VESA_PATCHLEVEL,
237 ABI_CLASS_VIDEODRV, /* This is a video driver */
238 ABI_VIDEODRV_VERSION,
239 MOD_CLASS_VIDEODRV,
240 {0, 0, 0, 0}
241 };
242
243 /*
244 * This data is accessed by the loader. The name must be the module name
245 * followed by "ModuleData".
246 */
247 _X_EXPORT XF86ModuleData vesaModuleData = { &vesaVersionRec, vesaSetup, NULL };
248
249 static pointer
vesaSetup(pointer Module,pointer Options,int * ErrorMajor,int * ErrorMinor)250 vesaSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
251 {
252 static Bool Initialised = FALSE;
253
254 if (!Initialised)
255 {
256 Initialised = TRUE;
257 xf86AddDriver(&VESA, Module, 1);
258 return (pointer)TRUE;
259 }
260
261 if (ErrorMajor)
262 *ErrorMajor = LDR_ONCEONLY;
263 return (NULL);
264 }
265
266 #endif
267
268 static const OptionInfoRec *
VESAAvailableOptions(int chipid,int busid)269 VESAAvailableOptions(int chipid, int busid)
270 {
271 return (VESAOptions);
272 }
273
274 static void
VESAIdentify(int flags)275 VESAIdentify(int flags)
276 {
277 xf86PrintChipsets(VESA_NAME, "driver for VESA chipsets", VESAChipsets);
278 }
279
280 static VESAPtr
VESAGetRec(ScrnInfoPtr pScrn)281 VESAGetRec(ScrnInfoPtr pScrn)
282 {
283 if (!pScrn->driverPrivate)
284 pScrn->driverPrivate = calloc(sizeof(VESARec), 1);
285
286 return ((VESAPtr)pScrn->driverPrivate);
287 }
288
289 /* Only a little like VBESetModeParameters */
290 static void
VESASetModeParameters(vbeInfoPtr pVbe,DisplayModePtr vbemode,DisplayModePtr ddcmode)291 VESASetModeParameters(vbeInfoPtr pVbe, DisplayModePtr vbemode,
292 DisplayModePtr ddcmode)
293 {
294 VbeModeInfoData *data;
295 int clock;
296
297 data = (VbeModeInfoData *)vbemode->Private;
298
299 data->block = calloc(sizeof(VbeCRTCInfoBlock), 1);
300 data->block->HorizontalTotal = ddcmode->HTotal;
301 data->block->HorizontalSyncStart = ddcmode->HSyncStart;
302 data->block->HorizontalSyncEnd = ddcmode->HSyncEnd;
303 data->block->VerticalTotal = ddcmode->VTotal;
304 data->block->VerticalSyncStart = ddcmode->VSyncStart;
305 data->block->VerticalSyncEnd = ddcmode->VSyncEnd;
306 data->block->Flags = ((ddcmode->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) |
307 ((ddcmode->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0);
308 data->block->PixelClock = ddcmode->Clock * 1000;
309
310 /* ask the BIOS to figure out the real clock */
311 clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock);
312 if (clock)
313 data->block->PixelClock = clock;
314
315 data->mode |= (1 << 11);
316 data->block->RefreshRate = 100 * ((double)(data->block->PixelClock) /
317 (double)(ddcmode->HTotal * ddcmode->VTotal));
318 }
319
320 /*
321 * Despite that VBE gives you pixel granularity for mode sizes, some BIOSes
322 * think they can only give sizes in multiples of character cells; and
323 * indeed, the reference CVT and GTF formulae only give results where
324 * (h % 8) == 0. Whatever, let's just try to cope. What we're looking for
325 * here is cases where the display says 1366x768 and the BIOS says 1360x768.
326 */
327 static Bool
vesaModesCloseEnough(DisplayModePtr edid,DisplayModePtr vbe)328 vesaModesCloseEnough(DisplayModePtr edid, DisplayModePtr vbe)
329 {
330 if (!(edid->type & M_T_DRIVER))
331 return FALSE;
332
333 /* never seen a height granularity... */
334 if (edid->VDisplay != vbe->VDisplay)
335 return FALSE;
336
337 if (edid->HDisplay >= vbe->HDisplay &&
338 (edid->HDisplay & ~7) == (vbe->HDisplay & ~7))
339 return TRUE;
340
341 return FALSE;
342 }
343
344 static ModeStatus
VESAValidMode(SCRN_ARG_TYPE arg,DisplayModePtr p,Bool flag,int pass)345 VESAValidMode(SCRN_ARG_TYPE arg, DisplayModePtr p, Bool flag, int pass)
346 {
347 SCRN_INFO_PTR(arg);
348 static int warned = 0;
349 int found = 0;
350 VESAPtr pVesa = VESAGetRec(pScrn);
351 MonPtr mon = pScrn->monitor;
352 ModeStatus ret = MODE_BAD;
353 DisplayModePtr mode;
354 float v;
355
356 pVesa = VESAGetRec(pScrn);
357
358 if (pass != MODECHECK_FINAL) {
359 if (!warned) {
360 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VESAValidMode called unexpectedly\n");
361 warned = 1;
362 }
363 return MODE_OK;
364 }
365
366 /*
367 * This is suboptimal. We pass in just the barest description of a mode
368 * we can get away with to VBEValidateModes, so it can't really throw
369 * out anything we give it. But we need to filter the list so that we
370 * don't populate the mode list with things the monitor can't do.
371 *
372 * So first off, if this isn't a mode we handed to the server (ie,
373 * M_T_BUILTIN), then we know we can't do it.
374 */
375 if (!(p->type & M_T_BUILTIN))
376 return MODE_NOMODE;
377
378 if (pVesa->strict_validation) {
379 /*
380 * If it's our first pass at mode validation, we'll try for a strict
381 * intersection between the VBE and DDC mode lists.
382 */
383 if (pScrn->monitor->DDC) {
384 for (mode = pScrn->monitor->Modes; mode; mode = mode->next) {
385 if (vesaModesCloseEnough(mode, p)) {
386 if (xf86CheckModeForMonitor(mode, mon) == MODE_OK) {
387 found = 1;
388 break;
389 }
390 }
391 if (mode == pScrn->monitor->Last)
392 break;
393 }
394 if (!found)
395 return MODE_NOMODE;
396
397 /* having found a matching mode, stash the CRTC values aside */
398 VESASetModeParameters(pVesa->pVbe, p, mode);
399 return MODE_OK;
400 }
401
402 /* No DDC and no modes make Homer something something... */
403 return MODE_NOMODE;
404 }
405
406 /*
407 * Finally, walk through the vsync rates 1Hz at a time looking for a mode
408 * that will fit. This is assuredly a terrible way to do this, but
409 * there's no obvious method for computing a mode of a given size that
410 * will pass xf86CheckModeForMonitor. XXX this path is terrible, but
411 * then, by this point, you're well into despair territory.
412 */
413 for (v = mon->vrefresh[0].lo; v <= mon->vrefresh[0].hi; v++) {
414 mode = xf86GTFMode(p->HDisplay, p->VDisplay, v, 0, 0);
415 ret = xf86CheckModeForMonitor(mode, mon);
416 free(mode->name);
417 free(mode);
418 if (ret == MODE_OK)
419 break;
420 }
421
422 return ret;
423 }
424
425 static void
VESAInitScrn(ScrnInfoPtr pScrn)426 VESAInitScrn(ScrnInfoPtr pScrn)
427 {
428 pScrn->driverVersion = VESA_VERSION;
429 pScrn->driverName = VESA_DRIVER_NAME;
430 pScrn->name = VESA_NAME;
431 pScrn->Probe = VESAProbe;
432 pScrn->PreInit = VESAPreInit;
433 pScrn->ScreenInit = VESAScreenInit;
434 pScrn->SwitchMode = VESASwitchMode;
435 pScrn->ValidMode = VESAValidMode;
436 pScrn->AdjustFrame = VESAAdjustFrame;
437 pScrn->EnterVT = VESAEnterVT;
438 pScrn->LeaveVT = VESALeaveVT;
439 pScrn->FreeScreen = VESAFreeScreen;
440 }
441
442 /*
443 * This function is called once, at the start of the first server generation to
444 * do a minimal probe for supported hardware.
445 */
446
447 #ifdef XSERVER_LIBPCIACCESS
448 static Bool
VESAPciProbe(DriverPtr drv,int entity_num,struct pci_device * dev,intptr_t match_data)449 VESAPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev,
450 intptr_t match_data)
451 {
452 ScrnInfoPtr pScrn;
453
454 #ifdef __linux__
455 if (access("/sys/devices/platform/efi-framebuffer.0", F_OK) == 0 ||
456 access("/sys/devices/platform/efifb.0", F_OK) == 0) {
457 ErrorF("vesa: Refusing to run on UEFI\n");
458 return FALSE;
459 }
460 #endif
461
462 pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, NULL,
463 NULL, NULL, NULL, NULL, NULL);
464 if (pScrn != NULL) {
465 VESAPtr pVesa;
466
467 if (pci_device_has_kernel_driver(dev)) {
468 ErrorF("vesa: Ignoring device with a bound kernel driver\n");
469 return FALSE;
470 }
471
472 pVesa = VESAGetRec(pScrn);
473 VESAInitScrn(pScrn);
474 pVesa->pciInfo = dev;
475 }
476
477 return (pScrn != NULL);
478 }
479 #endif
480
481 #ifndef VESAProbe
482 static Bool
VESAProbe(DriverPtr drv,int flags)483 VESAProbe(DriverPtr drv, int flags)
484 {
485 Bool foundScreen = FALSE;
486 int numDevSections, numUsed;
487 GDevPtr *devSections;
488 int *usedChips;
489 int i;
490
491 /*
492 * Find the config file Device sections that match this
493 * driver, and return if there are none.
494 */
495 if ((numDevSections = xf86MatchDevice(VESA_NAME,
496 &devSections)) <= 0)
497 return (FALSE);
498
499 #ifndef XSERVER_LIBPCIACCESS
500 /* PCI BUS */
501 if (xf86GetPciVideoInfo()) {
502 numUsed = xf86MatchPciInstances(VESA_NAME, PCI_VENDOR_GENERIC,
503 VESAChipsets, VESAPCIchipsets,
504 devSections, numDevSections,
505 drv, &usedChips);
506 if (numUsed > 0) {
507 if (flags & PROBE_DETECT)
508 foundScreen = TRUE;
509 else {
510 for (i = 0; i < numUsed; i++) {
511 ScrnInfoPtr pScrn = NULL;
512 /* Allocate a ScrnInfoRec */
513 if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],
514 VESAPCIchipsets,NULL,
515 NULL,NULL,NULL,NULL))) {
516 VESAInitScrn(pScrn);
517 foundScreen = TRUE;
518 }
519 }
520 }
521 free(usedChips);
522 }
523 }
524 #endif
525
526 #ifdef HAVE_ISA
527 /* Isa Bus */
528 numUsed = xf86MatchIsaInstances(VESA_NAME,VESAChipsets,
529 VESAISAchipsets, drv,
530 VESAFindIsaDevice, devSections,
531 numDevSections, &usedChips);
532 if(numUsed > 0) {
533 if (flags & PROBE_DETECT)
534 foundScreen = TRUE;
535 else for (i = 0; i < numUsed; i++) {
536 ScrnInfoPtr pScrn = NULL;
537 if ((pScrn = xf86ConfigIsaEntity(pScrn, 0,usedChips[i],
538 VESAISAchipsets, NULL,
539 NULL, NULL, NULL, NULL))) {
540 VESAInitScrn(pScrn);
541 foundScreen = TRUE;
542 }
543 }
544 free(usedChips);
545 }
546 #endif
547
548 free(devSections);
549
550 return (foundScreen);
551 }
552 #endif
553
554 #ifdef HAVE_ISA
555 static int
VESAFindIsaDevice(GDevPtr dev)556 VESAFindIsaDevice(GDevPtr dev)
557 {
558 #ifndef PC98_EGC
559 CARD16 GenericIOBase = VGAHW_GET_IOBASE();
560 CARD8 CurrentValue, TestValue;
561
562 /* There's no need to unlock VGA CRTC registers here */
563
564 /* VGA has one more read/write attribute register than EGA */
565 (void) inb(GenericIOBase + VGA_IN_STAT_1_OFFSET); /* Reset flip-flop */
566 outb(VGA_ATTR_INDEX, 0x14 | 0x20);
567 CurrentValue = inb(VGA_ATTR_DATA_R);
568 outb(VGA_ATTR_DATA_W, CurrentValue ^ 0x0F);
569 outb(VGA_ATTR_INDEX, 0x14 | 0x20);
570 TestValue = inb(VGA_ATTR_DATA_R);
571 outb(VGA_ATTR_DATA_R, CurrentValue);
572
573 /* Quit now if no VGA is present */
574 if ((CurrentValue ^ 0x0F) != TestValue)
575 return -1;
576 #endif
577 return (int)CHIP_VESA_GENERIC;
578 }
579 #endif
580
581 static void
VESAFreeRec(ScrnInfoPtr pScrn)582 VESAFreeRec(ScrnInfoPtr pScrn)
583 {
584 VESAPtr pVesa = VESAGetRec(pScrn);
585 #if 0
586 DisplayModePtr mode = pScrn->modes;
587 /* I am not sure if the modes will ever get freed.
588 * Anyway, the data unknown to other modules is being freed here.
589 */
590 if (mode) {
591 do {
592 if (mode->Private) {
593 VbeModeInfoData *data = (VbeModeInfoData*)mode->Private;
594
595 if (data->block)
596 free(data->block);
597
598 free(data);
599
600 mode->Private = NULL;
601 }
602 mode = mode->next;
603 } while (mode && mode != pScrn->modes);
604 }
605 #endif
606 free(pVesa->monitor);
607 if (pVesa->vbeInfo)
608 VBEFreeVBEInfo(pVesa->vbeInfo);
609 free(pVesa->pal);
610 free(pVesa->savedPal);
611 free(pVesa->fonts);
612 free(pScrn->driverPrivate);
613 pScrn->driverPrivate = NULL;
614 }
615
616 static int
VESAValidateModes(ScrnInfoPtr pScrn)617 VESAValidateModes(ScrnInfoPtr pScrn)
618 {
619 VESAPtr pVesa = VESAGetRec(pScrn);
620 DisplayModePtr mode;
621
622 for (mode = pScrn->monitor->Modes; mode; mode = mode->next)
623 mode->status = MODE_OK;
624
625 return VBEValidateModes(pScrn, NULL, pScrn->display->modes,
626 NULL, NULL, 0, 32767, 1, 0, 32767,
627 pScrn->display->virtualX,
628 pScrn->display->virtualY,
629 pVesa->mapSize, LOOKUP_BEST_REFRESH);
630 }
631
632 /*
633 * This function is called once for each screen at the start of the first
634 * server generation to initialise the screen for all server generations.
635 */
636 static Bool
VESAPreInit(ScrnInfoPtr pScrn,int flags)637 VESAPreInit(ScrnInfoPtr pScrn, int flags)
638 {
639 VESAPtr pVesa;
640 VbeInfoBlock *vbe;
641 DisplayModePtr pMode;
642 VbeModeInfoBlock *mode;
643 Gamma gzeros = {0.0, 0.0, 0.0};
644 rgb rzeros = {0, 0, 0};
645 pointer pDDCModule;
646 int i;
647 int flags24 = 0;
648 int defaultDepth = 0;
649 int defaultBpp = 0;
650 int depths = 0;
651
652 if (flags & PROBE_DETECT)
653 return (FALSE);
654
655 pVesa = VESAGetRec(pScrn);
656 pVesa->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
657
658 /* Load vbe module */
659 if (!xf86LoadSubModule(pScrn, "vbe"))
660 return (FALSE);
661
662 if ((pVesa->pVbe = VBEExtendedInit(NULL, pVesa->pEnt->index,
663 SET_BIOS_SCRATCH
664 | RESTORE_BIOS_SCRATCH)) == NULL)
665 return (FALSE);
666
667 #ifndef XSERVER_LIBPCIACCESS
668 if (pVesa->pEnt->location.type == BUS_PCI) {
669 pVesa->pciInfo = xf86GetPciInfoForEntity(pVesa->pEnt->index);
670 pVesa->pciTag = pciTag(pVesa->pciInfo->bus, pVesa->pciInfo->device,
671 pVesa->pciInfo->func);
672 }
673 #endif
674
675 pScrn->chipset = "vesa";
676 pScrn->monitor = pScrn->confScreen->monitor;
677 pScrn->progClock = TRUE;
678 pScrn->rgbBits = 8;
679
680 if ((vbe = VBEGetVBEInfo(pVesa->pVbe)) == NULL)
681 return (FALSE);
682 pVesa->major = (unsigned)(vbe->VESAVersion >> 8);
683 pVesa->minor = vbe->VESAVersion & 0xff;
684 pVesa->vbeInfo = vbe;
685 pScrn->videoRam = vbe->TotalMemory * 64;
686
687 /*
688 * Find what depths are available.
689 */
690 depths = VBEFindSupportedDepths(pVesa->pVbe, pVesa->vbeInfo, &flags24,
691 V_MODETYPE_VBE);
692
693 /* Preferred order for default depth selection. */
694 if (depths & V_DEPTH_24 && (flags24 & Support32bppFb))
695 defaultDepth = 24;
696 else if (depths & V_DEPTH_16)
697 defaultDepth = 16;
698 else if (depths & V_DEPTH_15)
699 defaultDepth = 15;
700 else if (depths & V_DEPTH_24)
701 defaultDepth = 24; /* ew though */
702 else if (depths & V_DEPTH_8)
703 defaultDepth = 8;
704 else if (depths & V_DEPTH_4)
705 defaultDepth = 4;
706 else if (depths & V_DEPTH_1)
707 defaultDepth = 1;
708
709 if (defaultDepth == 24 && !(flags24 & Support32bppFb))
710 defaultBpp = 24;
711
712 /* Prefer 32bpp because 1999 called and wants its packed pixels back */
713 if (flags24 & Support32bppFb)
714 flags24 |= SupportConvert24to32 | PreferConvert24to32;
715 if (flags24 & Support24bppFb)
716 flags24 |= SupportConvert32to24;
717
718 if (!xf86SetDepthBpp(pScrn, defaultDepth, 0, defaultBpp, flags24)) {
719 vbeFree(pVesa->pVbe);
720 return (FALSE);
721 }
722 xf86PrintDepthBpp(pScrn);
723
724 /* color weight */
725 if (pScrn->depth > 8 && !xf86SetWeight(pScrn, rzeros, rzeros)) {
726 vbeFree(pVesa->pVbe);
727 return (FALSE);
728 }
729 /* visual init */
730 if (!xf86SetDefaultVisual(pScrn, -1)) {
731 vbeFree(pVesa->pVbe);
732 return (FALSE);
733 }
734
735 xf86SetGamma(pScrn, gzeros);
736
737 /* set up options before loading any modules that may look at them */
738 xf86CollectOptions(pScrn, NULL);
739
740 if (pVesa->major >= 2) {
741 /* Load ddc module */
742 if ((pDDCModule = xf86LoadSubModule(pScrn, "ddc")) == NULL) {
743 vbeFree(pVesa->pVbe);
744 return (FALSE);
745 }
746
747 if ((pVesa->monitor = vbeDoEDID(pVesa->pVbe, pDDCModule)) != NULL) {
748 xf86PrintEDID(pVesa->monitor);
749 }
750
751 xf86UnloadSubModule(pDDCModule);
752 }
753
754 if ((pScrn->monitor->DDC = pVesa->monitor) != NULL)
755 xf86SetDDCproperties(pScrn, pVesa->monitor);
756 else {
757 void *panelid = VBEReadPanelID(pVesa->pVbe);
758 VBEInterpretPanelID(SCRN_OR_INDEX_ARG(pScrn), panelid);
759 free(panelid);
760 }
761
762 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB,
763 "Searching for matching VESA mode(s):\n");
764
765 /*
766 * Check the available BIOS modes, and extract those that match the
767 * requirements into the modePool. Note: modePool is a NULL-terminated
768 * list.
769 */
770 pScrn->modePool = VBEGetModePool (pScrn, pVesa->pVbe, pVesa->vbeInfo,
771 V_MODETYPE_VBE);
772
773 xf86ErrorFVerb(DEBUG_VERB, "\n");
774 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB,
775 "Total Memory: %d 64KB banks (%dkB)\n", vbe->TotalMemory,
776 (vbe->TotalMemory * 65536) / 1024);
777
778 pVesa->mapSize = vbe->TotalMemory * 65536;
779 if (pScrn->modePool == NULL) {
780 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No matching modes\n");
781 vbeFree(pVesa->pVbe);
782 return (FALSE);
783 }
784
785 VBESetModeNames(pScrn->modePool);
786
787 pVesa->strict_validation = TRUE;
788 i = VESAValidateModes(pScrn);
789
790 if (i <= 0) {
791 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
792 "No valid modes left. Trying less strict filter...\n");
793 pVesa->strict_validation = FALSE;
794 i = VESAValidateModes(pScrn);
795 }
796
797 if (i <= 0) do {
798 Bool changed = FALSE;
799 /* maybe there's more modes at the bottom... */
800 if (pScrn->monitor->vrefresh[0].lo > 50) {
801 changed = TRUE;
802 pScrn->monitor->vrefresh[0].lo = 50;
803 }
804 if (pScrn->monitor->hsync[0].lo > 31.5) {
805 changed = TRUE;
806 pScrn->monitor->hsync[0].lo = 31.5;
807 }
808
809 if (!changed)
810 break;
811
812 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
813 "No valid modes left. Trying aggressive sync range...\n");
814 i = VESAValidateModes(pScrn);
815 } while (0);
816
817 if (i <= 0) {
818 /* alright, i'm out of ideas */
819 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes\n");
820 vbeFree(pVesa->pVbe);
821 return (FALSE);
822 }
823
824 xf86PruneDriverModes(pScrn);
825
826 pMode = pScrn->modes;
827 do {
828 mode = ((VbeModeInfoData*)pMode->Private)->data;
829 if (mode->BytesPerScanline > pVesa->maxBytesPerScanline) {
830 pVesa->maxBytesPerScanline = mode->BytesPerScanline;
831 }
832 pMode = pMode->next;
833 } while (pMode != pScrn->modes);
834
835 pScrn->currentMode = pScrn->modes;
836 pScrn->displayWidth = pScrn->virtualX;
837
838 VBEPrintModes(pScrn);
839
840 /* Set display resolution */
841 xf86SetDpi(pScrn, 0, 0);
842
843 if (pScrn->modes == NULL) {
844 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes\n");
845 vbeFree(pVesa->pVbe);
846 return (FALSE);
847 }
848
849 /* options */
850 if (!(pVesa->Options = malloc(sizeof(VESAOptions)))) {
851 vbeFree(pVesa->pVbe);
852 return FALSE;
853 }
854 memcpy(pVesa->Options, VESAOptions, sizeof(VESAOptions));
855 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVesa->Options);
856
857 /* Use shadow by default, for non-virt hardware */
858 if (!xf86GetOptValBool(pVesa->Options, OPTION_SHADOW_FB, &pVesa->shadowFB))
859 {
860 switch (pVesa->pciInfo->vendor_id) {
861 case 0x1234: /* bochs vga (not in pci.ids) */
862 case 0x15ad: /* vmware */
863 case 0x1b36: /* qemu qxl */
864 case 0x80ee: /* virtualbox */
865 case 0xaaaa: /* parallels (not in pci.ids) */
866 pVesa->shadowFB = FALSE;
867 break;
868
869 case 0x1013: /* qemu's cirrus emulation */
870 if (pVesa->pciInfo->subvendor_id == 0x1af4)
871 pVesa->shadowFB = FALSE;
872 else
873 pVesa->shadowFB = TRUE;
874 break;
875
876 case 0x1414: /* microsoft hyper-v */
877 if (pVesa->pciInfo->device_id == 0x5353)
878 pVesa->shadowFB = FALSE;
879 else
880 pVesa->shadowFB = TRUE;
881 break;
882
883 default:
884 pVesa->shadowFB = TRUE;
885 break;
886 }
887 }
888
889 /* Use default refresh by default. Too many VBE 3.0
890 * BIOSes are incorrectly implemented.
891 */
892 pVesa->defaultRefresh = xf86ReturnOptValBool(pVesa->Options,
893 OPTION_DFLT_REFRESH, TRUE);
894
895 pVesa->ModeSetClearScreen =
896 xf86ReturnOptValBool(pVesa->Options,
897 OPTION_MODESET_CLEAR_SCREEN, FALSE);
898
899 if (!pVesa->defaultRefresh && !pVesa->strict_validation)
900 VBESetModeParameters(pScrn, pVesa->pVbe);
901
902 mode = ((VbeModeInfoData*)pScrn->modes->Private)->data;
903 switch (mode->MemoryModel) {
904 case 0x4: /* Packed pixel */
905 case 0x6: /* Direct Color */
906 pScrn->bitmapBitOrder = BITMAP_BIT_ORDER;
907
908 switch (pScrn->bitsPerPixel) {
909 case 8:
910 case 16:
911 case 24:
912 case 32:
913 break;
914 default:
915 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
916 "Unsupported bpp: %d\n", pScrn->bitsPerPixel);
917 vbeFree(pVesa->pVbe);
918 return FALSE;
919 }
920 break;
921 default:
922 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
923 "Unsupported Memory Model: %d\n", mode->MemoryModel);
924 return FALSE;
925 }
926
927 if (pVesa->shadowFB) {
928 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using \"Shadow Framebuffer\"\n");
929 if (!xf86LoadSubModule(pScrn, "shadow")) {
930 vbeFree(pVesa->pVbe);
931 return (FALSE);
932 }
933 }
934
935 if (xf86LoadSubModule(pScrn, "fb") == NULL) {
936 VESAFreeRec(pScrn);
937 vbeFree(pVesa->pVbe);
938 return (FALSE);
939 }
940
941 vbeFree(pVesa->pVbe);
942
943 return (TRUE);
944 }
945
946 static Bool
vesaCreateScreenResources(ScreenPtr pScreen)947 vesaCreateScreenResources(ScreenPtr pScreen)
948 {
949 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
950 VESAPtr pVesa = VESAGetRec(pScrn);
951 Bool ret;
952
953 pScreen->CreateScreenResources = pVesa->CreateScreenResources;
954 ret = pScreen->CreateScreenResources(pScreen);
955 pScreen->CreateScreenResources = vesaCreateScreenResources;
956
957 shadowAdd(pScreen, pScreen->GetScreenPixmap(pScreen), pVesa->update,
958 pVesa->window, 0, 0);
959
960 return ret;
961 }
962
963 static void
vesaEnableDisableFBAccess(SCRN_ARG_TYPE arg,Bool enable)964 vesaEnableDisableFBAccess(SCRN_ARG_TYPE arg, Bool enable)
965 {
966 SCRN_INFO_PTR(arg);
967 VESAPtr pVesa = VESAGetRec(pScrn);
968
969 pVesa->accessEnabled = enable;
970 pVesa->EnableDisableFBAccess(arg, enable);
971 }
972
973 static Bool
VESAScreenInit(SCREEN_INIT_ARGS_DECL)974 VESAScreenInit(SCREEN_INIT_ARGS_DECL)
975 {
976 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
977 VESAPtr pVesa = VESAGetRec(pScrn);
978 VisualPtr visual;
979 VbeModeInfoBlock *mode;
980 int flags;
981
982 if ((pVesa->pVbe = VBEExtendedInit(NULL, pVesa->pEnt->index,
983 SET_BIOS_SCRATCH
984 | RESTORE_BIOS_SCRATCH)) == NULL)
985 return (FALSE);
986
987 if (pVesa->mapPhys == 0) {
988 mode = ((VbeModeInfoData*)(pScrn->currentMode->Private))->data;
989 pScrn->videoRam = pVesa->mapSize;
990 pVesa->mapPhys = mode->PhysBasePtr;
991 pVesa->mapOff = 0;
992 }
993
994 if (pVesa->mapPhys == 0) {
995 pVesa->mapPhys = 0xa0000;
996 pVesa->mapSize = 0x10000;
997 }
998
999 if (!VESAMapVidMem(pScrn)) {
1000 if (pVesa->mapPhys != 0xa0000) {
1001 pVesa->mapPhys = 0xa0000;
1002 pVesa->mapSize = 0x10000;
1003 if (!VESAMapVidMem(pScrn))
1004 return (FALSE);
1005 }
1006 else
1007 return (FALSE);
1008 }
1009
1010 /* Set bpp to 8 for depth 4 when using shadowfb. */
1011 if (pVesa->shadowFB && pScrn->bitsPerPixel == 4)
1012 pScrn->bitsPerPixel = 8;
1013
1014 if (pVesa->shadowFB) {
1015 pVesa->shadow = calloc(1, pScrn->displayWidth * pScrn->virtualY *
1016 ((pScrn->bitsPerPixel + 7) / 8));
1017 if (!pVesa->shadow) {
1018 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1019 "Failed to allocate shadow buffer\n");
1020 return FALSE;
1021 }
1022 }
1023
1024 /* save current video state */
1025 VESASaveRestore(pScrn, MODE_SAVE);
1026 pVesa->savedPal = VBESetGetPaletteData(pVesa->pVbe, FALSE, 0, 256,
1027 NULL, FALSE, FALSE);
1028
1029 /* set first video mode */
1030 if (!VESASetMode(pScrn, pScrn->currentMode))
1031 return (FALSE);
1032
1033 /* set the viewport */
1034 VESAAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
1035
1036 /* Blank the screen for aesthetic reasons. */
1037 VESASaveScreen(pScreen, SCREEN_SAVER_ON);
1038
1039 /* mi layer */
1040 miClearVisualTypes();
1041 if (!xf86SetDefaultVisual(pScrn, -1))
1042 return (FALSE);
1043 if (pScrn->bitsPerPixel > 8) {
1044 if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
1045 pScrn->rgbBits, TrueColor))
1046 return (FALSE);
1047 }
1048 else {
1049 if (!miSetVisualTypes(pScrn->depth,
1050 miGetDefaultVisualMask(pScrn->depth),
1051 pScrn->rgbBits, pScrn->defaultVisual))
1052 return (FALSE);
1053 }
1054 if (!miSetPixmapDepths())
1055 return (FALSE);
1056
1057 mode = ((VbeModeInfoData*)pScrn->modes->Private)->data;
1058 switch (mode->MemoryModel) {
1059 case 0x4: /* Packed pixel */
1060 case 0x6: /* Direct Color */
1061 switch (pScrn->bitsPerPixel) {
1062 case 8:
1063 case 16:
1064 case 24:
1065 case 32:
1066 if (!fbScreenInit(pScreen,
1067 pVesa->shadowFB ? pVesa->shadow : pVesa->base,
1068 pScrn->virtualX, pScrn->virtualY,
1069 pScrn->xDpi, pScrn->yDpi,
1070 pScrn->displayWidth, pScrn->bitsPerPixel))
1071 return (FALSE);
1072 break;
1073 default:
1074 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1075 "Unsupported bpp: %d", pScrn->bitsPerPixel);
1076 return (FALSE);
1077 }
1078 break;
1079 default:
1080 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1081 "Unsupported Memory Model: %d", mode->MemoryModel);
1082 return (FALSE);
1083 }
1084
1085
1086 if (pScrn->bitsPerPixel > 8) {
1087 /* Fixup RGB ordering */
1088 visual = pScreen->visuals + pScreen->numVisuals;
1089 while (--visual >= pScreen->visuals) {
1090 if ((visual->class | DynamicClass) == DirectColor) {
1091 visual->offsetRed = pScrn->offset.red;
1092 visual->offsetGreen = pScrn->offset.green;
1093 visual->offsetBlue = pScrn->offset.blue;
1094 visual->redMask = pScrn->mask.red;
1095 visual->greenMask = pScrn->mask.green;
1096 visual->blueMask = pScrn->mask.blue;
1097 }
1098 }
1099 }
1100
1101 /* must be after RGB ordering fixed */
1102 fbPictureInit(pScreen, 0, 0);
1103
1104 if (pVesa->shadowFB) {
1105 if (pVesa->mapPhys == 0xa0000) { /* Windowed */
1106 pVesa->update = vesaUpdatePacked;
1107 pVesa->window = VESAWindowWindowed;
1108 }
1109 else { /* Linear */
1110 pVesa->update = vesaUpdatePacked;
1111 pVesa->window = VESAWindowLinear;
1112 }
1113
1114 if (!shadowSetup(pScreen))
1115 return FALSE;
1116 pVesa->CreateScreenResources = pScreen->CreateScreenResources;
1117 pScreen->CreateScreenResources = vesaCreateScreenResources;
1118 }
1119 else if (pVesa->mapPhys == 0xa0000) {
1120 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1121 "Banked framebuffer requires ShadowFB\n");
1122 return FALSE;
1123 }
1124
1125 VESADGAInit(pScrn, pScreen);
1126
1127 xf86SetBlackWhitePixels(pScreen);
1128 xf86SetBackingStore(pScreen);
1129
1130 /* software cursor */
1131 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
1132
1133 /* colormap */
1134 if (!miCreateDefColormap(pScreen))
1135 return (FALSE);
1136
1137 flags = CMAP_RELOAD_ON_MODE_SWITCH;
1138
1139 if(!xf86HandleColormaps(pScreen, 256,
1140 pVesa->vbeInfo->Capabilities[0] & 0x01 ? 8 : 6,
1141 VESALoadPalette, NULL, flags))
1142 return (FALSE);
1143
1144 pVesa->accessEnabled = TRUE;
1145 pVesa->EnableDisableFBAccess = pScrn->EnableDisableFBAccess;
1146 pScrn->EnableDisableFBAccess = vesaEnableDisableFBAccess;
1147
1148 pVesa->CloseScreen = pScreen->CloseScreen;
1149 pScreen->CloseScreen = VESACloseScreen;
1150 pScreen->SaveScreen = VESASaveScreen;
1151
1152 xf86DPMSInit(pScreen, VESADisplayPowerManagementSet, 0);
1153
1154 /* Report any unused options (only for the first generation) */
1155 if (serverGeneration == 1)
1156 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1157
1158 return (TRUE);
1159 }
1160
1161 static Bool
VESAEnterVT(VT_FUNC_ARGS_DECL)1162 VESAEnterVT(VT_FUNC_ARGS_DECL)
1163 {
1164 SCRN_INFO_PTR(arg);
1165
1166 if (!VESASetMode(pScrn, pScrn->currentMode))
1167 return FALSE;
1168 VESAAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
1169 return TRUE;
1170 }
1171
1172 static void
VESALeaveVT(VT_FUNC_ARGS_DECL)1173 VESALeaveVT(VT_FUNC_ARGS_DECL)
1174 {
1175 SCRN_INFO_PTR(arg);
1176 VESASaveRestore(pScrn, MODE_RESTORE);
1177 }
1178
1179 static Bool
VESACloseScreen(CLOSE_SCREEN_ARGS_DECL)1180 VESACloseScreen(CLOSE_SCREEN_ARGS_DECL)
1181 {
1182 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1183 VESAPtr pVesa = VESAGetRec(pScrn);
1184
1185 if (pScrn->vtSema) {
1186 VESASaveRestore(pScrn, MODE_RESTORE);
1187 if (pVesa->savedPal)
1188 VBESetGetPaletteData(pVesa->pVbe, TRUE, 0, 256,
1189 pVesa->savedPal, FALSE, TRUE);
1190 VESAUnmapVidMem(pScrn);
1191 }
1192 if (pVesa->shadowFB && pVesa->shadow) {
1193 shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen));
1194 free(pVesa->shadow);
1195 }
1196 if (pVesa->pDGAMode) {
1197 free(pVesa->pDGAMode);
1198 pVesa->pDGAMode = NULL;
1199 pVesa->nDGAMode = 0;
1200 }
1201 pScrn->vtSema = FALSE;
1202
1203 pScrn->EnableDisableFBAccess = pVesa->EnableDisableFBAccess;
1204 pScreen->CreateScreenResources = pVesa->CreateScreenResources;
1205 pScreen->CloseScreen = pVesa->CloseScreen;
1206 return pScreen->CloseScreen(CLOSE_SCREEN_ARGS);
1207 }
1208
1209 static Bool
VESASwitchMode(SWITCH_MODE_ARGS_DECL)1210 VESASwitchMode(SWITCH_MODE_ARGS_DECL)
1211 {
1212 SCRN_INFO_PTR(arg);
1213 VESAPtr pVesa = VESAGetRec(pScrn);
1214 Bool ret, disableAccess = pVesa->ModeSetClearScreen && pVesa->accessEnabled;
1215
1216 if (disableAccess)
1217 pScrn->EnableDisableFBAccess(SCRN_OR_INDEX_ARG(pScrn),FALSE);
1218 ret = VESASetMode(pScrn, mode);
1219 if (disableAccess)
1220 pScrn->EnableDisableFBAccess(SCRN_OR_INDEX_ARG(pScrn),TRUE);
1221 return ret;
1222 }
1223
1224 /* Set a graphics mode */
1225 static Bool
VESASetMode(ScrnInfoPtr pScrn,DisplayModePtr pMode)1226 VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
1227 {
1228 VESAPtr pVesa;
1229 VbeModeInfoData *data;
1230 int mode;
1231
1232 pVesa = VESAGetRec(pScrn);
1233
1234 data = (VbeModeInfoData*)pMode->Private;
1235
1236 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1237 "Setting up VESA Mode 0x%X (%dx%d)\n",
1238 data->mode & 0x7FF, pMode->HDisplay, pMode->VDisplay);
1239
1240 /* careful, setting the bit means don't clear the screen */
1241 mode = data->mode | (pVesa->ModeSetClearScreen ? 0 : (1U << 15));
1242
1243 /* enable linear addressing */
1244 if (pVesa->mapPhys != 0xa0000)
1245 mode |= 1 << 14;
1246
1247 if (VBESetVBEMode(pVesa->pVbe, mode, data->block) == FALSE) {
1248 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VBESetVBEMode failed");
1249 if ((data->block || (data->mode & (1 << 11))) &&
1250 VBESetVBEMode(pVesa->pVbe, (mode & ~(1 << 11)), NULL) == TRUE) {
1251 /* Some cards do not like setting the clock.
1252 * Free it as it will not be any longer useful
1253 */
1254 xf86ErrorF(", mode set without customized refresh.\n");
1255 free(data->block);
1256 data->block = NULL;
1257 data->mode &= ~(1 << 11);
1258 }
1259 else {
1260 ErrorF("\n");
1261 return (FALSE);
1262 }
1263 }
1264
1265 pVesa->bankSwitchWindowB =
1266 !((data->data->WinBSegment == 0) && (data->data->WinBAttributes == 0));
1267
1268 if (data->data->XResolution != pScrn->displayWidth)
1269 VBESetLogicalScanline(pVesa->pVbe, pScrn->displayWidth);
1270
1271 if (pScrn->bitsPerPixel == 8 && pVesa->vbeInfo->Capabilities[0] & 0x01 &&
1272 !(data->data->MemoryModel == 0x6 || data->data->MemoryModel == 0x7))
1273 VBESetGetDACPaletteFormat(pVesa->pVbe, 8);
1274
1275 pScrn->vtSema = TRUE;
1276
1277 return (TRUE);
1278 }
1279
1280 static void
VESAAdjustFrame(ADJUST_FRAME_ARGS_DECL)1281 VESAAdjustFrame(ADJUST_FRAME_ARGS_DECL)
1282 {
1283 SCRN_INFO_PTR(arg);
1284 VESAPtr pVesa = VESAGetRec(pScrn);
1285
1286 VBESetDisplayStart(pVesa->pVbe, x, y, TRUE);
1287 }
1288
1289 static void
VESAFreeScreen(FREE_SCREEN_ARGS_DECL)1290 VESAFreeScreen(FREE_SCREEN_ARGS_DECL)
1291 {
1292 SCRN_INFO_PTR(arg);
1293 VESAFreeRec(pScrn);
1294 }
1295
1296 static Bool
VESAMapVidMem(ScrnInfoPtr pScrn)1297 VESAMapVidMem(ScrnInfoPtr pScrn)
1298 {
1299 VESAPtr pVesa = VESAGetRec(pScrn);
1300
1301 if (pVesa->base != NULL)
1302 return (TRUE);
1303
1304 pScrn->memPhysBase = pVesa->mapPhys;
1305 pScrn->fbOffset = pVesa->mapOff;
1306
1307 #ifdef XSERVER_LIBPCIACCESS
1308 if (pVesa->pciInfo != NULL) {
1309 if (pVesa->mapPhys != 0xa0000) {
1310 (void) pci_device_map_range(pVesa->pciInfo, pScrn->memPhysBase,
1311 pVesa->mapSize,
1312 (PCI_DEV_MAP_FLAG_WRITABLE
1313 | PCI_DEV_MAP_FLAG_WRITE_COMBINE),
1314 & pVesa->base);
1315
1316 if (pVesa->base)
1317 (void) pci_device_map_legacy(pVesa->pciInfo, 0xa0000, 0x10000,
1318 PCI_DEV_MAP_FLAG_WRITABLE,
1319 & pVesa->VGAbase);
1320 }
1321 else {
1322 (void) pci_device_map_legacy(pVesa->pciInfo, pScrn->memPhysBase,
1323 pVesa->mapSize,
1324 PCI_DEV_MAP_FLAG_WRITABLE,
1325 & pVesa->base);
1326
1327 if (pVesa->base)
1328 pVesa->VGAbase = pVesa->base;
1329 }
1330 }
1331 #else
1332 if (pVesa->mapPhys != 0xa0000 && pVesa->pEnt->location.type == BUS_PCI)
1333 pVesa->base = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
1334 pVesa->pciTag, pScrn->memPhysBase,
1335 pVesa->mapSize);
1336 else
1337 pVesa->base = xf86MapDomainMemory(pScrn->scrnIndex, 0, pVesa->pciTag,
1338 pScrn->memPhysBase, pVesa->mapSize);
1339
1340 if (pVesa->base) {
1341 if (pVesa->mapPhys != 0xa0000)
1342 pVesa->VGAbase = xf86MapDomainMemory(pScrn->scrnIndex, 0,
1343 pVesa->pciTag,
1344 0xa0000, 0x10000);
1345 else
1346 pVesa->VGAbase = pVesa->base;
1347 }
1348 #endif
1349
1350 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
1351 pVesa->ioBase = pScrn->domainIOBase;
1352 #else
1353 pVesa->ioBase = 0;
1354 #endif
1355
1356 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB,
1357 "virtual address = %p, VGAbase = %p\n"
1358 "\tphysical address = 0x%lx, size = %ld\n",
1359 pVesa->base, pVesa->VGAbase,
1360 pScrn->memPhysBase, pVesa->mapSize);
1361
1362 return (pVesa->base != NULL);
1363 }
1364
1365 static void
VESAUnmapVidMem(ScrnInfoPtr pScrn)1366 VESAUnmapVidMem(ScrnInfoPtr pScrn)
1367 {
1368 VESAPtr pVesa = VESAGetRec(pScrn);
1369
1370 if (pVesa->base == NULL)
1371 return;
1372
1373 #ifdef XSERVER_LIBPCIACCESS
1374 if (pVesa->mapPhys != 0xa0000) {
1375 (void) pci_device_unmap_range(pVesa->pciInfo, pVesa->base,
1376 pVesa->mapSize);
1377 (void) pci_device_unmap_legacy(pVesa->pciInfo, pVesa->VGAbase,
1378 0x10000);
1379 }
1380 else {
1381 (void) pci_device_unmap_legacy(pVesa->pciInfo, pVesa->base,
1382 pVesa->mapSize);
1383 }
1384 #else
1385 xf86UnMapVidMem(pScrn->scrnIndex, pVesa->base, pVesa->mapSize);
1386 if (pVesa->mapPhys != 0xa0000)
1387 xf86UnMapVidMem(pScrn->scrnIndex, pVesa->VGAbase, 0x10000);
1388 #endif
1389 pVesa->base = NULL;
1390 }
1391
1392 /* This code works, but is very slow for programs that use it intensively */
1393 static void
VESALoadPalette(ScrnInfoPtr pScrn,int numColors,int * indices,LOCO * colors,VisualPtr pVisual)1394 VESALoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
1395 LOCO *colors, VisualPtr pVisual)
1396 {
1397 VESAPtr pVesa = VESAGetRec(pScrn);
1398 int i, idx;
1399 int base;
1400
1401 if (!pVesa->savedPal) {
1402 #define VESADACDelay() \
1403 do { \
1404 (void)inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
1405 (void)inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
1406 } while (0)
1407
1408 for (i = 0; i < numColors; i++) {
1409 idx = indices[i];
1410 outb(pVesa->ioBase + VGA_DAC_WRITE_ADDR, idx);
1411 VESADACDelay();
1412 outb(pVesa->ioBase + VGA_DAC_DATA, colors[idx].red);
1413 VESADACDelay();
1414 outb(pVesa->ioBase + VGA_DAC_DATA, colors[idx].green);
1415 VESADACDelay();
1416 outb(pVesa->ioBase + VGA_DAC_DATA, colors[idx].blue);
1417 VESADACDelay();
1418 }
1419 return;
1420 }
1421
1422 if (pVesa->pal == NULL)
1423 pVesa->pal = calloc(1, sizeof(CARD32) * 256);
1424
1425 for (i = 0, base = idx = indices[i]; i < numColors; i++, idx++) {
1426 int j = indices[i];
1427
1428 if (j < 0 || j >= 256)
1429 continue;
1430 pVesa->pal[j] = colors[j].blue |
1431 (colors[j].green << 8) |
1432 (colors[j].red << 16);
1433 if (j != idx) {
1434 VBESetGetPaletteData(pVesa->pVbe, TRUE, base, idx - base,
1435 pVesa->pal + base, FALSE, TRUE);
1436 idx = base = j;
1437 }
1438 }
1439
1440 if (idx - 1 == indices[i - 1])
1441 VBESetGetPaletteData(pVesa->pVbe, TRUE, base, idx - base,
1442 pVesa->pal + base, FALSE, TRUE);
1443 }
1444
1445 /*
1446 * Just adapted from the std* functions in vgaHW.c
1447 */
1448 static void
WriteAttr(VESAPtr pVesa,int index,int value)1449 WriteAttr(VESAPtr pVesa, int index, int value)
1450 {
1451 (void) inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
1452
1453 index |= 0x20;
1454 outb(pVesa->ioBase + VGA_ATTR_INDEX, index);
1455 outb(pVesa->ioBase + VGA_ATTR_DATA_W, value);
1456 }
1457
1458 static int
ReadAttr(VESAPtr pVesa,int index)1459 ReadAttr(VESAPtr pVesa, int index)
1460 {
1461 (void) inb(pVesa->ioBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
1462
1463 index |= 0x20;
1464 outb(pVesa->ioBase + VGA_ATTR_INDEX, index);
1465 return (inb(pVesa->ioBase + VGA_ATTR_DATA_R));
1466 }
1467
1468 #define WriteMiscOut(value) outb(pVesa->ioBase + VGA_MISC_OUT_W, value)
1469 #define ReadMiscOut() inb(pVesa->ioBase + VGA_MISC_OUT_R)
1470 #define WriteSeq(index, value) outb(pVesa->ioBase + VGA_SEQ_INDEX, index);\
1471 outb(pVesa->ioBase + VGA_SEQ_DATA, value)
1472
1473 static int
ReadSeq(VESAPtr pVesa,int index)1474 ReadSeq(VESAPtr pVesa, int index)
1475 {
1476 outb(pVesa->ioBase + VGA_SEQ_INDEX, index);
1477
1478 return (inb(pVesa->ioBase + VGA_SEQ_DATA));
1479 }
1480
1481 #define WriteGr(index, value) \
1482 outb(pVesa->ioBase + VGA_GRAPH_INDEX, index); \
1483 outb(pVesa->ioBase + VGA_GRAPH_DATA, value)
1484
1485 static int
ReadGr(VESAPtr pVesa,int index)1486 ReadGr(VESAPtr pVesa, int index)
1487 {
1488 outb(pVesa->ioBase + VGA_GRAPH_INDEX, index);
1489
1490 return (inb(pVesa->ioBase + VGA_GRAPH_DATA));
1491 }
1492
1493 #define WriteCrtc(index, value) \
1494 outb(pVesa->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_INDEX_OFFSET), index); \
1495 outb(pVesa->ioBase + (VGA_IOBASE_COLOR + VGA_CRTC_DATA_OFFSET), value)
1496
1497 static void
SeqReset(VESAPtr pVesa,Bool start)1498 SeqReset(VESAPtr pVesa, Bool start)
1499 {
1500 if (start) {
1501 WriteSeq(0x00, 0x01); /* Synchronous Reset */
1502 }
1503 else {
1504 WriteSeq(0x00, 0x03); /* End Reset */
1505 }
1506 }
1507
1508 static void
SaveFonts(ScrnInfoPtr pScrn)1509 SaveFonts(ScrnInfoPtr pScrn)
1510 {
1511 VESAPtr pVesa = VESAGetRec(pScrn);
1512 unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4, scrn;
1513
1514 if (pVesa->fonts != NULL)
1515 return;
1516
1517 /* If in graphics mode, don't save anything */
1518 attr10 = ReadAttr(pVesa, 0x10);
1519 if (attr10 & 0x01)
1520 return;
1521
1522 pVesa->fonts = malloc(16384);
1523
1524 /* save the registers that are needed here */
1525 miscOut = ReadMiscOut();
1526 gr4 = ReadGr(pVesa, 0x04);
1527 gr5 = ReadGr(pVesa, 0x05);
1528 gr6 = ReadGr(pVesa, 0x06);
1529 seq2 = ReadSeq(pVesa, 0x02);
1530 seq4 = ReadSeq(pVesa, 0x04);
1531
1532 /* Force into colour mode */
1533 WriteMiscOut(miscOut | 0x01);
1534
1535 scrn = ReadSeq(pVesa, 0x01) | 0x20;
1536 SeqReset(pVesa, TRUE);
1537 WriteSeq(0x01, scrn);
1538 SeqReset(pVesa, FALSE);
1539
1540 WriteAttr(pVesa, 0x10, 0x01); /* graphics mode */
1541
1542 /*font1 */
1543 WriteSeq(0x02, 0x04); /* write to plane 2 */
1544 WriteSeq(0x04, 0x06); /* enable plane graphics */
1545 WriteGr(0x04, 0x02); /* read plane 2 */
1546 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1547 WriteGr(0x06, 0x05); /* set graphics */
1548 slowbcopy_frombus(pVesa->VGAbase, pVesa->fonts, 8192);
1549
1550 /* font2 */
1551 WriteSeq(0x02, 0x08); /* write to plane 3 */
1552 WriteSeq(0x04, 0x06); /* enable plane graphics */
1553 WriteGr(0x04, 0x03); /* read plane 3 */
1554 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1555 WriteGr(0x06, 0x05); /* set graphics */
1556 slowbcopy_frombus(pVesa->VGAbase, pVesa->fonts + 8192, 8192);
1557
1558 scrn = ReadSeq(pVesa, 0x01) & ~0x20;
1559 SeqReset(pVesa, TRUE);
1560 WriteSeq(0x01, scrn);
1561 SeqReset(pVesa, FALSE);
1562
1563 /* Restore clobbered registers */
1564 WriteAttr(pVesa, 0x10, attr10);
1565 WriteSeq(0x02, seq2);
1566 WriteSeq(0x04, seq4);
1567 WriteGr(0x04, gr4);
1568 WriteGr(0x05, gr5);
1569 WriteGr(0x06, gr6);
1570 WriteMiscOut(miscOut);
1571 }
1572
1573 static void
RestoreFonts(ScrnInfoPtr pScrn)1574 RestoreFonts(ScrnInfoPtr pScrn)
1575 {
1576 VESAPtr pVesa = VESAGetRec(pScrn);
1577 unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4, scrn;
1578
1579 if (pVesa->fonts == NULL)
1580 return;
1581
1582 if (pVesa->mapPhys == 0xa0000 && pVesa->curBank != 0)
1583 VESABankSwitch(pScrn->pScreen, 0);
1584
1585 /* save the registers that are needed here */
1586 miscOut = ReadMiscOut();
1587 attr10 = ReadAttr(pVesa, 0x10);
1588 gr1 = ReadGr(pVesa, 0x01);
1589 gr3 = ReadGr(pVesa, 0x03);
1590 gr4 = ReadGr(pVesa, 0x04);
1591 gr5 = ReadGr(pVesa, 0x05);
1592 gr6 = ReadGr(pVesa, 0x06);
1593 gr8 = ReadGr(pVesa, 0x08);
1594 seq2 = ReadSeq(pVesa, 0x02);
1595 seq4 = ReadSeq(pVesa, 0x04);
1596
1597 /* Force into colour mode */
1598 WriteMiscOut(miscOut | 0x01);
1599
1600 scrn = ReadSeq(pVesa, 0x01) | 0x20;
1601 SeqReset(pVesa, TRUE);
1602 WriteSeq(0x01, scrn);
1603 SeqReset(pVesa, FALSE);
1604
1605 WriteAttr(pVesa, 0x10, 0x01); /* graphics mode */
1606 if (pScrn->depth == 4) {
1607 /* GJA */
1608 WriteGr(0x03, 0x00); /* don't rotate, write unmodified */
1609 WriteGr(0x08, 0xFF); /* write all bits in a byte */
1610 WriteGr(0x01, 0x00); /* all planes come from CPU */
1611 }
1612
1613 WriteSeq(0x02, 0x04); /* write to plane 2 */
1614 WriteSeq(0x04, 0x06); /* enable plane graphics */
1615 WriteGr(0x04, 0x02); /* read plane 2 */
1616 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1617 WriteGr(0x06, 0x05); /* set graphics */
1618 slowbcopy_tobus(pVesa->fonts, pVesa->VGAbase, 8192);
1619
1620 WriteSeq(0x02, 0x08); /* write to plane 3 */
1621 WriteSeq(0x04, 0x06); /* enable plane graphics */
1622 WriteGr(0x04, 0x03); /* read plane 3 */
1623 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1624 WriteGr(0x06, 0x05); /* set graphics */
1625 slowbcopy_tobus(pVesa->fonts + 8192, pVesa->VGAbase, 8192);
1626
1627 scrn = ReadSeq(pVesa, 0x01) & ~0x20;
1628 SeqReset(pVesa, TRUE);
1629 WriteSeq(0x01, scrn);
1630 SeqReset(pVesa, FALSE);
1631
1632 /* restore the registers that were changed */
1633 WriteMiscOut(miscOut);
1634 WriteAttr(pVesa, 0x10, attr10);
1635 WriteGr(0x01, gr1);
1636 WriteGr(0x03, gr3);
1637 WriteGr(0x04, gr4);
1638 WriteGr(0x05, gr5);
1639 WriteGr(0x06, gr6);
1640 WriteGr(0x08, gr8);
1641 WriteSeq(0x02, seq2);
1642 WriteSeq(0x04, seq4);
1643 }
1644
1645 static Bool
VESASaveScreen(ScreenPtr pScreen,int mode)1646 VESASaveScreen(ScreenPtr pScreen, int mode)
1647 {
1648 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1649 VESAPtr pVesa = VESAGetRec(pScrn);
1650 Bool on = xf86IsUnblank(mode);
1651
1652 if (on)
1653 SetTimeSinceLastInputEvent();
1654
1655 if (pScrn->vtSema) {
1656 unsigned char scrn = ReadSeq(pVesa, 0x01);
1657
1658 if (on)
1659 scrn &= ~0x20;
1660 else
1661 scrn |= 0x20;
1662 SeqReset(pVesa, TRUE);
1663 WriteSeq(0x01, scrn);
1664 SeqReset(pVesa, FALSE);
1665 }
1666
1667 return (TRUE);
1668 }
1669
1670 static int
VESABankSwitch(ScreenPtr pScreen,unsigned int iBank)1671 VESABankSwitch(ScreenPtr pScreen, unsigned int iBank)
1672 {
1673 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1674 VESAPtr pVesa = VESAGetRec(pScrn);
1675
1676 if (pVesa->curBank == iBank)
1677 return (0);
1678 if (!VBEBankSwitch(pVesa->pVbe, iBank, 0))
1679 return (1);
1680 if (pVesa->bankSwitchWindowB) {
1681 if (!VBEBankSwitch(pVesa->pVbe, iBank, 1))
1682 return (1);
1683 }
1684 pVesa->curBank = iBank;
1685
1686 return (0);
1687 }
1688
1689 Bool
VESASaveRestore(ScrnInfoPtr pScrn,vbeSaveRestoreFunction function)1690 VESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
1691 {
1692 VESAPtr pVesa;
1693
1694 if (function < MODE_QUERY || function > MODE_RESTORE)
1695 return (FALSE);
1696
1697 pVesa = VESAGetRec(pScrn);
1698
1699
1700 /* Query amount of memory to save state */
1701 if (function == MODE_QUERY ||
1702 (function == MODE_SAVE && pVesa->state == NULL)) {
1703
1704 /* Make sure we save at least this information in case of failure */
1705 (void)VBEGetVBEMode(pVesa->pVbe, &pVesa->stateMode);
1706 SaveFonts(pScrn);
1707
1708 if (pVesa->major > 1) {
1709 if (!VBESaveRestore(pVesa->pVbe,function,(pointer)&pVesa->state,
1710 &pVesa->stateSize,&pVesa->statePage))
1711 return FALSE;
1712
1713 }
1714 }
1715
1716 /* Save/Restore Super VGA state */
1717 if (function != MODE_QUERY) {
1718 Bool retval = TRUE;
1719
1720 if (pVesa->major > 1) {
1721 if (function == MODE_RESTORE)
1722 memcpy(pVesa->state, pVesa->pstate, pVesa->stateSize);
1723
1724 if ((retval = VBESaveRestore(pVesa->pVbe,function,
1725 (pointer)&pVesa->state,
1726 &pVesa->stateSize,&pVesa->statePage))
1727 && function == MODE_SAVE) {
1728 /* don't rely on the memory not being touched */
1729 if (pVesa->pstate == NULL)
1730 pVesa->pstate = malloc(pVesa->stateSize);
1731 memcpy(pVesa->pstate, pVesa->state, pVesa->stateSize);
1732 }
1733 }
1734
1735 if (function == MODE_RESTORE) {
1736 VBESetVBEMode(pVesa->pVbe, pVesa->stateMode, NULL);
1737 RestoreFonts(pScrn);
1738 }
1739
1740 if (!retval)
1741 return (FALSE);
1742
1743 }
1744
1745 return (TRUE);
1746 }
1747
1748 static void
VESADisplayPowerManagementSet(ScrnInfoPtr pScrn,int mode,int flags)1749 VESADisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
1750 int flags)
1751 {
1752 VESAPtr pVesa = VESAGetRec(pScrn);
1753
1754 if (!pScrn->vtSema)
1755 return;
1756
1757 VBEDPMSSet(pVesa->pVbe, mode);
1758 }
1759
1760 /***********************************************************************
1761 * DGA stuff
1762 ***********************************************************************/
1763 static Bool VESADGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1764 unsigned char **ApertureBase,
1765 int *ApertureSize, int *ApertureOffset,
1766 int *flags);
1767 static Bool VESADGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode);
1768 static void VESADGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags);
1769
1770 static Bool
VESADGAOpenFramebuffer(ScrnInfoPtr pScrn,char ** DeviceName,unsigned char ** ApertureBase,int * ApertureSize,int * ApertureOffset,int * flags)1771 VESADGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1772 unsigned char **ApertureBase, int *ApertureSize,
1773 int *ApertureOffset, int *flags)
1774 {
1775 VESAPtr pVesa = VESAGetRec(pScrn);
1776
1777 *DeviceName = NULL; /* No special device */
1778 *ApertureBase = (unsigned char *)(long)(pVesa->mapPhys);
1779 *ApertureSize = pVesa->mapSize;
1780 *ApertureOffset = pVesa->mapOff;
1781 *flags = DGA_NEED_ROOT;
1782
1783 return (TRUE);
1784 }
1785
1786 static Bool
VESADGASetMode(ScrnInfoPtr pScrn,DGAModePtr pDGAMode)1787 VESADGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode)
1788 {
1789 DisplayModePtr pMode;
1790 int scrnIdx = pScrn->pScreen->myNum;
1791 int frameX0, frameY0;
1792
1793 if (pDGAMode) {
1794 pMode = pDGAMode->mode;
1795 frameX0 = frameY0 = 0;
1796 }
1797 else {
1798 if (!(pMode = pScrn->currentMode))
1799 return (TRUE);
1800
1801 frameX0 = pScrn->frameX0;
1802 frameY0 = pScrn->frameY0;
1803 }
1804
1805 if (!(*pScrn->SwitchMode)(SWITCH_MODE_ARGS(pScrn, pMode)))
1806 return (FALSE);
1807 (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, frameX0, frameY0));
1808
1809 return (TRUE);
1810 }
1811
1812 static void
VESADGASetViewport(ScrnInfoPtr pScrn,int x,int y,int flags)1813 VESADGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
1814 {
1815 (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, x, y));
1816 }
1817
1818 static int
VESADGAGetViewport(ScrnInfoPtr pScrn)1819 VESADGAGetViewport(ScrnInfoPtr pScrn)
1820 {
1821 return (0);
1822 }
1823
1824 static DGAFunctionRec VESADGAFunctions =
1825 {
1826 VESADGAOpenFramebuffer,
1827 NULL, /* CloseFramebuffer */
1828 VESADGASetMode,
1829 VESADGASetViewport,
1830 VESADGAGetViewport,
1831 NULL, /* Sync */
1832 NULL, /* FillRect */
1833 NULL, /* BlitRect */
1834 NULL, /* BlitTransRect */
1835 };
1836
1837 static void
VESADGAAddModes(ScrnInfoPtr pScrn)1838 VESADGAAddModes(ScrnInfoPtr pScrn)
1839 {
1840 VESAPtr pVesa = VESAGetRec(pScrn);
1841 DisplayModePtr pMode = pScrn->modes;
1842 DGAModePtr pDGAMode;
1843
1844 do {
1845 pDGAMode = realloc(pVesa->pDGAMode,
1846 (pVesa->nDGAMode + 1) * sizeof(DGAModeRec));
1847 if (!pDGAMode)
1848 break;
1849
1850 pVesa->pDGAMode = pDGAMode;
1851 pDGAMode += pVesa->nDGAMode;
1852 (void)memset(pDGAMode, 0, sizeof(DGAModeRec));
1853
1854 ++pVesa->nDGAMode;
1855 pDGAMode->mode = pMode;
1856 pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
1857 pDGAMode->byteOrder = pScrn->imageByteOrder;
1858 pDGAMode->depth = pScrn->depth;
1859 pDGAMode->bitsPerPixel = pScrn->bitsPerPixel;
1860 pDGAMode->red_mask = pScrn->mask.red;
1861 pDGAMode->green_mask = pScrn->mask.green;
1862 pDGAMode->blue_mask = pScrn->mask.blue;
1863 pDGAMode->visualClass = pScrn->bitsPerPixel > 8 ?
1864 TrueColor : PseudoColor;
1865 pDGAMode->xViewportStep = 1;
1866 pDGAMode->yViewportStep = 1;
1867 pDGAMode->viewportWidth = pMode->HDisplay;
1868 pDGAMode->viewportHeight = pMode->VDisplay;
1869
1870 pDGAMode->bytesPerScanline = pVesa->maxBytesPerScanline;
1871 pDGAMode->imageWidth = pMode->HDisplay;
1872 pDGAMode->imageHeight = pMode->VDisplay;
1873 pDGAMode->pixmapWidth = pDGAMode->imageWidth;
1874 pDGAMode->pixmapHeight = pDGAMode->imageHeight;
1875 pDGAMode->maxViewportX = pScrn->virtualX -
1876 pDGAMode->viewportWidth;
1877 pDGAMode->maxViewportY = pScrn->virtualY -
1878 pDGAMode->viewportHeight;
1879
1880 pDGAMode->address = pVesa->base;
1881
1882 pMode = pMode->next;
1883 } while (pMode != pScrn->modes);
1884 }
1885
1886 static Bool
VESADGAInit(ScrnInfoPtr pScrn,ScreenPtr pScreen)1887 VESADGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen)
1888 {
1889 VESAPtr pVesa = VESAGetRec(pScrn);
1890
1891 if (pScrn->depth < 8 || pVesa->mapPhys == 0xa0000L)
1892 return (FALSE);
1893
1894 if (!pVesa->nDGAMode)
1895 VESADGAAddModes(pScrn);
1896
1897 return (DGAInit(pScreen, &VESADGAFunctions,
1898 pVesa->pDGAMode, pVesa->nDGAMode));
1899 }
1900