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 "xf86cmap.h" 37 38#include "xf86Bus.h" 39 40#include "xf86sbusBus.h" 41#include "xf86Sbus.h" 42 43Bool sbusSlotClaimed = FALSE; 44 45static int xf86nSbusInfo; 46 47static void 48CheckSbusDevice(const char *device, int fbNum) 49{ 50 int fd, i; 51 struct fbgattr fbattr; 52 sbusDevicePtr psdp; 53 54 fd = open(device, O_RDONLY, 0); 55 if (fd < 0) 56 return; 57 memset(&fbattr, 0, sizeof(fbattr)); 58 if (ioctl(fd, FBIOGATTR, &fbattr) < 0) { 59 if (ioctl(fd, FBIOGTYPE, &fbattr.fbtype) < 0) { 60 close(fd); 61 return; 62 } 63 } 64 close(fd); 65 for (i = 0; sbusDeviceTable[i].devId; i++) 66 if (sbusDeviceTable[i].fbType == fbattr.fbtype.fb_type) 67 break; 68 if (!sbusDeviceTable[i].devId) 69 return; 70 xf86SbusInfo = 71 xnfreallocarray(xf86SbusInfo, ++xf86nSbusInfo + 1, sizeof(psdp)); 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 = malloc(sizeof(psdp)); 90 *xf86SbusInfo = NULL; 91 for (i = 0; i < 32; i++) { 92 snprintf(fbDevName, sizeof(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"; 132 break; 133 case 5: 134 case 6: 135 case 7: 136 case 8: 137 case 9: 138 psdp->descr = "Sun Single width GX"; 139 break; 140 case 11: 141 switch (vmsize) { 142 case 2: 143 psdp->descr = "Sun Turbo GX with 1M VSIMM"; 144 break; 145 case 4: 146 psdp->descr = "Sun Turbo GX Plus"; 147 break; 148 default: 149 psdp->descr = "Sun Turbo GX"; 150 break; 151 } 152 } 153 break; 154 case SBUS_DEVICE_CG14: 155 prop = sparcPromGetProperty(&psdp->node, "reg", &len); 156 vmsize = 0; 157 if (prop && !(len % 12) && len > 0) 158 vmsize = *(int *) (prop + len - 4); 159 switch (vmsize) { 160 case 0x400000: 161 psdp->descr = "Sun SX with 4M VSIMM"; 162 break; 163 case 0x800000: 164 psdp->descr = "Sun SX with 8M VSIMM"; 165 break; 166 } 167 break; 168 case SBUS_DEVICE_LEO: 169 prop = sparcPromGetProperty(&psdp->node, "model", &len); 170 if (prop && len > 0 && !strstr(prop, "501-2503")) 171 psdp->descr = "Sun Turbo ZX"; 172 break; 173 case SBUS_DEVICE_TCX: 174 if (sparcPromGetBool(&psdp->node, "tcx-8-bit")) 175 psdp->descr = "Sun TCX (8bit)"; 176 else 177 psdp->descr = "Sun TCX (S24)"; 178 break; 179 case SBUS_DEVICE_FFB: 180 prop = sparcPromGetProperty(&psdp->node, "name", &len); 181 chiprev = 0; 182 prop = sparcPromGetProperty(&psdp->node, "board_type", &len); 183 if (prop && len == 4) 184 chiprev = *(int *) prop; 185 if (strstr(prop, "afb")) { 186 if (chiprev == 3) 187 psdp->descr = "Sun|Elite3D-M6 Horizontal"; 188 } 189 else { 190 switch (chiprev) { 191 case 0x08: 192 psdp->descr = "Sun FFB 67MHz Creator"; 193 break; 194 case 0x0b: 195 psdp->descr = "Sun FFB 67MHz Creator 3D"; 196 break; 197 case 0x1b: 198 psdp->descr = "Sun FFB 75MHz Creator 3D"; 199 break; 200 case 0x20: 201 case 0x28: 202 psdp->descr = "Sun FFB2 Vertical Creator"; 203 break; 204 case 0x23: 205 case 0x2b: 206 psdp->descr = "Sun FFB2 Vertical Creator 3D"; 207 break; 208 case 0x30: 209 psdp->descr = "Sun FFB2+ Vertical Creator"; 210 break; 211 case 0x33: 212 psdp->descr = "Sun FFB2+ Vertical Creator 3D"; 213 break; 214 case 0x40: 215 case 0x48: 216 psdp->descr = "Sun FFB2 Horizontal Creator"; 217 break; 218 case 0x43: 219 case 0x4b: 220 psdp->descr = "Sun FFB2 Horizontal Creator 3D"; 221 break; 222 } 223 } 224 break; 225 } 226 227 xf86Msg(X_PROBED, "SBUS:(0x%08x) %s", psdp->node.node, psdp->descr); 228 promPath = sparcPromNode2Pathname(&psdp->node); 229 if (promPath) { 230 xf86ErrorF(" at %s", promPath); 231 free(promPath); 232 } 233 } 234 else 235 xf86Msg(X_PROBED, "SBUS: %s", psdp->descr); 236 xf86ErrorF("\n"); 237 } 238 if (useProm) 239 sparcPromClose(); 240} 241 242/* 243 * Parse a BUS ID string, and return the SBUS bus parameters if it was 244 * in the correct format for a SBUS bus id. 245 */ 246 247static Bool 248xf86ParseSbusBusString(const char *busID, int *fbNum) 249{ 250 /* 251 * The format is assumed to be one of: 252 * "fbN", e.g. "fb1", which means the device corresponding to /dev/fbN 253 * "nameN", e.g. "cgsix0", which means Nth instance of card NAME 254 * "/prompath", e.g. "/sbus@0,10001000/cgsix@3,0" which is PROM pathname 255 * to the device. 256 */ 257 258 const char *id; 259 int i, len; 260 261 if (StringToBusType(busID, &id) != BUS_SBUS) 262 return FALSE; 263 264 if (*id != '/') { 265 if (!strncmp(id, "fb", 2)) { 266 if (!isdigit(id[2])) 267 return FALSE; 268 *fbNum = atoi(id + 2); 269 return TRUE; 270 } 271 else { 272 sbusDevicePtr *psdpp; 273 int devId; 274 275 for (i = 0, len = 0; sbusDeviceTable[i].devId; i++) { 276 len = strlen(sbusDeviceTable[i].promName); 277 if (!strncmp(sbusDeviceTable[i].promName, id, len) 278 && isdigit(id[len])) 279 break; 280 } 281 devId = sbusDeviceTable[i].devId; 282 if (!devId) 283 return FALSE; 284 i = atoi(id + len); 285 for (psdpp = xf86SbusInfo; *psdpp; ++psdpp) { 286 if ((*psdpp)->devId != devId) 287 continue; 288 if (!i) { 289 *fbNum = (*psdpp)->fbNum; 290 return TRUE; 291 } 292 i--; 293 } 294 } 295 return FALSE; 296 } 297 298 if (sparcPromInit() >= 0) { 299 i = sparcPromPathname2Node(id); 300 sparcPromClose(); 301 if (i) { 302 sbusDevicePtr *psdpp; 303 304 for (psdpp = xf86SbusInfo; *psdpp; ++psdpp) { 305 if ((*psdpp)->node.node == i) { 306 *fbNum = (*psdpp)->fbNum; 307 return TRUE; 308 } 309 } 310 } 311 } 312 return FALSE; 313} 314 315/* 316 * Compare a BUS ID string with a SBUS bus id. Return TRUE if they match. 317 */ 318 319static Bool 320xf86CompareSbusBusString(const char *busID, int fbNum) 321{ 322 int iFbNum; 323 324 if (xf86ParseSbusBusString(busID, &iFbNum)) { 325 return fbNum == iFbNum; 326 } 327 else { 328 return FALSE; 329 } 330} 331 332/* 333 * Check if the slot requested is free. If it is already in use, return FALSE. 334 */ 335 336static Bool 337xf86CheckSbusSlot(int fbNum) 338{ 339 int i; 340 EntityPtr p; 341 342 for (i = 0; i < xf86NumEntities; i++) { 343 p = xf86Entities[i]; 344 /* Check if this SBUS slot is taken */ 345 if (p->bus.type == BUS_SBUS && p->bus.id.sbus.fbNum == fbNum) 346 return FALSE; 347 } 348 349 return TRUE; 350} 351 352/* 353 * If the slot requested is already in use, return -1. 354 * Otherwise, claim the slot for the screen requesting it. 355 */ 356 357static int 358xf86ClaimSbusSlot(sbusDevicePtr psdp, DriverPtr drvp, GDevPtr dev, Bool active) 359{ 360 EntityPtr p = NULL; 361 362 int num; 363 364 if (xf86CheckSbusSlot(psdp->fbNum)) { 365 num = xf86AllocateEntity(); 366 p = xf86Entities[num]; 367 p->driver = drvp; 368 p->chipset = -1; 369 p->bus.type = BUS_SBUS; 370 xf86AddDevToEntity(num, dev); 371 p->bus.id.sbus.fbNum = psdp->fbNum; 372 p->active = active; 373 p->inUse = FALSE; 374 sbusSlotClaimed = TRUE; 375 return num; 376 } 377 else 378 return -1; 379} 380 381int 382xf86MatchSbusInstances(const char *driverName, int sbusDevId, 383 GDevPtr * devList, int numDevs, DriverPtr drvp, 384 int **foundEntities) 385{ 386 int i, j; 387 sbusDevicePtr psdp, *psdpp; 388 int numClaimedInstances = 0; 389 int allocatedInstances = 0; 390 int numFound = 0; 391 GDevPtr devBus = NULL; 392 GDevPtr dev = NULL; 393 int *retEntities = NULL; 394 int useProm = 0; 395 396 struct Inst { 397 sbusDevicePtr sbus; 398 GDevPtr dev; 399 Bool claimed; /* BusID matches with a device section */ 400 } *instances = NULL; 401 402 *foundEntities = NULL; 403 for (psdpp = xf86SbusInfo, psdp = *psdpp; psdp; psdp = *++psdpp) { 404 if (psdp->devId != sbusDevId) 405 continue; 406 if (psdp->fd == -2) 407 continue; 408 ++allocatedInstances; 409 instances = xnfreallocarray(instances, 410 allocatedInstances, sizeof(struct Inst)); 411 instances[allocatedInstances - 1].sbus = psdp; 412 instances[allocatedInstances - 1].dev = NULL; 413 instances[allocatedInstances - 1].claimed = FALSE; 414 numFound++; 415 } 416 417 /* 418 * This may be debatable, but if no SBUS devices with a matching vendor 419 * type is found, return zero now. It is probably not desirable to 420 * allow the config file to override this. 421 */ 422 if (allocatedInstances <= 0) { 423 free(instances); 424 return 0; 425 } 426 427 if (sparcPromInit() >= 0) 428 useProm = 1; 429 430 if (xf86DoConfigure && xf86DoConfigurePass1) { 431 GDevPtr pGDev; 432 int actualcards = 0; 433 434 for (i = 0; i < allocatedInstances; i++) { 435 actualcards++; 436 pGDev = xf86AddBusDeviceToConfigure(drvp->driverName, BUS_SBUS, 437 instances[i].sbus, -1); 438 if (pGDev) { 439 /* 440 * XF86Match???Instances() treat chipID and chipRev as 441 * overrides, so clobber them here. 442 */ 443 pGDev->chipID = pGDev->chipRev = -1; 444 } 445 } 446 free(instances); 447 if (useProm) 448 sparcPromClose(); 449 return actualcards; 450 } 451 452 DebugF("%s instances found: %d\n", driverName, allocatedInstances); 453 454 for (i = 0; i < allocatedInstances; i++) { 455 char *promPath = NULL; 456 457 psdp = instances[i].sbus; 458 devBus = NULL; 459 dev = NULL; 460 if (useProm && psdp->node.node) 461 promPath = sparcPromNode2Pathname(&psdp->node); 462 463 for (j = 0; j < numDevs; j++) { 464 if (devList[j]->busID && *devList[j]->busID) { 465 if (xf86CompareSbusBusString(devList[j]->busID, psdp->fbNum)) { 466 if (devBus) 467 xf86MsgVerb(X_WARNING, 0, 468 "%s: More than one matching Device section for " 469 "instance (BusID: %s) found: %s\n", 470 driverName, devList[j]->identifier, 471 devList[j]->busID); 472 else 473 devBus = devList[j]; 474 } 475 } 476 else { 477 if (!dev && !devBus) { 478 if (promPath) 479 xf86Msg(X_PROBED, 480 "Assigning device section with no busID to SBUS:%s\n", 481 promPath); 482 else 483 xf86Msg(X_PROBED, 484 "Assigning device section with no busID to SBUS:fb%d\n", 485 psdp->fbNum); 486 dev = devList[j]; 487 } 488 else 489 xf86MsgVerb(X_WARNING, 0, 490 "%s: More than one matching Device section " 491 "found: %s\n", driverName, 492 devList[j]->identifier); 493 } 494 } 495 if (devBus) 496 dev = devBus; /* busID preferred */ 497 if (!dev && psdp->fd != -2) { 498 if (promPath) { 499 xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section " 500 "for instance (BusID SBUS:%s) found\n", 501 driverName, promPath); 502 } 503 else 504 xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section " 505 "for instance (BusID SBUS:fb%d) found\n", 506 driverName, psdp->fbNum); 507 } 508 else if (dev) { 509 numClaimedInstances++; 510 instances[i].claimed = TRUE; 511 instances[i].dev = dev; 512 } 513 free(promPath); 514 } 515 516 DebugF("%s instances found: %d\n", driverName, numClaimedInstances); 517 518 /* 519 * Of the claimed instances, check that another driver hasn't already 520 * claimed its slot. 521 */ 522 numFound = 0; 523 for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) { 524 if (!instances[i].claimed) 525 continue; 526 psdp = instances[i].sbus; 527 if (!xf86CheckSbusSlot(psdp->fbNum)) 528 continue; 529 530 DebugF("%s: card at fb%d %08x is claimed by a Device section\n", 531 driverName, psdp->fbNum, psdp->node.node); 532 533 /* Allocate an entry in the lists to be returned */ 534 numFound++; 535 retEntities = xnfreallocarray(retEntities, numFound, sizeof(int)); 536 retEntities[numFound - 1] 537 = xf86ClaimSbusSlot(psdp, drvp, instances[i].dev, 538 instances[i].dev->active ? TRUE : FALSE); 539 } 540 free(instances); 541 if (numFound > 0) { 542 *foundEntities = retEntities; 543 } 544 545 if (useProm) 546 sparcPromClose(); 547 548 return numFound; 549} 550 551/* 552 * xf86GetSbusInfoForEntity() -- Get the sbusDevicePtr of entity. 553 */ 554sbusDevicePtr 555xf86GetSbusInfoForEntity(int entityIndex) 556{ 557 sbusDevicePtr *psdpp; 558 EntityPtr p = xf86Entities[entityIndex]; 559 560 if (entityIndex >= xf86NumEntities || p->bus.type != BUS_SBUS) 561 return NULL; 562 563 for (psdpp = xf86SbusInfo; *psdpp != NULL; psdpp++) { 564 if (p->bus.id.sbus.fbNum == (*psdpp)->fbNum) 565 return *psdpp; 566 } 567 return NULL; 568} 569 570int 571xf86GetEntityForSbusInfo(sbusDevicePtr psdp) 572{ 573 int i; 574 575 for (i = 0; i < xf86NumEntities; i++) { 576 EntityPtr p = xf86Entities[i]; 577 578 if (p->bus.type != BUS_SBUS) 579 continue; 580 581 if (p->bus.id.sbus.fbNum == psdp->fbNum) 582 return i; 583 } 584 return -1; 585} 586 587void 588xf86SbusUseBuiltinMode(ScrnInfoPtr pScrn, sbusDevicePtr psdp) 589{ 590 DisplayModePtr mode; 591 592 mode = xnfcalloc(sizeof(DisplayModeRec), 1); 593 mode->name = "current"; 594 mode->next = mode; 595 mode->prev = mode; 596 mode->type = M_T_BUILTIN; 597 mode->Clock = 100000000; 598 mode->HDisplay = psdp->width; 599 mode->HSyncStart = psdp->width; 600 mode->HSyncEnd = psdp->width; 601 mode->HTotal = psdp->width; 602 mode->VDisplay = psdp->height; 603 mode->VSyncStart = psdp->height; 604 mode->VSyncEnd = psdp->height; 605 mode->VTotal = psdp->height; 606 mode->SynthClock = mode->Clock; 607 mode->CrtcHDisplay = mode->HDisplay; 608 mode->CrtcHSyncStart = mode->HSyncStart; 609 mode->CrtcHSyncEnd = mode->HSyncEnd; 610 mode->CrtcHTotal = mode->HTotal; 611 mode->CrtcVDisplay = mode->VDisplay; 612 mode->CrtcVSyncStart = mode->VSyncStart; 613 mode->CrtcVSyncEnd = mode->VSyncEnd; 614 mode->CrtcVTotal = mode->VTotal; 615 mode->CrtcHAdjusted = FALSE; 616 mode->CrtcVAdjusted = FALSE; 617 pScrn->modes = mode; 618 pScrn->virtualX = psdp->width; 619 pScrn->virtualY = psdp->height; 620} 621 622static DevPrivateKeyRec sbusPaletteKeyRec; 623#define sbusPaletteKey (&sbusPaletteKeyRec) 624 625typedef struct _sbusCmap { 626 sbusDevicePtr psdp; 627 CloseScreenProcPtr CloseScreen; 628 Bool origCmapValid; 629 unsigned char origRed[16]; 630 unsigned char origGreen[16]; 631 unsigned char origBlue[16]; 632} sbusCmapRec, *sbusCmapPtr; 633 634#define SBUSCMAPPTR(pScreen) ((sbusCmapPtr) \ 635 dixLookupPrivate(&(pScreen)->devPrivates, sbusPaletteKey)) 636 637static void 638xf86SbusCmapLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, 639 LOCO * colors, VisualPtr pVisual) 640{ 641 int i, index, ret; 642 sbusCmapPtr cmap; 643 struct fbcmap fbcmap; 644 unsigned char *data; 645 646 cmap = SBUSCMAPPTR(pScrn->pScreen); 647 if (!cmap) 648 return; 649 fbcmap.count = 0; 650 fbcmap.index = indices[0]; 651 fbcmap.red = data = xallocarray(numColors, 3); 652 if (!data) 653 return; 654 fbcmap.green = data + numColors; 655 fbcmap.blue = fbcmap.green + numColors; 656 for (i = 0; i < numColors; i++) { 657 index = indices[i]; 658 if (fbcmap.count && index != fbcmap.index + fbcmap.count) { 659 ret = ioctl(cmap->psdp->fd, FBIOPUTCMAP, &fbcmap); 660 if (ret != 0) 661 xf86Msg(X_ERROR, "%s: ioctl(%d, FBIOPUTCMAP): %d %d\n", 662 __func__, cmap->psdp->fd, ret, errno); 663 fbcmap.count = 0; 664 fbcmap.index = index; 665 } 666 fbcmap.red[fbcmap.count] = colors[index].red; 667 fbcmap.green[fbcmap.count] = colors[index].green; 668 fbcmap.blue[fbcmap.count++] = colors[index].blue; 669 } 670 ret = ioctl(cmap->psdp->fd, FBIOPUTCMAP, &fbcmap); 671 if (ret != 0) 672 xf86Msg(X_ERROR, "%s: ioctl(%d, FBIOPUTCMAP): %d %d\n", __func__, 673 cmap->psdp->fd, ret, errno); 674 free(data); 675} 676 677static Bool 678xf86SbusCmapCloseScreen(ScreenPtr pScreen) 679{ 680 sbusCmapPtr cmap; 681 struct fbcmap fbcmap; 682 683 cmap = SBUSCMAPPTR(pScreen); 684 if (cmap->origCmapValid) { 685 fbcmap.index = 0; 686 fbcmap.count = 16; 687 fbcmap.red = cmap->origRed; 688 fbcmap.green = cmap->origGreen; 689 fbcmap.blue = cmap->origBlue; 690 ioctl(cmap->psdp->fd, FBIOPUTCMAP, &fbcmap); 691 } 692 pScreen->CloseScreen = cmap->CloseScreen; 693 free(cmap); 694 return (*pScreen->CloseScreen) (pScreen); 695} 696 697Bool 698xf86SbusHandleColormaps(ScreenPtr pScreen, sbusDevicePtr psdp) 699{ 700 sbusCmapPtr cmap; 701 struct fbcmap fbcmap; 702 int ret; 703 unsigned char data[2]; 704 705 if (!dixRegisterPrivateKey(sbusPaletteKey, PRIVATE_SCREEN, 0)) 706 FatalError("Cannot register sbus private key"); 707 708 cmap = xnfcalloc(1, sizeof(sbusCmapRec)); 709 if (!dixPrivateKeyRegistered(sbusPaletteKey)) { 710 dixRegisterPrivateKey(sbusPaletteKey, PRIVATE_SCREEN, 0); 711 } 712 dixSetPrivate(&pScreen->devPrivates, sbusPaletteKey, cmap); 713 cmap->psdp = psdp; 714 fbcmap.index = 0; 715 fbcmap.count = 16; 716 fbcmap.red = cmap->origRed; 717 fbcmap.green = cmap->origGreen; 718 fbcmap.blue = cmap->origBlue; 719 if (ioctl(psdp->fd, FBIOGETCMAP, &fbcmap) >= 0) 720 cmap->origCmapValid = TRUE; 721 fbcmap.index = 0; 722 fbcmap.count = 2; 723 fbcmap.red = data; 724 fbcmap.green = data; 725 fbcmap.blue = data; 726 if (pScreen->whitePixel == 0) { 727 data[0] = 255; 728 data[1] = 0; 729 } else { 730 data[0] = 0; 731 data[1] = 255; 732 } 733 ret = ioctl(psdp->fd, FBIOPUTCMAP, &fbcmap); 734 if (ret != 0) 735 xf86Msg(X_ERROR, "%s: ioctl(%d, FBIOPUTCMAP): %d %d\n", __func__, 736 psdp->fd, ret, errno); 737 cmap->CloseScreen = pScreen->CloseScreen; 738 pScreen->CloseScreen = xf86SbusCmapCloseScreen; 739 return xf86HandleColormaps(pScreen, 256, 8, 740 xf86SbusCmapLoadPalette, NULL, 0); 741} 742 743Bool 744xf86SbusConfigure(void *busData, sbusDevicePtr sBus) 745{ 746 if (sBus && sBus->fbNum == ((sbusDevicePtr) busData)->fbNum) 747 return 0; 748 return 1; 749} 750 751void 752xf86SbusConfigureNewDev(void *busData, sbusDevicePtr sBus, GDevRec * GDev) 753{ 754 char *promPath = NULL; 755 char *tmp; 756 757 sBus = (sbusDevicePtr) busData; 758 GDev->identifier = sBus->descr; 759 if (sparcPromInit() >= 0) { 760 promPath = sparcPromNode2Pathname(&sBus->node); 761 sparcPromClose(); 762 } 763 if (promPath) { 764 XNFasprintf(&tmp, "SBUS:%s", promPath); 765 free(promPath); 766 } 767 else { 768 XNFasprintf(&tmp, "SBUS:fb%d", sBus->fbNum); 769 } 770 GDev->busID = tmp; 771} 772