xf86sbusBus.c revision 4642e01f
1/* 2 * SBUS bus-specific code. 3 * 4 * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com) 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * 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 * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24#ifdef HAVE_XORG_CONFIG_H 25#include <xorg-config.h> 26#endif 27 28#include <ctype.h> 29#include <stdio.h> 30#include <unistd.h> 31#include <X11/X.h> 32#include "os.h" 33#include "xf86.h" 34#include "xf86Priv.h" 35#include "xf86_OSlib.h" 36#include "xf86Resources.h" 37#include "xf86cmap.h" 38 39#include "xf86Bus.h" 40 41#include "xf86sbusBus.h" 42#include "xf86Sbus.h" 43 44Bool sbusSlotClaimed = FALSE; 45 46static int xf86nSbusInfo; 47 48static void 49CheckSbusDevice(const char *device, int fbNum) 50{ 51 int fd, i; 52 struct fbgattr fbattr; 53 sbusDevicePtr psdp; 54 55 fd = open(device, O_RDONLY, 0); 56 if (fd < 0) 57 return; 58 memset(&fbattr, 0, sizeof(fbattr)); 59 if (ioctl(fd, FBIOGATTR, &fbattr) < 0) { 60 if (ioctl(fd, FBIOGTYPE, &fbattr.fbtype) < 0) { 61 close(fd); 62 return; 63 } 64 } 65 close(fd); 66 for (i = 0; sbusDeviceTable[i].devId; i++) 67 if (sbusDeviceTable[i].fbType == fbattr.fbtype.fb_type) 68 break; 69 if (! sbusDeviceTable[i].devId) 70 return; 71 xf86SbusInfo = xnfrealloc(xf86SbusInfo, sizeof(psdp) * (++xf86nSbusInfo + 1)); 72 xf86SbusInfo[xf86nSbusInfo] = NULL; 73 xf86SbusInfo[xf86nSbusInfo - 1] = psdp = xnfcalloc(sizeof (sbusDevice), 1); 74 psdp->devId = sbusDeviceTable[i].devId; 75 psdp->fbNum = fbNum; 76 psdp->device = xnfstrdup(device); 77 psdp->width = fbattr.fbtype.fb_width; 78 psdp->height = fbattr.fbtype.fb_height; 79 psdp->fd = -1; 80} 81 82void 83xf86SbusProbe(void) 84{ 85 int i, useProm = 0; 86 char fbDevName[32]; 87 sbusDevicePtr psdp, *psdpp; 88 89 xf86SbusInfo = xalloc(sizeof(psdp)); 90 *xf86SbusInfo = NULL; 91 for (i = 0; i < 32; i++) { 92 sprintf(fbDevName, "/dev/fb%d", i); 93 CheckSbusDevice(fbDevName, i); 94 } 95 if (sparcPromInit() >= 0) { 96 useProm = 1; 97 sparcPromAssignNodes(); 98 } 99 for (psdpp = xf86SbusInfo; (psdp = *psdpp); psdpp++) { 100 for (i = 0; sbusDeviceTable[i].devId; i++) 101 if (sbusDeviceTable[i].devId == psdp->devId) 102 psdp->descr = sbusDeviceTable[i].descr; 103 /* 104 * If we can use PROM information and found the PROM node for this 105 * device, we can tell more about the card. 106 */ 107 if (useProm && psdp->node.node) { 108 char *prop, *promPath; 109 int len, chiprev, vmsize; 110 111 switch (psdp->devId) { 112 case SBUS_DEVICE_MGX: 113 prop = sparcPromGetProperty(&psdp->node, "fb_size", &len); 114 if (prop && len == 4 && *(int *)prop == 0x400000) 115 psdp->descr = "Quantum 3D MGXplus with 4M VRAM"; 116 break; 117 case SBUS_DEVICE_CG6: 118 chiprev = 0; 119 vmsize = 0; 120 prop = sparcPromGetProperty(&psdp->node, "chiprev", &len); 121 if (prop && len == 4) 122 chiprev = *(int *)prop; 123 prop = sparcPromGetProperty(&psdp->node, "vmsize", &len); 124 if (prop && len == 4) 125 vmsize = *(int *)prop; 126 switch (chiprev) { 127 case 1: 128 case 2: 129 case 3: 130 case 4: 131 psdp->descr = "Sun Double width GX"; break; 132 case 5: 133 case 6: 134 case 7: 135 case 8: 136 case 9: 137 psdp->descr = "Sun Single width GX"; break; 138 case 11: 139 switch (vmsize) { 140 case 2: 141 psdp->descr = "Sun Turbo GX with 1M VSIMM"; break; 142 case 4: 143 psdp->descr = "Sun Turbo GX Plus"; break; 144 default: 145 psdp->descr = "Sun Turbo GX"; break; 146 } 147 } 148 break; 149 case SBUS_DEVICE_CG14: 150 prop = sparcPromGetProperty(&psdp->node, "reg", &len); 151 vmsize = 0; 152 if (prop && !(len % 12) && len > 0) 153 vmsize = *(int *)(prop + len - 4); 154 switch (vmsize) { 155 case 0x400000: 156 psdp->descr = "Sun SX with 4M VSIMM"; break; 157 case 0x800000: 158 psdp->descr = "Sun SX with 8M VSIMM"; break; 159 } 160 break; 161 case SBUS_DEVICE_LEO: 162 prop = sparcPromGetProperty(&psdp->node, "model", &len); 163 if (prop && len > 0 && !strstr(prop, "501-2503")) 164 psdp->descr = "Sun Turbo ZX"; 165 break; 166 case SBUS_DEVICE_TCX: 167 if (sparcPromGetBool(&psdp->node, "tcx-8-bit")) 168 psdp->descr = "Sun TCX (8bit)"; 169 else 170 psdp->descr = "Sun TCX (S24)"; 171 break; 172 case SBUS_DEVICE_FFB: 173 prop = sparcPromGetProperty(&psdp->node, "name", &len); 174 chiprev = 0; 175 prop = sparcPromGetProperty(&psdp->node, "board_type", &len); 176 if (prop && len == 4) 177 chiprev = *(int *)prop; 178 if (strstr (prop, "afb")) { 179 if (chiprev == 3) 180 psdp->descr = "Sun|Elite3D-M6 Horizontal"; 181 } else { 182 switch (chiprev) { 183 case 0x08: 184 psdp->descr = "Sun FFB 67MHz Creator"; break; 185 case 0x0b: 186 psdp->descr = "Sun FFB 67MHz Creator 3D"; break; 187 case 0x1b: 188 psdp->descr = "Sun FFB 75MHz Creator 3D"; break; 189 case 0x20: 190 case 0x28: 191 psdp->descr = "Sun FFB2 Vertical Creator"; break; 192 case 0x23: 193 case 0x2b: 194 psdp->descr = "Sun FFB2 Vertical Creator 3D"; break; 195 case 0x30: 196 psdp->descr = "Sun FFB2+ Vertical Creator"; break; 197 case 0x33: 198 psdp->descr = "Sun FFB2+ Vertical Creator 3D"; break; 199 case 0x40: 200 case 0x48: 201 psdp->descr = "Sun FFB2 Horizontal Creator"; break; 202 case 0x43: 203 case 0x4b: 204 psdp->descr = "Sun FFB2 Horizontal Creator 3D"; break; 205 } 206 } 207 break; 208 } 209 210 xf86Msg(X_PROBED, "SBUS:(0x%08x) %s", psdp->node.node, psdp->descr); 211 promPath = sparcPromNode2Pathname (&psdp->node); 212 if (promPath) { 213 xf86ErrorF(" at %s", promPath); 214 xfree(promPath); 215 } 216 } else 217 xf86Msg(X_PROBED, "SBUS: %s", psdp->descr); 218 xf86ErrorF("\n"); 219 } 220 if (useProm) 221 sparcPromClose(); 222} 223 224/* 225 * Parse a BUS ID string, and return the SBUS bus parameters if it was 226 * in the correct format for a SBUS bus id. 227 */ 228 229Bool 230xf86ParseSbusBusString(const char *busID, int *fbNum) 231{ 232 /* 233 * The format is assumed to be one of: 234 * "fbN", e.g. "fb1", which means the device corresponding to /dev/fbN 235 * "nameN", e.g. "cgsix0", which means Nth instance of card NAME 236 * "/prompath", e.g. "/sbus@0,10001000/cgsix@3,0" which is PROM pathname 237 * to the device. 238 */ 239 240 const char *id; 241 int i, len; 242 243 if (StringToBusType(busID, &id) != BUS_SBUS) 244 return FALSE; 245 246 if (*id != '/') { 247 if (!strncmp (id, "fb", 2)) { 248 if (!isdigit(id[2])) 249 return FALSE; 250 *fbNum = atoi(id + 2); 251 return TRUE; 252 } else { 253 sbusDevicePtr *psdpp; 254 int devId; 255 256 for (i = 0, len = 0; sbusDeviceTable[i].devId; i++) { 257 len = strlen(sbusDeviceTable[i].promName); 258 if (!strncmp (sbusDeviceTable[i].promName, id, len) 259 && isdigit(id[len])) 260 break; 261 } 262 devId = sbusDeviceTable[i].devId; 263 if (!devId) return FALSE; 264 i = atoi(id + len); 265 for (psdpp = xf86SbusInfo; *psdpp; ++psdpp) { 266 if ((*psdpp)->devId != devId) 267 continue; 268 if (!i) { 269 *fbNum = (*psdpp)->fbNum; 270 return TRUE; 271 } 272 i--; 273 } 274 } 275 return FALSE; 276 } 277 278 if (sparcPromInit() >= 0) { 279 i = sparcPromPathname2Node(id); 280 sparcPromClose(); 281 if (i) { 282 sbusDevicePtr *psdpp; 283 for (psdpp = xf86SbusInfo; *psdpp; ++psdpp) { 284 if ((*psdpp)->node.node == i) { 285 *fbNum = (*psdpp)->fbNum; 286 return TRUE; 287 } 288 } 289 } 290 } 291 return FALSE; 292} 293 294/* 295 * Compare a BUS ID string with a SBUS bus id. Return TRUE if they match. 296 */ 297 298Bool 299xf86CompareSbusBusString(const char *busID, int fbNum) 300{ 301 int iFbNum; 302 303 if (xf86ParseSbusBusString(busID, &iFbNum)) { 304 return fbNum == iFbNum; 305 } else { 306 return FALSE; 307 } 308} 309 310/* 311 * Check if the slot requested is free. If it is already in use, return FALSE. 312 */ 313 314Bool 315xf86CheckSbusSlot(int fbNum) 316{ 317 int i; 318 EntityPtr p; 319 320 for (i = 0; i < xf86NumEntities; i++) { 321 p = xf86Entities[i]; 322 /* Check if this SBUS slot is taken */ 323 if (p->busType == BUS_SBUS && p->sbusBusId.fbNum == fbNum) 324 return FALSE; 325 } 326 327 return TRUE; 328} 329 330/* 331 * If the slot requested is already in use, return -1. 332 * Otherwise, claim the slot for the screen requesting it. 333 */ 334 335int 336xf86ClaimSbusSlot(sbusDevicePtr psdp, DriverPtr drvp, 337 GDevPtr dev, Bool active) 338{ 339 EntityPtr p = NULL; 340 341 int num; 342 343 if (xf86CheckSbusSlot(psdp->fbNum)) { 344 num = xf86AllocateEntity(); 345 p = xf86Entities[num]; 346 p->driver = drvp; 347 p->chipset = -1; 348 p->busType = BUS_SBUS; 349 xf86AddDevToEntity(num, dev); 350 p->sbusBusId.fbNum = psdp->fbNum; 351 p->active = active; 352 p->inUse = FALSE; 353 /* Here we initialize the access structure */ 354 p->access = xnfcalloc(1,sizeof(EntityAccessRec)); 355 p->access->fallback = &AccessNULL; 356 p->access->pAccess = &AccessNULL; 357 sbusSlotClaimed = TRUE; 358 return num; 359 } else 360 return -1; 361} 362 363_X_EXPORT int 364xf86MatchSbusInstances(const char *driverName, int sbusDevId, 365 GDevPtr *devList, int numDevs, DriverPtr drvp, 366 int **foundEntities) 367{ 368 int i,j; 369 sbusDevicePtr psdp, *psdpp; 370 int numClaimedInstances = 0; 371 int allocatedInstances = 0; 372 int numFound = 0; 373 GDevPtr devBus = NULL; 374 GDevPtr dev = NULL; 375 int *retEntities = NULL; 376 int useProm = 0; 377 378 struct Inst { 379 sbusDevicePtr sbus; 380 GDevPtr dev; 381 Bool claimed; /* BusID matches with a device section */ 382 } *instances = NULL; 383 384 *foundEntities = NULL; 385 for (psdpp = xf86SbusInfo, psdp = *psdpp; psdp; psdp = *++psdpp) { 386 if (psdp->devId != sbusDevId) 387 continue; 388 if (psdp->fd == -2) 389 continue; 390 ++allocatedInstances; 391 instances = xnfrealloc(instances, 392 allocatedInstances * sizeof(struct Inst)); 393 instances[allocatedInstances - 1].sbus = psdp; 394 instances[allocatedInstances - 1].dev = NULL; 395 instances[allocatedInstances - 1].claimed = FALSE; 396 numFound++; 397 } 398 399 /* 400 * This may be debatable, but if no SBUS devices with a matching vendor 401 * type is found, return zero now. It is probably not desirable to 402 * allow the config file to override this. 403 */ 404 if (allocatedInstances <= 0) { 405 xfree(instances); 406 return 0; 407 } 408 409 if (xf86DoProbe) { 410 xfree(instances); 411 return numFound; 412 } 413 414 if (sparcPromInit() >= 0) 415 useProm = 1; 416 417 if (xf86DoConfigure && xf86DoConfigurePass1) { 418 GDevPtr pGDev; 419 int actualcards = 0; 420 for (i = 0; i < allocatedInstances; i++) { 421 actualcards++; 422 pGDev = xf86AddBusDeviceToConfigure(drvp->driverName, BUS_SBUS, 423 instances[i].sbus, -1); 424 if (pGDev) { 425 /* 426 * XF86Match???Instances() treat chipID and chipRev as 427 * overrides, so clobber them here. 428 */ 429 pGDev->chipID = pGDev->chipRev = -1; 430 } 431 } 432 xfree(instances); 433 if (useProm) 434 sparcPromClose(); 435 return actualcards; 436 } 437 438#ifdef DEBUG 439 ErrorF("%s instances found: %d\n", driverName, allocatedInstances); 440#endif 441 442 for (i = 0; i < allocatedInstances; i++) { 443 char *promPath = NULL; 444 445 psdp = instances[i].sbus; 446 devBus = NULL; 447 dev = NULL; 448 if (useProm && psdp->node.node) 449 promPath = sparcPromNode2Pathname(&psdp->node); 450 451 for (j = 0; j < numDevs; j++) { 452 if (devList[j]->busID && *devList[j]->busID) { 453 if (xf86CompareSbusBusString(devList[j]->busID, psdp->fbNum)) { 454 if (devBus) 455 xf86MsgVerb(X_WARNING,0, 456 "%s: More than one matching Device section for " 457 "instance (BusID: %s) found: %s\n", 458 driverName,devList[j]->identifier, 459 devList[j]->busID); 460 else 461 devBus = devList[j]; 462 } 463 } else { 464 if (!dev && !devBus) { 465 if (promPath) 466 xf86Msg(X_PROBED, "Assigning device section with no busID to SBUS:%s\n", 467 promPath); 468 else 469 xf86Msg(X_PROBED, "Assigning device section with no busID to SBUS:fb%d\n", 470 psdp->fbNum); 471 dev = devList[j]; 472 } else 473 xf86MsgVerb(X_WARNING, 0, 474 "%s: More than one matching Device section " 475 "found: %s\n", driverName, devList[j]->identifier); 476 } 477 } 478 if (devBus) dev = devBus; /* busID preferred */ 479 if (!dev && psdp->fd != -2) { 480 if (promPath) { 481 xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section " 482 "for instance (BusID SBUS:%s) found\n", 483 driverName, promPath); 484 } else 485 xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section " 486 "for instance (BusID SBUS:fb%d) found\n", 487 driverName, psdp->fbNum); 488 } else if (dev) { 489 numClaimedInstances++; 490 instances[i].claimed = TRUE; 491 instances[i].dev = dev; 492 } 493 if (promPath) 494 xfree(promPath); 495 } 496 497#ifdef DEBUG 498 ErrorF("%s instances found: %d\n", driverName, numClaimedInstances); 499#endif 500 501 /* 502 * Of the claimed instances, check that another driver hasn't already 503 * claimed its slot. 504 */ 505 numFound = 0; 506 for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) { 507 if (!instances[i].claimed) 508 continue; 509 psdp = instances[i].sbus; 510 if (!xf86CheckSbusSlot(psdp->fbNum)) 511 continue; 512 513#ifdef DEBUG 514 ErrorF("%s: card at fb%d %08x is claimed by a Device section\n", 515 driverName, psdp->fbNum, psdp->node.node); 516#endif 517 518 /* Allocate an entry in the lists to be returned */ 519 numFound++; 520 retEntities = xnfrealloc(retEntities, numFound * sizeof(int)); 521 retEntities[numFound - 1] 522 = xf86ClaimSbusSlot(psdp, drvp, instances[i].dev,instances[i].dev->active ? 523 TRUE : FALSE); 524 } 525 xfree(instances); 526 if (numFound > 0) { 527 *foundEntities = retEntities; 528 } 529 530 if (useProm) 531 sparcPromClose(); 532 533 return numFound; 534} 535 536/* 537 * xf86GetSbusInfoForEntity() -- Get the sbusDevicePtr of entity. 538 */ 539_X_EXPORT sbusDevicePtr 540xf86GetSbusInfoForEntity(int entityIndex) 541{ 542 sbusDevicePtr *psdpp; 543 EntityPtr p = xf86Entities[entityIndex]; 544 545 if (entityIndex >= xf86NumEntities 546 || p->busType != BUS_SBUS) return NULL; 547 548 for (psdpp = xf86SbusInfo; *psdpp != NULL; psdpp++) { 549 if (p->sbusBusId.fbNum == (*psdpp)->fbNum) 550 return (*psdpp); 551 } 552 return NULL; 553} 554 555_X_EXPORT int 556xf86GetEntityForSbusInfo(sbusDevicePtr psdp) 557{ 558 int i; 559 560 for (i = 0; i < xf86NumEntities; i++) { 561 EntityPtr p = xf86Entities[i]; 562 if (p->busType != BUS_SBUS) continue; 563 564 if (p->sbusBusId.fbNum == psdp->fbNum) 565 return i; 566 } 567 return -1; 568} 569 570_X_EXPORT void 571xf86SbusUseBuiltinMode(ScrnInfoPtr pScrn, sbusDevicePtr psdp) 572{ 573 DisplayModePtr mode; 574 575 mode = xnfcalloc(sizeof(DisplayModeRec), 1); 576 mode->name = "current"; 577 mode->next = mode; 578 mode->prev = mode; 579 mode->type = M_T_BUILTIN; 580 mode->Clock = 100000000; 581 mode->HDisplay = psdp->width; 582 mode->HSyncStart = psdp->width; 583 mode->HSyncEnd = psdp->width; 584 mode->HTotal = psdp->width; 585 mode->VDisplay = psdp->height; 586 mode->VSyncStart = psdp->height; 587 mode->VSyncEnd = psdp->height; 588 mode->VTotal = psdp->height; 589 mode->SynthClock = mode->Clock; 590 mode->CrtcHDisplay = mode->HDisplay; 591 mode->CrtcHSyncStart = mode->HSyncStart; 592 mode->CrtcHSyncEnd = mode->HSyncEnd; 593 mode->CrtcHTotal = mode->HTotal; 594 mode->CrtcVDisplay = mode->VDisplay; 595 mode->CrtcVSyncStart = mode->VSyncStart; 596 mode->CrtcVSyncEnd = mode->VSyncEnd; 597 mode->CrtcVTotal = mode->VTotal; 598 mode->CrtcHAdjusted = FALSE; 599 mode->CrtcVAdjusted = FALSE; 600 pScrn->modes = mode; 601 pScrn->virtualX = psdp->width; 602 pScrn->virtualY = psdp->height; 603} 604 605static sbusPaletteKeyIndex; 606static DevPrivateKey sbusPaletteKey = &sbusPaletteKeyIndex; 607typedef struct _sbusCmap { 608 sbusDevicePtr psdp; 609 CloseScreenProcPtr CloseScreen; 610 Bool origCmapValid; 611 unsigned char origRed[16]; 612 unsigned char origGreen[16]; 613 unsigned char origBlue[16]; 614} sbusCmapRec, *sbusCmapPtr; 615 616#define SBUSCMAPPTR(pScreen) ((sbusCmapPtr) \ 617 dixLookupPrivate(&(pScreen)->devPrivates, sbusPaletteKey)) 618 619static void 620xf86SbusCmapLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, 621 LOCO *colors, VisualPtr pVisual) 622{ 623 int i, index; 624 sbusCmapPtr cmap; 625 struct fbcmap fbcmap; 626 unsigned char *data = xalloc(numColors*3); 627 628 cmap = SBUSCMAPPTR(pScrn->pScreen); 629 if (!cmap) return; 630 fbcmap.count = 0; 631 fbcmap.index = indices[0]; 632 fbcmap.red = data; 633 fbcmap.green = data + numColors; 634 fbcmap.blue = fbcmap.green + numColors; 635 for (i = 0; i < numColors; i++) { 636 index = indices[i]; 637 if (fbcmap.count && index != fbcmap.index + fbcmap.count) { 638 ioctl (cmap->psdp->fd, FBIOPUTCMAP, &fbcmap); 639 fbcmap.count = 0; 640 fbcmap.index = index; 641 } 642 fbcmap.red[fbcmap.count] = colors[index].red; 643 fbcmap.green[fbcmap.count] = colors[index].green; 644 fbcmap.blue[fbcmap.count++] = colors[index].blue; 645 } 646 ioctl (cmap->psdp->fd, FBIOPUTCMAP, &fbcmap); 647 xfree(data); 648} 649 650static Bool 651xf86SbusCmapCloseScreen(int i, ScreenPtr pScreen) 652{ 653 sbusCmapPtr cmap; 654 struct fbcmap fbcmap; 655 656 cmap = SBUSCMAPPTR(pScreen); 657 if (cmap->origCmapValid) { 658 fbcmap.index = 0; 659 fbcmap.count = 16; 660 fbcmap.red = cmap->origRed; 661 fbcmap.green = cmap->origGreen; 662 fbcmap.blue = cmap->origBlue; 663 ioctl (cmap->psdp->fd, FBIOPUTCMAP, &fbcmap); 664 } 665 pScreen->CloseScreen = cmap->CloseScreen; 666 xfree (cmap); 667 return (*pScreen->CloseScreen) (i, pScreen); 668} 669 670_X_EXPORT Bool 671xf86SbusHandleColormaps(ScreenPtr pScreen, sbusDevicePtr psdp) 672{ 673 sbusCmapPtr cmap; 674 struct fbcmap fbcmap; 675 unsigned char data[2]; 676 677 cmap = xnfcalloc(1, sizeof(sbusCmapRec)); 678 dixSetPrivate(&pScreen->devPrivates, sbusPaletteKey, cmap); 679 cmap->psdp = psdp; 680 fbcmap.index = 0; 681 fbcmap.count = 16; 682 fbcmap.red = cmap->origRed; 683 fbcmap.green = cmap->origGreen; 684 fbcmap.blue = cmap->origBlue; 685 if (ioctl (psdp->fd, FBIOGETCMAP, &fbcmap) >= 0) 686 cmap->origCmapValid = TRUE; 687 fbcmap.index = 0; 688 fbcmap.count = 2; 689 fbcmap.red = data; 690 fbcmap.green = data; 691 fbcmap.blue = data; 692 if (pScreen->whitePixel == 0) { 693 data[0] = 255; 694 data[1] = 0; 695 } else { 696 data[0] = 0; 697 data[1] = 255; 698 } 699 ioctl (psdp->fd, FBIOPUTCMAP, &fbcmap); 700 cmap->CloseScreen = pScreen->CloseScreen; 701 pScreen->CloseScreen = xf86SbusCmapCloseScreen; 702 return xf86HandleColormaps(pScreen, 256, 8, 703 xf86SbusCmapLoadPalette, NULL, 0); 704} 705