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
CheckSbusDevice(const char * device,int fbNum)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
xf86SbusProbe(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
xf86ParseSbusBusString(const char * busID,int * fbNum)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
xf86CompareSbusBusString(const char * busID,int fbNum)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
xf86CheckSbusSlot(int fbNum)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
xf86ClaimSbusSlot(sbusDevicePtr psdp,DriverPtr drvp,GDevPtr dev,Bool active)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
xf86MatchSbusInstances(const char * driverName,int sbusDevId,GDevPtr * devList,int numDevs,DriverPtr drvp,int ** foundEntities)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
xf86GetSbusInfoForEntity(int entityIndex)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
xf86GetEntityForSbusInfo(sbusDevicePtr psdp)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
xf86SbusUseBuiltinMode(ScrnInfoPtr pScrn,sbusDevicePtr psdp)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
xf86SbusCmapLoadPalette(ScrnInfoPtr pScrn,int numColors,int * indices,LOCO * colors,VisualPtr pVisual)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
xf86SbusCmapCloseScreen(ScreenPtr pScreen)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
xf86SbusHandleColormaps(ScreenPtr pScreen,sbusDevicePtr psdp)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
xf86SbusConfigure(void * busData,sbusDevicePtr sBus)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
xf86SbusConfigureNewDev(void * busData,sbusDevicePtr sBus,GDevRec * GDev)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 }
758