xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xf86sbusBus.c (23162B)


      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 
     43 Bool sbusSlotClaimed = FALSE;
     44 
     45 static int xf86nSbusInfo;
     46 
     47 static void
     48 CheckSbusDevice(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 
     82 void
     83 xf86SbusProbe(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 
    247 Bool
    248 xf86ParseSbusBusString(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 
    319 Bool
    320 xf86CompareSbusBusString(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 
    336 Bool
    337 xf86CheckSbusSlot(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 
    357 int
    358 xf86ClaimSbusSlot(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 
    381 int
    382 xf86MatchSbusInstances(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  */
    554 sbusDevicePtr
    555 xf86GetSbusInfoForEntity(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 
    570 int
    571 xf86GetEntityForSbusInfo(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 
    587 void
    588 xf86SbusUseBuiltinMode(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 
    622 static DevPrivateKeyRec sbusPaletteKeyRec;
    623 #define sbusPaletteKey (&sbusPaletteKeyRec)
    624 
    625 typedef 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 
    637 static void
    638 xf86SbusCmapLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
    639                         LOCO * colors, VisualPtr pVisual)
    640 {
    641     int i, index;
    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             ioctl(cmap->psdp->fd, FBIOPUTCMAP, &fbcmap);
    660             fbcmap.count = 0;
    661             fbcmap.index = index;
    662         }
    663         fbcmap.red[fbcmap.count] = colors[index].red;
    664         fbcmap.green[fbcmap.count] = colors[index].green;
    665         fbcmap.blue[fbcmap.count++] = colors[index].blue;
    666     }
    667     ioctl(cmap->psdp->fd, FBIOPUTCMAP, &fbcmap);
    668     free(data);
    669 }
    670 
    671 static Bool
    672 xf86SbusCmapCloseScreen(ScreenPtr pScreen)
    673 {
    674     sbusCmapPtr cmap;
    675     struct fbcmap fbcmap;
    676 
    677     cmap = SBUSCMAPPTR(pScreen);
    678     if (cmap->origCmapValid) {
    679         fbcmap.index = 0;
    680         fbcmap.count = 16;
    681         fbcmap.red = cmap->origRed;
    682         fbcmap.green = cmap->origGreen;
    683         fbcmap.blue = cmap->origBlue;
    684         ioctl(cmap->psdp->fd, FBIOPUTCMAP, &fbcmap);
    685     }
    686     pScreen->CloseScreen = cmap->CloseScreen;
    687     free(cmap);
    688     return (*pScreen->CloseScreen) (pScreen);
    689 }
    690 
    691 Bool
    692 xf86SbusHandleColormaps(ScreenPtr pScreen, sbusDevicePtr psdp)
    693 {
    694     sbusCmapPtr cmap;
    695     struct fbcmap fbcmap;
    696     unsigned char data[2];
    697 
    698     if (!dixRegisterPrivateKey(sbusPaletteKey, PRIVATE_SCREEN, 0))
    699         FatalError("Cannot register sbus private key");
    700 
    701     cmap = xnfcalloc(1, sizeof(sbusCmapRec));
    702     dixSetPrivate(&pScreen->devPrivates, sbusPaletteKey, cmap);
    703     cmap->psdp = psdp;
    704     fbcmap.index = 0;
    705     fbcmap.count = 16;
    706     fbcmap.red = cmap->origRed;
    707     fbcmap.green = cmap->origGreen;
    708     fbcmap.blue = cmap->origBlue;
    709     if (ioctl(psdp->fd, FBIOGETCMAP, &fbcmap) >= 0)
    710         cmap->origCmapValid = TRUE;
    711     fbcmap.index = 0;
    712     fbcmap.count = 2;
    713     fbcmap.red = data;
    714     fbcmap.green = data;
    715     fbcmap.blue = data;
    716     if (pScreen->whitePixel == 0) {
    717         data[0] = 255;
    718         data[1] = 0;
    719     }
    720     else {
    721         data[0] = 0;
    722         data[1] = 255;
    723     }
    724     ioctl(psdp->fd, FBIOPUTCMAP, &fbcmap);
    725     cmap->CloseScreen = pScreen->CloseScreen;
    726     pScreen->CloseScreen = xf86SbusCmapCloseScreen;
    727     return xf86HandleColormaps(pScreen, 256, 8,
    728                                xf86SbusCmapLoadPalette, NULL, 0);
    729 }
    730 
    731 Bool
    732 xf86SbusConfigure(void *busData, sbusDevicePtr sBus)
    733 {
    734     if (sBus && sBus->fbNum == ((sbusDevicePtr) busData)->fbNum)
    735         return 0;
    736     return 1;
    737 }
    738 
    739 void
    740 xf86SbusConfigureNewDev(void *busData, sbusDevicePtr sBus, GDevRec * GDev)
    741 {
    742     char *promPath = NULL;
    743 
    744     sBus = (sbusDevicePtr) busData;
    745     GDev->identifier = sBus->descr;
    746     if (sparcPromInit() >= 0) {
    747         promPath = sparcPromNode2Pathname(&sBus->node);
    748         sparcPromClose();
    749     }
    750     if (promPath) {
    751         XNFasprintf(&GDev->busID, "SBUS:%s", promPath);
    752         free(promPath);
    753     }
    754     else {
    755         XNFasprintf(&GDev->busID, "SBUS:fb%d", sBus->fbNum);
    756     }
    757 }