1 /*
2 * Copyright © 2001-2012 Matthieu Herrb
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 */
30
31 /*
32 * Based on fbdev.c written by:
33 *
34 * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk>
35 * Michel Dänzer, <michdaen@iiic.ethz.ch>
36 */
37
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <unistd.h>
45 #include <sys/ioctl.h>
46 #include <sys/types.h>
47 #include <sys/mman.h>
48 #include <sys/time.h>
49 #include <sys/consio.h>
50 #include <sys/fbio.h>
51
52 /* All drivers need this. */
53 #include "xf86.h"
54 #include "xf86_OSproc.h"
55 #include "xf86Priv.h"
56
57 #include "mipointer.h"
58 #include "micmap.h"
59 #include "colormapst.h"
60 #include "xf86cmap.h"
61 #include "shadow.h"
62 #include "dgaproc.h"
63
64 /* For visuals */
65 #ifdef HAVE_XF1BPP
66 # include "xf1bpp.h"
67 #endif
68 #ifdef HAVE_XF4BPP
69 # include "xf4bpp.h"
70 #endif
71 #include "fb.h"
72
73 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
74 #include "xf86Resources.h"
75 #include "xf86RAC.h"
76 #endif
77
78 #ifdef XvExtension
79 #include "xf86xv.h"
80 #endif
81
82 #include "compat-api.h"
83
84 #undef DEBUG
85 #define DEBUG 1
86
87 #if DEBUG
88 # define TRACE_ENTER(str) ErrorF("scfb: " str " %d\n",pScrn->scrnIndex)
89 # define TRACE_EXIT(str) ErrorF("scfb: " str " done\n")
90 # define TRACE(str) ErrorF("scfb trace: " str "\n")
91 #else
92 # define TRACE_ENTER(str)
93 # define TRACE_EXIT(str)
94 # define TRACE(str)
95 #endif
96
97 /* Prototypes */
98 static pointer ScfbSetup(pointer, pointer, int *, int *);
99 static Bool ScfbGetRec(ScrnInfoPtr);
100 static void ScfbFreeRec(ScrnInfoPtr);
101 static const OptionInfoRec * ScfbAvailableOptions(int, int);
102 static void ScfbIdentify(int);
103 static Bool ScfbProbe(DriverPtr, int);
104 static Bool ScfbPreInit(ScrnInfoPtr, int);
105 static Bool ScfbScreenInit(SCREEN_INIT_ARGS_DECL);
106 static Bool ScfbCloseScreen(CLOSE_SCREEN_ARGS_DECL);
107 static void *ScfbWindowLinear(ScreenPtr, CARD32, CARD32, int, CARD32 *,
108 void *);
109 static void ScfbPointerMoved(SCRN_ARG_TYPE, int, int);
110 static Bool ScfbEnterVT(VT_FUNC_ARGS_DECL);
111 static void ScfbLeaveVT(VT_FUNC_ARGS_DECL);
112 static Bool ScfbSwitchMode(SWITCH_MODE_ARGS_DECL);
113 static int ScfbValidMode(SCRN_ARG_TYPE, DisplayModePtr, Bool, int);
114 static void ScfbLoadPalette(ScrnInfoPtr, int, int *, LOCO *, VisualPtr);
115 static Bool ScfbSaveScreen(ScreenPtr, int);
116 static void ScfbSave(ScrnInfoPtr);
117 static void ScfbRestore(ScrnInfoPtr);
118
119 /* DGA stuff */
120 #ifdef XFreeXDGA
121 static Bool ScfbDGAOpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
122 int *, int *, int *);
123 static Bool ScfbDGASetMode(ScrnInfoPtr, DGAModePtr);
124 static void ScfbDGASetViewport(ScrnInfoPtr, int, int, int);
125 static Bool ScfbDGAInit(ScrnInfoPtr, ScreenPtr);
126 #endif
127 static Bool ScfbDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op,
128 pointer ptr);
129
130 /* Helper functions */
131 static pointer scfb_mmap(size_t, off_t, int);
132
133 enum { SCFB_ROTATE_NONE = 0,
134 SCFB_ROTATE_CCW = 90,
135 SCFB_ROTATE_UD = 180,
136 SCFB_ROTATE_CW = 270
137 };
138
139 /*
140 * This is intentionally screen-independent.
141 * It indicates the binding choice made in the first PreInit.
142 */
143 static int pix24bpp = 0;
144
145 #define SCFB_VERSION 0002
146 #define SCFB_NAME "scfb"
147 #define SCFB_DRIVER_NAME "scfb"
148
149 _X_EXPORT DriverRec SCFB = {
150 SCFB_VERSION,
151 SCFB_DRIVER_NAME,
152 ScfbIdentify,
153 ScfbProbe,
154 ScfbAvailableOptions,
155 NULL,
156 0,
157 ScfbDriverFunc
158 };
159
160 /* Supported "chipsets" */
161 static SymTabRec ScfbChipsets[] = {
162 { 0, "scfb" },
163 { -1, NULL }
164 };
165
166 /* Supported options */
167 typedef enum {
168 OPTION_SHADOW_FB,
169 OPTION_ROTATE
170 } ScfbOpts;
171
172 static const OptionInfoRec ScfbOptions[] = {
173 { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE},
174 { OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE},
175 { -1, NULL, OPTV_NONE, {0}, FALSE}
176 };
177
178 static XF86ModuleVersionInfo ScfbVersRec = {
179 "scfb",
180 MODULEVENDORSTRING,
181 MODINFOSTRING1,
182 MODINFOSTRING2,
183 XORG_VERSION_CURRENT,
184 PACKAGE_VERSION_MAJOR,
185 PACKAGE_VERSION_MINOR,
186 PACKAGE_VERSION_PATCHLEVEL,
187 ABI_CLASS_VIDEODRV,
188 ABI_VIDEODRV_VERSION,
189 NULL,
190 {0, 0, 0, 0}
191 };
192
193 _X_EXPORT XF86ModuleData scfbModuleData = { &ScfbVersRec, ScfbSetup, NULL };
194
195 static pointer
ScfbSetup(pointer module,pointer opts,int * errmaj,int * errmin)196 ScfbSetup(pointer module, pointer opts, int *errmaj, int *errmin)
197 {
198 static Bool setupDone = FALSE;
199
200 if (!setupDone) {
201 setupDone = TRUE;
202 xf86AddDriver(&SCFB, module, HaveDriverFuncs);
203 return (pointer)1;
204 } else {
205 if (errmaj != NULL)
206 *errmaj = LDR_ONCEONLY;
207 return NULL;
208 }
209 }
210
211 /* Private data */
212 typedef struct {
213 int fd; /* File descriptor of open device. */
214 struct video_info info;
215 int linebytes; /* Number of bytes per row. */
216 unsigned char* fbstart;
217 unsigned char* fbmem;
218 size_t fbmem_len;
219 int rotate;
220 Bool shadowFB;
221 void * shadow;
222 CloseScreenProcPtr CloseScreen;
223 CreateScreenResourcesProcPtr CreateScreenResources;
224 void (*PointerMoved)(SCRN_ARG_TYPE, int, int);
225 EntityInfoPtr pEnt;
226
227 #ifdef XFreeXDGA
228 /* DGA info */
229 DGAModePtr pDGAMode;
230 int nDGAMode;
231 #endif
232 OptionInfoPtr Options;
233 } ScfbRec, *ScfbPtr;
234
235 #define SCFBPTR(p) ((ScfbPtr)((p)->driverPrivate))
236
237 static Bool
ScfbGetRec(ScrnInfoPtr pScrn)238 ScfbGetRec(ScrnInfoPtr pScrn)
239 {
240
241 if (pScrn->driverPrivate != NULL)
242 return TRUE;
243
244 pScrn->driverPrivate = xnfcalloc(sizeof(ScfbRec), 1);
245 return TRUE;
246 }
247
248 static void
ScfbFreeRec(ScrnInfoPtr pScrn)249 ScfbFreeRec(ScrnInfoPtr pScrn)
250 {
251
252 if (pScrn->driverPrivate == NULL)
253 return;
254 free(pScrn->driverPrivate);
255 pScrn->driverPrivate = NULL;
256 }
257
258 static const OptionInfoRec *
ScfbAvailableOptions(int chipid,int busid)259 ScfbAvailableOptions(int chipid, int busid)
260 {
261 return ScfbOptions;
262 }
263
264 static void
ScfbIdentify(int flags)265 ScfbIdentify(int flags)
266 {
267 xf86PrintChipsets(SCFB_NAME, "driver for wsdisplay framebuffer",
268 ScfbChipsets);
269 }
270
271 /* Map the framebuffer's memory. */
272 static pointer
scfb_mmap(size_t len,off_t off,int fd)273 scfb_mmap(size_t len, off_t off, int fd)
274 {
275 int pagemask, mapsize;
276 caddr_t addr;
277 pointer mapaddr;
278
279 pagemask = getpagesize() - 1;
280 mapsize = ((int) len + pagemask) & ~pagemask;
281 addr = 0;
282
283 /*
284 * Try and make it private first, that way once we get it, an
285 * interloper, e.g. another server, can't get this frame buffer,
286 * and if another server already has it, this one won't.
287 */
288 mapaddr = (pointer) mmap(addr, mapsize,
289 PROT_READ | PROT_WRITE, MAP_SHARED,
290 fd, off);
291 if (mapaddr == (pointer) -1) {
292 mapaddr = NULL;
293 }
294 #if DEBUG
295 ErrorF("mmap returns: addr %p len 0x%x, fd %d, off %lx\n", mapaddr, mapsize, fd, off);
296 #endif
297 return mapaddr;
298 }
299
300 static Bool
ScfbProbe(DriverPtr drv,int flags)301 ScfbProbe(DriverPtr drv, int flags)
302 {
303 int i, fd, entity;
304 GDevPtr *devSections;
305 int numDevSections;
306 const char *dev;
307 struct fbtype fb;
308 Bool foundScreen = FALSE;
309
310 TRACE("probe start");
311
312 /* For now, just bail out for PROBE_DETECT. */
313 if (flags & PROBE_DETECT)
314 return FALSE;
315
316 if ((numDevSections = xf86MatchDevice(SCFB_DRIVER_NAME,
317 &devSections)) <= 0)
318 return FALSE;
319
320
321 for (i = 0; i < numDevSections; i++) {
322 ScrnInfoPtr pScrn = NULL;
323 dev = xf86FindOptionValue(devSections[i]->options, "device");
324 if ((fd = xf86Info.consoleFd) >= 0 &&
325 ioctl(fd, FBIOGTYPE, &fb) != -1 &&
326 fb.fb_type == FBTYPE_DUMBFB) {
327 entity = xf86ClaimFbSlot(drv, 0, devSections[i], TRUE);
328 pScrn = xf86ConfigFbEntity(NULL,0,entity,
329 NULL,NULL,NULL,NULL);
330 if (pScrn != NULL) {
331 foundScreen = TRUE;
332 pScrn->driverVersion = SCFB_VERSION;
333 pScrn->driverName = SCFB_DRIVER_NAME;
334 pScrn->name = SCFB_NAME;
335 pScrn->Probe = ScfbProbe;
336 pScrn->PreInit = ScfbPreInit;
337 pScrn->ScreenInit = ScfbScreenInit;
338 pScrn->SwitchMode = ScfbSwitchMode;
339 pScrn->AdjustFrame = NULL;
340 pScrn->EnterVT = ScfbEnterVT;
341 pScrn->LeaveVT = ScfbLeaveVT;
342 pScrn->ValidMode = ScfbValidMode;
343
344 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
345 "using %s\n", dev != NULL ? dev :
346 "default device");
347 }
348 }
349 }
350 free(devSections);
351 TRACE("probe done");
352 return foundScreen;
353 }
354
355 static Bool
ScfbPreInit(ScrnInfoPtr pScrn,int flags)356 ScfbPreInit(ScrnInfoPtr pScrn, int flags)
357 {
358 ScfbPtr fPtr;
359 struct fbtype fb;
360 int default_depth, wstype;
361 const char *dev;
362 char *mod = NULL;
363 const char *reqSym = NULL, *s;
364 Gamma zeros = {0.0, 0.0, 0.0};
365 DisplayModePtr mode;
366
367 if (flags & PROBE_DETECT) return FALSE;
368
369 TRACE_ENTER("PreInit");
370
371 if (pScrn->numEntities != 1) return FALSE;
372
373 pScrn->monitor = pScrn->confScreen->monitor;
374
375 ScfbGetRec(pScrn);
376 fPtr = SCFBPTR(pScrn);
377
378 fPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
379
380 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
381 pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
382 pScrn->racIoFlags = pScrn->racMemFlags;
383 #endif
384
385 dev = xf86FindOptionValue(fPtr->pEnt->device->options, "device");
386 fPtr->fd = xf86Info.consoleFd;
387 if (fPtr->fd == -1) {
388 return FALSE;
389 }
390
391 if (ioctl(fPtr->fd, FBIOGTYPE, &fb) == -1) {
392 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
393 "ioctl FBIOGTYPE: %s\n",
394 strerror(errno));
395 return FALSE;
396 }
397
398 fPtr->info.vi_depth = fb.fb_depth;
399 fPtr->info.vi_width = fb.fb_width;
400 fPtr->info.vi_height = fb.fb_height;
401 fPtr->info.vi_pixel_size = fb.fb_depth/8;
402
403 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
404 "Using: depth (%d),\twidth (%d),\t height (%d)\n",
405 fPtr->info.vi_depth,fPtr->info.vi_width, fPtr->info.vi_height);
406
407 if (ioctl(fPtr->fd, FBIO_GETLINEWIDTH, &fPtr->linebytes) == -1) {
408 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
409 "ioctl FBIO_GETLINEWIDTH fail: %s. "
410 "Falling back to width * bytes per pixel.\n",
411 strerror(errno));
412 fPtr->linebytes = fPtr->info.vi_width *
413 fPtr->info.vi_pixel_size;
414 }
415
416 /* Handle depth */
417 default_depth = fPtr->info.vi_depth <= 24 ? fPtr->info.vi_depth : 24;
418 if (!xf86SetDepthBpp(pScrn, default_depth, default_depth,
419 fPtr->info.vi_depth,
420 fPtr->info.vi_depth >= 24 ? Support24bppFb|Support32bppFb : 0))
421 return FALSE;
422
423 /* Check consistency. */
424 if (pScrn->bitsPerPixel != fPtr->info.vi_depth) {
425 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
426 "specified depth (%d) or bpp (%d) doesn't match "
427 "framebuffer depth (%d)\n", pScrn->depth,
428 pScrn->bitsPerPixel, fPtr->info.vi_depth);
429 return FALSE;
430 }
431 xf86PrintDepthBpp(pScrn);
432
433 /* Get the depth24 pixmap format. */
434 if (pScrn->depth == 24 && pix24bpp == 0)
435 pix24bpp = xf86GetBppFromDepth(pScrn, 24);
436
437 /* Color weight */
438 if (pScrn->depth > 8) {
439 rgb zeros = { 0, 0, 0 }, masks = { 0, 0, 0 };
440 #ifdef FBIO_GETRGBOFFS
441 struct fb_rgboffs offs;
442
443 if (ioctl(fPtr->fd, FBIO_GETRGBOFFS, &offs) == -1) {
444 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
445 "ioctl FBIO_GETRGBOFFS fail: %s. "
446 "Falling back to default color format.\n",
447 strerror(errno));
448 memset(&offs, 0, sizeof(offs));
449 }
450
451 /*
452 * If FBIO_GETRGBOFFS returned any non-zero offset, set the
453 * RGB masks appropriately.
454 *
455 * As there was an issue in Xorg server's RGB masks handling
456 * (https://gitlab.freedesktop.org/xorg/xserver/-/issues/1112),
457 * that is only fixed in master and 21.1.x releases for now,
458 * avoid modifying the masks if they correspond to the default
459 * values used by X.
460 */
461 if ((offs.red != 0 || offs.green != 0 || offs.blue != 0) &&
462 !(offs.red == 16 && offs.green == 8 && offs.blue == 0)) {
463 masks.red = 0xff << offs.red;
464 masks.green = 0xff << offs.green;
465 masks.blue = 0xff << offs.blue;
466 }
467 #endif
468
469 if (!xf86SetWeight(pScrn, zeros, masks))
470 return FALSE;
471 }
472
473 /* Visual init */
474 if (!xf86SetDefaultVisual(pScrn, -1))
475 return FALSE;
476
477 /* We don't currently support DirectColor at > 8bpp . */
478 if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
479 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
480 " (%s) is not supported at depth %d\n",
481 xf86GetVisualName(pScrn->defaultVisual),
482 pScrn->depth);
483 return FALSE;
484 }
485
486 xf86SetGamma(pScrn,zeros);
487
488 pScrn->progClock = TRUE;
489 pScrn->rgbBits = 8;
490 pScrn->chipset = "scfb";
491 pScrn->videoRam = fPtr->linebytes * fPtr->info.vi_height;
492
493 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Vidmem: %dk\n",
494 pScrn->videoRam/1024);
495
496 /* Handle options. */
497 xf86CollectOptions(pScrn, NULL);
498 fPtr->Options = (OptionInfoRec *)malloc(sizeof(ScfbOptions));
499 if (fPtr->Options == NULL)
500 return FALSE;
501 memcpy(fPtr->Options, ScfbOptions, sizeof(ScfbOptions));
502 xf86ProcessOptions(pScrn->scrnIndex, fPtr->pEnt->device->options,
503 fPtr->Options);
504
505 /* Use shadow framebuffer by default, on depth >= 8 */
506 if (pScrn->depth >= 8)
507 fPtr->shadowFB = xf86ReturnOptValBool(fPtr->Options,
508 OPTION_SHADOW_FB, TRUE);
509 else
510 if (xf86ReturnOptValBool(fPtr->Options,
511 OPTION_SHADOW_FB, FALSE)) {
512 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
513 "Shadow FB option ignored on depth < 8");
514 }
515
516 /* Rotation */
517 fPtr->rotate = SCFB_ROTATE_NONE;
518 if ((s = xf86GetOptValString(fPtr->Options, OPTION_ROTATE))) {
519 if (pScrn->depth >= 8) {
520 if (!xf86NameCmp(s, "CW")) {
521 fPtr->shadowFB = TRUE;
522 fPtr->rotate = SCFB_ROTATE_CW;
523 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
524 "Rotating screen clockwise\n");
525 } else if (!xf86NameCmp(s, "CCW")) {
526 fPtr->shadowFB = TRUE;
527 fPtr->rotate = SCFB_ROTATE_CCW;
528 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
529 "Rotating screen counter clockwise\n");
530 } else if (!xf86NameCmp(s, "UD")) {
531 fPtr->shadowFB = TRUE;
532 fPtr->rotate = SCFB_ROTATE_UD;
533 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
534 "Rotating screen upside down\n");
535 } else {
536 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
537 "\"%s\" is not a valid value for Option "
538 "\"Rotate\"\n", s);
539 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
540 "Valid options are \"CW\", \"CCW\","
541 " or \"UD\"\n");
542 }
543 } else {
544 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
545 "Option \"Rotate\" ignored on depth < 8");
546 }
547 }
548
549 /* Fake video mode struct. */
550 mode = (DisplayModePtr)malloc(sizeof(DisplayModeRec));
551 mode->prev = mode;
552 mode->next = mode;
553 mode->name = "scfb current mode";
554 mode->status = MODE_OK;
555 mode->type = M_T_BUILTIN;
556 mode->Clock = 0;
557 mode->HDisplay = fPtr->info.vi_width;
558 mode->HSyncStart = 0;
559 mode->HSyncEnd = 0;
560 mode->HTotal = 0;
561 mode->HSkew = 0;
562 mode->VDisplay = fPtr->info.vi_height;
563 mode->VSyncStart = 0;
564 mode->VSyncEnd = 0;
565 mode->VTotal = 0;
566 mode->VScan = 0;
567 mode->Flags = 0;
568 if (pScrn->modes != NULL) {
569 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
570 "Ignoring mode specification from screen section\n");
571 }
572 pScrn->currentMode = pScrn->modes = mode;
573 pScrn->virtualX = fPtr->info.vi_width;
574 pScrn->virtualY = fPtr->info.vi_height;
575 pScrn->displayWidth = pScrn->virtualX;
576
577 /* Set the display resolution. */
578 xf86SetDpi(pScrn, 0, 0);
579
580 /* Load bpp-specific modules. */
581 switch(pScrn->bitsPerPixel) {
582 #ifdef HAVE_XF1BPP
583 case 1:
584 mod = "xf1bpp";
585 reqSym = "xf1bppScreenInit";
586 break;
587 #endif
588 #ifdef HAVE_XF4BPP
589 case 4:
590 mod = "xf4bpp";
591 reqSym = "xf4bppScreenInit";
592 break;
593 #endif
594 default:
595 mod = "fb";
596 break;
597 }
598
599 /* Load shadow if needed. */
600 if (fPtr->shadowFB) {
601 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
602 "Using \"Shadow Framebuffer\"\n");
603 if (xf86LoadSubModule(pScrn, "shadow") == NULL) {
604 ScfbFreeRec(pScrn);
605 return FALSE;
606 }
607 }
608 if (mod && xf86LoadSubModule(pScrn, mod) == NULL) {
609 ScfbFreeRec(pScrn);
610 return FALSE;
611 }
612 TRACE_EXIT("PreInit");
613 return TRUE;
614 }
615
616 static void
scfbUpdateRotatePacked(ScreenPtr pScreen,shadowBufPtr pBuf)617 scfbUpdateRotatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
618 {
619 shadowUpdateRotatePacked(pScreen, pBuf);
620 }
621
622 static void
scfbUpdatePacked(ScreenPtr pScreen,shadowBufPtr pBuf)623 scfbUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
624 {
625 shadowUpdatePacked(pScreen, pBuf);
626 }
627
628 static Bool
ScfbCreateScreenResources(ScreenPtr pScreen)629 ScfbCreateScreenResources(ScreenPtr pScreen)
630 {
631 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
632 ScfbPtr fPtr = SCFBPTR(pScrn);
633 PixmapPtr pPixmap;
634 Bool ret;
635
636 pScreen->CreateScreenResources = fPtr->CreateScreenResources;
637 ret = pScreen->CreateScreenResources(pScreen);
638 pScreen->CreateScreenResources = ScfbCreateScreenResources;
639
640 if (!ret)
641 return FALSE;
642
643 pPixmap = pScreen->GetScreenPixmap(pScreen);
644
645 if (!shadowAdd(pScreen, pPixmap, fPtr->rotate ?
646 scfbUpdateRotatePacked : scfbUpdatePacked,
647 ScfbWindowLinear, fPtr->rotate, NULL)) {
648 return FALSE;
649 }
650 return TRUE;
651 }
652
653
654 static Bool
ScfbShadowInit(ScreenPtr pScreen)655 ScfbShadowInit(ScreenPtr pScreen)
656 {
657 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
658 ScfbPtr fPtr = SCFBPTR(pScrn);
659
660 if (!shadowSetup(pScreen))
661 return FALSE;
662 fPtr->CreateScreenResources = pScreen->CreateScreenResources;
663 pScreen->CreateScreenResources = ScfbCreateScreenResources;
664
665 return TRUE;
666 }
667
668 static Bool
ScfbScreenInit(SCREEN_INIT_ARGS_DECL)669 ScfbScreenInit(SCREEN_INIT_ARGS_DECL)
670 {
671 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
672 ScfbPtr fPtr = SCFBPTR(pScrn);
673 VisualPtr visual;
674 int ret, flags, ncolors;
675 size_t len;
676
677 TRACE_ENTER("ScfbScreenInit");
678 #if DEBUG
679 ErrorF("\tbitsPerPixel=%d, depth=%d, defaultVisual=%s\n"
680 "\tmask: %x,%x,%x, offset: %u,%u,%u\n",
681 pScrn->bitsPerPixel,
682 pScrn->depth,
683 xf86GetVisualName(pScrn->defaultVisual),
684 pScrn->mask.red,pScrn->mask.green,pScrn->mask.blue,
685 pScrn->offset.red,pScrn->offset.green,pScrn->offset.blue);
686 #endif
687 switch (fPtr->info.vi_depth) {
688 case 1:
689 case 4:
690 case 8:
691 len = fPtr->linebytes*fPtr->info.vi_height;
692 break;
693 case 16:
694 if (fPtr->linebytes == fPtr->info.vi_width) {
695 len = fPtr->info.vi_width*fPtr->info.vi_height*sizeof(short);
696 } else {
697 len = fPtr->linebytes*fPtr->info.vi_height;
698 }
699 break;
700 case 24:
701 if (fPtr->linebytes == fPtr->info.vi_width) {
702 len = fPtr->info.vi_width*fPtr->info.vi_height*3;
703 } else {
704 len = fPtr->linebytes*fPtr->info.vi_height;
705 }
706 break;
707 case 32:
708 if (fPtr->linebytes == fPtr->info.vi_width) {
709 len = fPtr->info.vi_width*fPtr->info.vi_height*sizeof(int);
710 } else {
711 len = fPtr->linebytes*fPtr->info.vi_height;
712 }
713 break;
714 default:
715 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
716 "unsupported depth %d\n", fPtr->info.vi_depth);
717 return FALSE;
718 }
719 /* TODO: Switch to graphics mode - required before mmap. */
720 fPtr->fbmem = scfb_mmap(len, 0, fPtr->fd);
721
722 if (fPtr->fbmem == NULL) {
723 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
724 "scfb_mmap: %s\n", strerror(errno));
725 return FALSE;
726 }
727 fPtr->fbmem_len = len;
728
729 ScfbSave(pScrn);
730 pScrn->vtSema = TRUE;
731
732 /* MI layer */
733 miClearVisualTypes();
734 if (pScrn->bitsPerPixel > 8) {
735 if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
736 pScrn->rgbBits, TrueColor))
737 return FALSE;
738 } else {
739 if (!miSetVisualTypes(pScrn->depth,
740 miGetDefaultVisualMask(pScrn->depth),
741 pScrn->rgbBits, pScrn->defaultVisual))
742 return FALSE;
743 }
744 if (!miSetPixmapDepths())
745 return FALSE;
746
747 if (fPtr->rotate == SCFB_ROTATE_CW
748 || fPtr->rotate == SCFB_ROTATE_CCW) {
749 int tmp = pScrn->virtualX;
750 pScrn->virtualX = pScrn->displayWidth = pScrn->virtualY;
751 pScrn->virtualY = tmp;
752 }
753 if (fPtr->rotate && !fPtr->PointerMoved) {
754 fPtr->PointerMoved = pScrn->PointerMoved;
755 pScrn->PointerMoved = ScfbPointerMoved;
756 }
757
758 fPtr->fbstart = fPtr->fbmem;
759
760 if (fPtr->shadowFB) {
761 fPtr->shadow = calloc(1, pScrn->virtualX * pScrn->virtualY *
762 pScrn->bitsPerPixel/8);
763
764 if (!fPtr->shadow) {
765 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
766 "Failed to allocate shadow framebuffer\n");
767 return FALSE;
768 }
769 }
770
771 switch (pScrn->bitsPerPixel) {
772 case 1:
773 #ifdef HAVE_XF1BPP
774 ret = xf1bppScreenInit(pScreen, fPtr->fbstart,
775 pScrn->virtualX, pScrn->virtualY,
776 pScrn->xDpi, pScrn->yDpi,
777 fPtr->linebytes * 8);
778 break;
779 #endif
780 case 4:
781 #ifdef HAVE_XF4BPP
782 ret = xf4bppScreenInit(pScreen, fPtr->fbstart,
783 pScrn->virtualX, pScrn->virtualY,
784 pScrn->xDpi, pScrn->yDpi,
785 fPtr->linebytes * 2);
786 break;
787 #endif
788 case 8:
789 case 16:
790 case 24:
791 case 32:
792 ret = fbScreenInit(pScreen,
793 fPtr->shadowFB ? fPtr->shadow : fPtr->fbstart,
794 pScrn->virtualX, pScrn->virtualY,
795 pScrn->xDpi, pScrn->yDpi,
796 pScrn->displayWidth, pScrn->bitsPerPixel);
797 break;
798 default:
799 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
800 "Unsupported bpp: %d", pScrn->bitsPerPixel);
801 return FALSE;
802 } /* case */
803
804 if (!ret)
805 return FALSE;
806
807 if (pScrn->bitsPerPixel > 8) {
808 /* Fixup RGB ordering. */
809 visual = pScreen->visuals + pScreen->numVisuals;
810 while (--visual >= pScreen->visuals) {
811 if ((visual->class | DynamicClass) == DirectColor) {
812 visual->offsetRed = pScrn->offset.red;
813 visual->offsetGreen = pScrn->offset.green;
814 visual->offsetBlue = pScrn->offset.blue;
815 visual->redMask = pScrn->mask.red;
816 visual->greenMask = pScrn->mask.green;
817 visual->blueMask = pScrn->mask.blue;
818 }
819 }
820 }
821
822 if (pScrn->bitsPerPixel >= 8) {
823 if (!fbPictureInit(pScreen, NULL, 0))
824 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
825 "RENDER extension initialisation failed.");
826 }
827 if (fPtr->shadowFB && !ScfbShadowInit(pScreen)) {
828 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
829 "shadow framebuffer initialization failed\n");
830 return FALSE;
831 }
832
833 #ifdef XFreeXDGA
834 if (!fPtr->rotate)
835 ScfbDGAInit(pScrn, pScreen);
836 else
837 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rotated display, "
838 "disabling DGA\n");
839 #endif
840 if (fPtr->rotate) {
841 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling Driver Rotation, "
842 "disabling RandR\n");
843 xf86DisableRandR();
844 if (pScrn->bitsPerPixel == 24)
845 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
846 "Rotation might be broken in 24 bpp\n");
847 }
848
849 xf86SetBlackWhitePixels(pScreen);
850 xf86SetBackingStore(pScreen);
851
852 /* Software cursor. */
853 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
854
855 /*
856 * Colormap
857 *
858 * Note that, even on less than 8 bit depth frame buffers, we
859 * expect the colormap to be programmable with 8 bit values.
860 * As of now, this is indeed the case on all OpenBSD supported
861 * graphics hardware.
862 */
863 if (!miCreateDefColormap(pScreen))
864 return FALSE;
865 flags = CMAP_RELOAD_ON_MODE_SWITCH;
866 ncolors = 256;
867 if(!xf86HandleColormaps(pScreen, ncolors, 8, ScfbLoadPalette,
868 NULL, flags))
869 return FALSE;
870
871 pScreen->SaveScreen = ScfbSaveScreen;
872
873 #ifdef XvExtension
874 {
875 XF86VideoAdaptorPtr *ptr;
876
877 int n = xf86XVListGenericAdaptors(pScrn,&ptr);
878 if (n) {
879 xf86XVScreenInit(pScreen,ptr,n);
880 }
881 }
882 #endif
883
884 /* Wrap the current CloseScreen function. */
885 fPtr->CloseScreen = pScreen->CloseScreen;
886 pScreen->CloseScreen = ScfbCloseScreen;
887
888 TRACE_EXIT("ScfbScreenInit");
889 return TRUE;
890 }
891
892 static Bool
ScfbCloseScreen(CLOSE_SCREEN_ARGS_DECL)893 ScfbCloseScreen(CLOSE_SCREEN_ARGS_DECL)
894 {
895 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
896 PixmapPtr pPixmap;
897 ScfbPtr fPtr = SCFBPTR(pScrn);
898
899
900 TRACE_ENTER("ScfbCloseScreen");
901
902 pPixmap = pScreen->GetScreenPixmap(pScreen);
903 if (fPtr->shadowFB)
904 shadowRemove(pScreen, pPixmap);
905
906 if (pScrn->vtSema) {
907 ScfbRestore(pScrn);
908 if (munmap(fPtr->fbmem, fPtr->fbmem_len) == -1) {
909 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
910 "munmap: %s\n", strerror(errno));
911 }
912
913 fPtr->fbmem = NULL;
914 }
915 #ifdef XFreeXDGA
916 if (fPtr->pDGAMode) {
917 free(fPtr->pDGAMode);
918 fPtr->pDGAMode = NULL;
919 fPtr->nDGAMode = 0;
920 }
921 #endif
922 pScrn->vtSema = FALSE;
923
924 /* Unwrap CloseScreen. */
925 pScreen->CloseScreen = fPtr->CloseScreen;
926 TRACE_EXIT("ScfbCloseScreen");
927 return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
928 }
929
930 static void *
ScfbWindowLinear(ScreenPtr pScreen,CARD32 row,CARD32 offset,int mode,CARD32 * size,void * closure)931 ScfbWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode,
932 CARD32 *size, void *closure)
933 {
934 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
935 ScfbPtr fPtr = SCFBPTR(pScrn);
936
937 *size = fPtr->linebytes;
938 return ((CARD8 *)fPtr->fbmem + row *fPtr->linebytes + offset);
939 }
940
941 static void
ScfbPointerMoved(SCRN_ARG_TYPE arg,int x,int y)942 ScfbPointerMoved(SCRN_ARG_TYPE arg, int x, int y)
943 {
944 SCRN_INFO_PTR(arg);
945 ScfbPtr fPtr = SCFBPTR(pScrn);
946 int newX, newY;
947
948 switch (fPtr->rotate)
949 {
950 case SCFB_ROTATE_CW:
951 /* 90 degrees CW rotation. */
952 newX = pScrn->pScreen->height - y - 1;
953 newY = x;
954 break;
955
956 case SCFB_ROTATE_CCW:
957 /* 90 degrees CCW rotation. */
958 newX = y;
959 newY = pScrn->pScreen->width - x - 1;
960 break;
961
962 case SCFB_ROTATE_UD:
963 /* 180 degrees UD rotation. */
964 newX = pScrn->pScreen->width - x - 1;
965 newY = pScrn->pScreen->height - y - 1;
966 break;
967
968 default:
969 /* No rotation. */
970 newX = x;
971 newY = y;
972 break;
973 }
974
975 /* Pass adjusted pointer coordinates to wrapped PointerMoved function. */
976 (*fPtr->PointerMoved)(arg, newX, newY);
977 }
978
979 static Bool
ScfbEnterVT(VT_FUNC_ARGS_DECL)980 ScfbEnterVT(VT_FUNC_ARGS_DECL)
981 {
982 SCRN_INFO_PTR(arg);
983
984 TRACE_ENTER("EnterVT");
985 pScrn->vtSema = TRUE;
986 TRACE_EXIT("EnterVT");
987 return TRUE;
988 }
989
990 static void
ScfbLeaveVT(VT_FUNC_ARGS_DECL)991 ScfbLeaveVT(VT_FUNC_ARGS_DECL)
992 {
993 #if DEBUG
994 SCRN_INFO_PTR(arg);
995 #endif
996
997 TRACE_ENTER("LeaveVT");
998 }
999
1000 static Bool
ScfbSwitchMode(SWITCH_MODE_ARGS_DECL)1001 ScfbSwitchMode(SWITCH_MODE_ARGS_DECL)
1002 {
1003 #if DEBUG
1004 SCRN_INFO_PTR(arg);
1005 #endif
1006
1007 TRACE_ENTER("SwitchMode");
1008 /* Nothing else to do. */
1009 return TRUE;
1010 }
1011
1012 static int
ScfbValidMode(SCRN_ARG_TYPE arg,DisplayModePtr mode,Bool verbose,int flags)1013 ScfbValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
1014 {
1015 #if DEBUG
1016 SCRN_INFO_PTR(arg);
1017 #endif
1018
1019 TRACE_ENTER("ValidMode");
1020 return MODE_OK;
1021 }
1022
1023 static void
ScfbLoadPalette(ScrnInfoPtr pScrn,int numColors,int * indices,LOCO * colors,VisualPtr pVisual)1024 ScfbLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
1025 LOCO *colors, VisualPtr pVisual)
1026 {
1027
1028 TRACE_ENTER("LoadPalette");
1029 /* TODO */
1030 }
1031
1032 static Bool
ScfbSaveScreen(ScreenPtr pScreen,int mode)1033 ScfbSaveScreen(ScreenPtr pScreen, int mode)
1034 {
1035 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1036 ScfbPtr fPtr = SCFBPTR(pScrn);
1037 int state;
1038
1039 TRACE_ENTER("SaveScreen");
1040
1041 if (!pScrn->vtSema)
1042 return TRUE;
1043
1044 if (mode != SCREEN_SAVER_FORCER) {
1045 /* TODO, if (mode) enable_screen(); else disable_screen(); */
1046 }
1047 TRACE_EXIT("SaveScreen");
1048 return TRUE;
1049 }
1050
1051
1052 static void
ScfbSave(ScrnInfoPtr pScrn)1053 ScfbSave(ScrnInfoPtr pScrn)
1054 {
1055 ScfbPtr fPtr = SCFBPTR(pScrn);
1056
1057 TRACE_ENTER("ScfbSave");
1058
1059 TRACE_EXIT("ScfbSave");
1060
1061 }
1062
1063 static void
ScfbRestore(ScrnInfoPtr pScrn)1064 ScfbRestore(ScrnInfoPtr pScrn)
1065 {
1066 ScfbPtr fPtr = SCFBPTR(pScrn);
1067 int mode;
1068
1069 TRACE_ENTER("ScfbRestore");
1070
1071 /* Clear the screen. */
1072 memset(fPtr->fbmem, 0, fPtr->fbmem_len);
1073
1074 /* Restore the text mode. */
1075 /* TODO: We need to get first, if we need mode switching */
1076 TRACE_EXIT("ScfbRestore");
1077 }
1078
1079 #ifdef XFreeXDGA
1080 /***********************************************************************
1081 * DGA stuff
1082 ***********************************************************************/
1083
1084 static Bool
ScfbDGAOpenFramebuffer(ScrnInfoPtr pScrn,char ** DeviceName,unsigned char ** ApertureBase,int * ApertureSize,int * ApertureOffset,int * flags)1085 ScfbDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1086 unsigned char **ApertureBase, int *ApertureSize,
1087 int *ApertureOffset, int *flags)
1088 {
1089 *DeviceName = NULL; /* No special device */
1090 *ApertureBase = (unsigned char *)(pScrn->memPhysBase);
1091 *ApertureSize = pScrn->videoRam;
1092 *ApertureOffset = pScrn->fbOffset;
1093 *flags = 0;
1094
1095 return TRUE;
1096 }
1097
1098 static Bool
ScfbDGASetMode(ScrnInfoPtr pScrn,DGAModePtr pDGAMode)1099 ScfbDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode)
1100 {
1101 DisplayModePtr pMode;
1102 int frameX0, frameY0;
1103
1104 if (pDGAMode) {
1105 pMode = pDGAMode->mode;
1106 frameX0 = frameY0 = 0;
1107 } else {
1108 if (!(pMode = pScrn->currentMode))
1109 return TRUE;
1110
1111 frameX0 = pScrn->frameX0;
1112 frameY0 = pScrn->frameY0;
1113 }
1114
1115 if (!(*pScrn->SwitchMode)(SWITCH_MODE_ARGS(pScrn, pMode)))
1116 return FALSE;
1117 (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, frameX0, frameY0));
1118
1119 return TRUE;
1120 }
1121
1122 static void
ScfbDGASetViewport(ScrnInfoPtr pScrn,int x,int y,int flags)1123 ScfbDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
1124 {
1125 (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, x, y));
1126 }
1127
1128 static int
ScfbDGAGetViewport(ScrnInfoPtr pScrn)1129 ScfbDGAGetViewport(ScrnInfoPtr pScrn)
1130 {
1131 return (0);
1132 }
1133
1134 static DGAFunctionRec ScfbDGAFunctions =
1135 {
1136 ScfbDGAOpenFramebuffer,
1137 NULL, /* CloseFramebuffer */
1138 ScfbDGASetMode,
1139 ScfbDGASetViewport,
1140 ScfbDGAGetViewport,
1141 NULL, /* Sync */
1142 NULL, /* FillRect */
1143 NULL, /* BlitRect */
1144 NULL, /* BlitTransRect */
1145 };
1146
1147 static void
ScfbDGAAddModes(ScrnInfoPtr pScrn)1148 ScfbDGAAddModes(ScrnInfoPtr pScrn)
1149 {
1150 ScfbPtr fPtr = SCFBPTR(pScrn);
1151 DisplayModePtr pMode = pScrn->modes;
1152 DGAModePtr pDGAMode;
1153
1154 do {
1155 pDGAMode = realloc(fPtr->pDGAMode,
1156 (fPtr->nDGAMode + 1) * sizeof(DGAModeRec));
1157 if (!pDGAMode)
1158 break;
1159
1160 fPtr->pDGAMode = pDGAMode;
1161 pDGAMode += fPtr->nDGAMode;
1162 (void)memset(pDGAMode, 0, sizeof(DGAModeRec));
1163
1164 ++fPtr->nDGAMode;
1165 pDGAMode->mode = pMode;
1166 pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
1167 pDGAMode->byteOrder = pScrn->imageByteOrder;
1168 pDGAMode->depth = pScrn->depth;
1169 pDGAMode->bitsPerPixel = pScrn->bitsPerPixel;
1170 pDGAMode->red_mask = pScrn->mask.red;
1171 pDGAMode->green_mask = pScrn->mask.green;
1172 pDGAMode->blue_mask = pScrn->mask.blue;
1173 pDGAMode->visualClass = pScrn->bitsPerPixel > 8 ?
1174 TrueColor : PseudoColor;
1175 pDGAMode->xViewportStep = 1;
1176 pDGAMode->yViewportStep = 1;
1177 pDGAMode->viewportWidth = pMode->HDisplay;
1178 pDGAMode->viewportHeight = pMode->VDisplay;
1179
1180 pDGAMode->bytesPerScanline = fPtr->linebytes;
1181
1182 pDGAMode->imageWidth = pMode->HDisplay;
1183 pDGAMode->imageHeight = pMode->VDisplay;
1184 pDGAMode->pixmapWidth = pDGAMode->imageWidth;
1185 pDGAMode->pixmapHeight = pDGAMode->imageHeight;
1186 pDGAMode->maxViewportX = pScrn->virtualX -
1187 pDGAMode->viewportWidth;
1188 pDGAMode->maxViewportY = pScrn->virtualY -
1189 pDGAMode->viewportHeight;
1190
1191 pDGAMode->address = fPtr->fbstart;
1192
1193 pMode = pMode->next;
1194 } while (pMode != pScrn->modes);
1195 }
1196
1197 static Bool
ScfbDGAInit(ScrnInfoPtr pScrn,ScreenPtr pScreen)1198 ScfbDGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen)
1199 {
1200 ScfbPtr fPtr = SCFBPTR(pScrn);
1201
1202 if (pScrn->depth < 8)
1203 return FALSE;
1204
1205 if (!fPtr->nDGAMode)
1206 ScfbDGAAddModes(pScrn);
1207
1208 return (DGAInit(pScreen, &ScfbDGAFunctions,
1209 fPtr->pDGAMode, fPtr->nDGAMode));
1210 }
1211 #endif
1212
1213 static Bool
ScfbDriverFunc(ScrnInfoPtr pScrn,xorgDriverFuncOp op,pointer ptr)1214 ScfbDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op,
1215 pointer ptr)
1216 {
1217 xorgHWFlags *flag;
1218
1219 switch (op) {
1220 case GET_REQUIRED_HW_INTERFACES:
1221 flag = (CARD32*)ptr;
1222 (*flag) = 0;
1223 return TRUE;
1224 default:
1225 return FALSE;
1226 }
1227 }
1228
1229