xref: /OK3568_Linux_fs/external/xserver/hw/xfree86/os-support/bus/Sbus.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * SBUS and OpenPROM access functions.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com)
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*4882a593Smuzhiyun  * of this software and associated documentation files (the "Software"), to deal
8*4882a593Smuzhiyun  * in the Software without restriction, including without limitation the rights
9*4882a593Smuzhiyun  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10*4882a593Smuzhiyun  * copies of the Software, and to permit persons to whom the Software is
11*4882a593Smuzhiyun  * furnished to do so, subject to the following conditions:
12*4882a593Smuzhiyun  *
13*4882a593Smuzhiyun  * The above copyright notice and this permission notice shall be included in
14*4882a593Smuzhiyun  * all copies or substantial portions of the Software.
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*4882a593Smuzhiyun  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*4882a593Smuzhiyun  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19*4882a593Smuzhiyun  * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20*4882a593Smuzhiyun  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21*4882a593Smuzhiyun  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22*4882a593Smuzhiyun  */
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #ifdef HAVE_XORG_CONFIG_H
25*4882a593Smuzhiyun #include <xorg-config.h>
26*4882a593Smuzhiyun #endif
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #include <fcntl.h>
29*4882a593Smuzhiyun #include <stdio.h>
30*4882a593Smuzhiyun #include <unistd.h>
31*4882a593Smuzhiyun #include <stdlib.h>
32*4882a593Smuzhiyun #include <sys/ioctl.h>
33*4882a593Smuzhiyun #include <sys/mman.h>
34*4882a593Smuzhiyun #ifdef __sun
35*4882a593Smuzhiyun #include <sys/utsname.h>
36*4882a593Smuzhiyun #endif
37*4882a593Smuzhiyun #include "xf86.h"
38*4882a593Smuzhiyun #include "xf86Priv.h"
39*4882a593Smuzhiyun #include "xf86_OSlib.h"
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #include "xf86sbusBus.h"
42*4882a593Smuzhiyun #include "xf86Sbus.h"
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun int promRootNode;
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun static int promFd = -1;
47*4882a593Smuzhiyun static int promCurrentNode;
48*4882a593Smuzhiyun static int promOpenCount = 0;
49*4882a593Smuzhiyun static int promP1275 = -1;
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #define MAX_PROP	128
52*4882a593Smuzhiyun #define MAX_VAL		(4096-128-4)
53*4882a593Smuzhiyun static struct openpromio *promOpio;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun sbusDevicePtr *xf86SbusInfo = NULL;
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun struct sbus_devtable sbusDeviceTable[] = {
58*4882a593Smuzhiyun     {SBUS_DEVICE_BW2, FBTYPE_SUN2BW, "bwtwo", "sunbw2",
59*4882a593Smuzhiyun      "Sun Monochrome (bwtwo)"},
60*4882a593Smuzhiyun     {SBUS_DEVICE_CG2, FBTYPE_SUN2COLOR, "cgtwo", NULL, "Sun Color2 (cgtwo)"},
61*4882a593Smuzhiyun     {SBUS_DEVICE_CG3, FBTYPE_SUN3COLOR, "cgthree", "suncg3",
62*4882a593Smuzhiyun      "Sun Color3 (cgthree)"},
63*4882a593Smuzhiyun     {SBUS_DEVICE_CG4, FBTYPE_SUN4COLOR, "cgfour", NULL, "Sun Color4 (cgfour)"},
64*4882a593Smuzhiyun     {SBUS_DEVICE_CG6, FBTYPE_SUNFAST_COLOR, "cgsix", "suncg6", "Sun GX"},
65*4882a593Smuzhiyun     {SBUS_DEVICE_CG8, FBTYPE_MEMCOLOR, "cgeight", NULL, "Sun CG8/RasterOps"},
66*4882a593Smuzhiyun     {SBUS_DEVICE_CG12, FBTYPE_SUNGP3, "cgtwelve", NULL, "Sun GS (cgtwelve)"},
67*4882a593Smuzhiyun     {SBUS_DEVICE_CG14, FBTYPE_MDICOLOR, "cgfourteen", "suncg14", "Sun SX"},
68*4882a593Smuzhiyun     {SBUS_DEVICE_GT, FBTYPE_SUNGT, "gt", NULL, "Sun Graphics Tower"},
69*4882a593Smuzhiyun     {SBUS_DEVICE_MGX, -1, "mgx", NULL, "Quantum 3D MGXplus"},
70*4882a593Smuzhiyun     {SBUS_DEVICE_LEO, FBTYPE_SUNLEO, "leo", "sunleo", "Sun ZX or Turbo ZX"},
71*4882a593Smuzhiyun     {SBUS_DEVICE_TCX, FBTYPE_TCXCOLOR, "tcx", "suntcx", "Sun TCX"},
72*4882a593Smuzhiyun     {SBUS_DEVICE_FFB, FBTYPE_CREATOR, "ffb", "sunffb", "Sun FFB"},
73*4882a593Smuzhiyun     {SBUS_DEVICE_FFB, FBTYPE_CREATOR, "afb", "sunffb", "Sun Elite3D"},
74*4882a593Smuzhiyun     {0, 0, NULL}
75*4882a593Smuzhiyun };
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun int
promGetSibling(int node)78*4882a593Smuzhiyun promGetSibling(int node)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun     promOpio->oprom_size = sizeof(int);
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun     if (node == -1)
83*4882a593Smuzhiyun         return 0;
84*4882a593Smuzhiyun     *(int *) promOpio->oprom_array = node;
85*4882a593Smuzhiyun     if (ioctl(promFd, OPROMNEXT, promOpio) < 0)
86*4882a593Smuzhiyun         return 0;
87*4882a593Smuzhiyun     promCurrentNode = *(int *) promOpio->oprom_array;
88*4882a593Smuzhiyun     return *(int *) promOpio->oprom_array;
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun int
promGetChild(int node)92*4882a593Smuzhiyun promGetChild(int node)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun     promOpio->oprom_size = sizeof(int);
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun     if (!node || node == -1)
97*4882a593Smuzhiyun         return 0;
98*4882a593Smuzhiyun     *(int *) promOpio->oprom_array = node;
99*4882a593Smuzhiyun     if (ioctl(promFd, OPROMCHILD, promOpio) < 0)
100*4882a593Smuzhiyun         return 0;
101*4882a593Smuzhiyun     promCurrentNode = *(int *) promOpio->oprom_array;
102*4882a593Smuzhiyun     return *(int *) promOpio->oprom_array;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun char *
promGetProperty(const char * prop,int * lenp)106*4882a593Smuzhiyun promGetProperty(const char *prop, int *lenp)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun     promOpio->oprom_size = MAX_VAL;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun     strcpy(promOpio->oprom_array, prop);
111*4882a593Smuzhiyun     if (ioctl(promFd, OPROMGETPROP, promOpio) < 0)
112*4882a593Smuzhiyun         return 0;
113*4882a593Smuzhiyun     if (lenp)
114*4882a593Smuzhiyun         *lenp = promOpio->oprom_size;
115*4882a593Smuzhiyun     return promOpio->oprom_array;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun int
promGetBool(const char * prop)119*4882a593Smuzhiyun promGetBool(const char *prop)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun     promOpio->oprom_size = 0;
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun     *(int *) promOpio->oprom_array = 0;
124*4882a593Smuzhiyun     for (;;) {
125*4882a593Smuzhiyun         promOpio->oprom_size = MAX_PROP;
126*4882a593Smuzhiyun         if (ioctl(promFd, OPROMNXTPROP, promOpio) < 0)
127*4882a593Smuzhiyun             return 0;
128*4882a593Smuzhiyun         if (!promOpio->oprom_size)
129*4882a593Smuzhiyun             return 0;
130*4882a593Smuzhiyun         if (!strcmp(promOpio->oprom_array, prop))
131*4882a593Smuzhiyun             return 1;
132*4882a593Smuzhiyun     }
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun #define PROM_NODE_SIBLING 0x01
136*4882a593Smuzhiyun #define PROM_NODE_PREF    0x02
137*4882a593Smuzhiyun #define PROM_NODE_SBUS    0x04
138*4882a593Smuzhiyun #define PROM_NODE_EBUS    0x08
139*4882a593Smuzhiyun #define PROM_NODE_PCI     0x10
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun static int
promSetNode(sbusPromNodePtr pnode)142*4882a593Smuzhiyun promSetNode(sbusPromNodePtr pnode)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun     int node;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun     if (!pnode->node || pnode->node == -1)
147*4882a593Smuzhiyun         return -1;
148*4882a593Smuzhiyun     if (pnode->cookie[0] & PROM_NODE_SIBLING)
149*4882a593Smuzhiyun         node = promGetSibling(pnode->cookie[1]);
150*4882a593Smuzhiyun     else
151*4882a593Smuzhiyun         node = promGetChild(pnode->cookie[1]);
152*4882a593Smuzhiyun     if (pnode->node != node)
153*4882a593Smuzhiyun         return -1;
154*4882a593Smuzhiyun     return 0;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun static void
promIsP1275(void)158*4882a593Smuzhiyun promIsP1275(void)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun #ifdef __linux__
161*4882a593Smuzhiyun     FILE *f;
162*4882a593Smuzhiyun     char buffer[1024];
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun     if (promP1275 != -1)
165*4882a593Smuzhiyun         return;
166*4882a593Smuzhiyun     promP1275 = 0;
167*4882a593Smuzhiyun     f = fopen("/proc/cpuinfo", "r");
168*4882a593Smuzhiyun     if (!f)
169*4882a593Smuzhiyun         return;
170*4882a593Smuzhiyun     while (fgets(buffer, 1024, f) != NULL)
171*4882a593Smuzhiyun         if (!strncmp(buffer, "type", 4) && strstr(buffer, "sun4u")) {
172*4882a593Smuzhiyun             promP1275 = 1;
173*4882a593Smuzhiyun             break;
174*4882a593Smuzhiyun         }
175*4882a593Smuzhiyun     fclose(f);
176*4882a593Smuzhiyun #elif defined(__sun)
177*4882a593Smuzhiyun     struct utsname buffer;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun     if ((uname(&buffer) >= 0) && !strcmp(buffer.machine, "sun4u"))
180*4882a593Smuzhiyun         promP1275 = TRUE;
181*4882a593Smuzhiyun     else
182*4882a593Smuzhiyun         promP1275 = FALSE;
183*4882a593Smuzhiyun #elif defined(__FreeBSD__)
184*4882a593Smuzhiyun     promP1275 = TRUE;
185*4882a593Smuzhiyun #else
186*4882a593Smuzhiyun #error Missing promIsP1275() function for this OS
187*4882a593Smuzhiyun #endif
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun void
sparcPromClose(void)191*4882a593Smuzhiyun sparcPromClose(void)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun     if (promOpenCount > 1) {
194*4882a593Smuzhiyun         promOpenCount--;
195*4882a593Smuzhiyun         return;
196*4882a593Smuzhiyun     }
197*4882a593Smuzhiyun     if (promFd != -1) {
198*4882a593Smuzhiyun         close(promFd);
199*4882a593Smuzhiyun         promFd = -1;
200*4882a593Smuzhiyun     }
201*4882a593Smuzhiyun     free(promOpio);
202*4882a593Smuzhiyun     promOpio = NULL;
203*4882a593Smuzhiyun     promOpenCount = 0;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun int
sparcPromInit(void)207*4882a593Smuzhiyun sparcPromInit(void)
208*4882a593Smuzhiyun {
209*4882a593Smuzhiyun     if (promOpenCount) {
210*4882a593Smuzhiyun         promOpenCount++;
211*4882a593Smuzhiyun         return 0;
212*4882a593Smuzhiyun     }
213*4882a593Smuzhiyun     promFd = open("/dev/openprom", O_RDONLY, 0);
214*4882a593Smuzhiyun     if (promFd == -1)
215*4882a593Smuzhiyun         return -1;
216*4882a593Smuzhiyun     promOpio = (struct openpromio *) malloc(4096);
217*4882a593Smuzhiyun     if (!promOpio) {
218*4882a593Smuzhiyun         sparcPromClose();
219*4882a593Smuzhiyun         return -1;
220*4882a593Smuzhiyun     }
221*4882a593Smuzhiyun     promRootNode = promGetSibling(0);
222*4882a593Smuzhiyun     if (!promRootNode) {
223*4882a593Smuzhiyun         sparcPromClose();
224*4882a593Smuzhiyun         return -1;
225*4882a593Smuzhiyun     }
226*4882a593Smuzhiyun     promIsP1275();
227*4882a593Smuzhiyun     promOpenCount++;
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun     return 0;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun char *
sparcPromGetProperty(sbusPromNodePtr pnode,const char * prop,int * lenp)233*4882a593Smuzhiyun sparcPromGetProperty(sbusPromNodePtr pnode, const char *prop, int *lenp)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun     if (promSetNode(pnode))
236*4882a593Smuzhiyun         return NULL;
237*4882a593Smuzhiyun     return promGetProperty(prop, lenp);
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun int
sparcPromGetBool(sbusPromNodePtr pnode,const char * prop)241*4882a593Smuzhiyun sparcPromGetBool(sbusPromNodePtr pnode, const char *prop)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun     if (promSetNode(pnode))
244*4882a593Smuzhiyun         return 0;
245*4882a593Smuzhiyun     return promGetBool(prop);
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun static char *
promWalkGetDriverName(int node,int oldnode)249*4882a593Smuzhiyun promWalkGetDriverName(int node, int oldnode)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun     int nextnode;
252*4882a593Smuzhiyun     int len;
253*4882a593Smuzhiyun     char *prop;
254*4882a593Smuzhiyun     int devId, i;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun     prop = promGetProperty("device_type", &len);
257*4882a593Smuzhiyun     if (prop && (len > 0))
258*4882a593Smuzhiyun         do {
259*4882a593Smuzhiyun             if (!strcmp(prop, "display")) {
260*4882a593Smuzhiyun                 prop = promGetProperty("name", &len);
261*4882a593Smuzhiyun                 if (!prop || len <= 0)
262*4882a593Smuzhiyun                     break;
263*4882a593Smuzhiyun                 while ((*prop >= 'A' && *prop <= 'Z') || *prop == ',')
264*4882a593Smuzhiyun                     prop++;
265*4882a593Smuzhiyun                 for (i = 0; sbusDeviceTable[i].devId; i++)
266*4882a593Smuzhiyun                     if (!strcmp(prop, sbusDeviceTable[i].promName))
267*4882a593Smuzhiyun                         break;
268*4882a593Smuzhiyun                 devId = sbusDeviceTable[i].devId;
269*4882a593Smuzhiyun                 if (!devId)
270*4882a593Smuzhiyun                     break;
271*4882a593Smuzhiyun                 if (sbusDeviceTable[i].driverName)
272*4882a593Smuzhiyun                     return sbusDeviceTable[i].driverName;
273*4882a593Smuzhiyun             }
274*4882a593Smuzhiyun         } while (0);
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun     nextnode = promGetChild(node);
277*4882a593Smuzhiyun     if (nextnode) {
278*4882a593Smuzhiyun         char *name;
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun         name = promWalkGetDriverName(nextnode, node);
281*4882a593Smuzhiyun         if (name)
282*4882a593Smuzhiyun             return name;
283*4882a593Smuzhiyun     }
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun     nextnode = promGetSibling(node);
286*4882a593Smuzhiyun     if (nextnode)
287*4882a593Smuzhiyun         return promWalkGetDriverName(nextnode, node);
288*4882a593Smuzhiyun     return NULL;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun char *
sparcDriverName(void)292*4882a593Smuzhiyun sparcDriverName(void)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun     char *name;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun     if (sparcPromInit() < 0)
297*4882a593Smuzhiyun         return NULL;
298*4882a593Smuzhiyun     promGetSibling(0);
299*4882a593Smuzhiyun     name = promWalkGetDriverName(promRootNode, 0);
300*4882a593Smuzhiyun     sparcPromClose();
301*4882a593Smuzhiyun     return name;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun static void
promWalkAssignNodes(int node,int oldnode,int flags,sbusDevicePtr * devicePtrs)305*4882a593Smuzhiyun promWalkAssignNodes(int node, int oldnode, int flags,
306*4882a593Smuzhiyun                     sbusDevicePtr * devicePtrs)
307*4882a593Smuzhiyun {
308*4882a593Smuzhiyun     int nextnode;
309*4882a593Smuzhiyun     int len, sbus = flags & PROM_NODE_SBUS;
310*4882a593Smuzhiyun     char *prop;
311*4882a593Smuzhiyun     int devId, i, j;
312*4882a593Smuzhiyun     sbusPromNode pNode, pNode2;
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun     prop = promGetProperty("device_type", &len);
315*4882a593Smuzhiyun     if (prop && (len > 0))
316*4882a593Smuzhiyun         do {
317*4882a593Smuzhiyun             if (!strcmp(prop, "display")) {
318*4882a593Smuzhiyun                 prop = promGetProperty("name", &len);
319*4882a593Smuzhiyun                 if (!prop || len <= 0)
320*4882a593Smuzhiyun                     break;
321*4882a593Smuzhiyun                 while ((*prop >= 'A' && *prop <= 'Z') || *prop == ',')
322*4882a593Smuzhiyun                     prop++;
323*4882a593Smuzhiyun                 for (i = 0; sbusDeviceTable[i].devId; i++)
324*4882a593Smuzhiyun                     if (!strcmp(prop, sbusDeviceTable[i].promName))
325*4882a593Smuzhiyun                         break;
326*4882a593Smuzhiyun                 devId = sbusDeviceTable[i].devId;
327*4882a593Smuzhiyun                 if (!devId)
328*4882a593Smuzhiyun                     break;
329*4882a593Smuzhiyun                 if (!sbus) {
330*4882a593Smuzhiyun                     if (devId == SBUS_DEVICE_FFB) {
331*4882a593Smuzhiyun                         /*
332*4882a593Smuzhiyun                          * All /SUNW,ffb outside of SBUS tree come before all
333*4882a593Smuzhiyun                          * /SUNW,afb outside of SBUS tree in Linux.
334*4882a593Smuzhiyun                          */
335*4882a593Smuzhiyun                         if (!strcmp(prop, "afb"))
336*4882a593Smuzhiyun                             flags |= PROM_NODE_PREF;
337*4882a593Smuzhiyun                     }
338*4882a593Smuzhiyun                     else if (devId != SBUS_DEVICE_CG14)
339*4882a593Smuzhiyun                         break;
340*4882a593Smuzhiyun                 }
341*4882a593Smuzhiyun                 for (i = 0; i < 32; i++) {
342*4882a593Smuzhiyun                     if (!devicePtrs[i] || devicePtrs[i]->devId != devId)
343*4882a593Smuzhiyun                         continue;
344*4882a593Smuzhiyun                     if (devicePtrs[i]->node.node) {
345*4882a593Smuzhiyun                         if ((devicePtrs[i]->node.
346*4882a593Smuzhiyun                              cookie[0] & ~PROM_NODE_SIBLING) <=
347*4882a593Smuzhiyun                             (flags & ~PROM_NODE_SIBLING))
348*4882a593Smuzhiyun                             continue;
349*4882a593Smuzhiyun                         for (j = i + 1, pNode = devicePtrs[i]->node; j < 32;
350*4882a593Smuzhiyun                              j++) {
351*4882a593Smuzhiyun                             if (!devicePtrs[j] || devicePtrs[j]->devId != devId)
352*4882a593Smuzhiyun                                 continue;
353*4882a593Smuzhiyun                             pNode2 = devicePtrs[j]->node;
354*4882a593Smuzhiyun                             devicePtrs[j]->node = pNode;
355*4882a593Smuzhiyun                             pNode = pNode2;
356*4882a593Smuzhiyun                         }
357*4882a593Smuzhiyun                     }
358*4882a593Smuzhiyun                     devicePtrs[i]->node.node = node;
359*4882a593Smuzhiyun                     devicePtrs[i]->node.cookie[0] = flags;
360*4882a593Smuzhiyun                     devicePtrs[i]->node.cookie[1] = oldnode;
361*4882a593Smuzhiyun                     break;
362*4882a593Smuzhiyun                 }
363*4882a593Smuzhiyun                 break;
364*4882a593Smuzhiyun             }
365*4882a593Smuzhiyun         } while (0);
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun     prop = promGetProperty("name", &len);
368*4882a593Smuzhiyun     if (prop && len > 0) {
369*4882a593Smuzhiyun         if (!strcmp(prop, "sbus") || !strcmp(prop, "sbi"))
370*4882a593Smuzhiyun             sbus = PROM_NODE_SBUS;
371*4882a593Smuzhiyun     }
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun     nextnode = promGetChild(node);
374*4882a593Smuzhiyun     if (nextnode)
375*4882a593Smuzhiyun         promWalkAssignNodes(nextnode, node, sbus, devicePtrs);
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun     nextnode = promGetSibling(node);
378*4882a593Smuzhiyun     if (nextnode)
379*4882a593Smuzhiyun         promWalkAssignNodes(nextnode, node, PROM_NODE_SIBLING | sbus,
380*4882a593Smuzhiyun                             devicePtrs);
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun void
sparcPromAssignNodes(void)384*4882a593Smuzhiyun sparcPromAssignNodes(void)
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun     sbusDevicePtr psdp, *psdpp;
387*4882a593Smuzhiyun     int n, holes = 0, i, j;
388*4882a593Smuzhiyun     FILE *f;
389*4882a593Smuzhiyun     sbusDevicePtr devicePtrs[32];
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun     memset(devicePtrs, 0, sizeof(devicePtrs));
392*4882a593Smuzhiyun     for (psdpp = xf86SbusInfo, n = 0; (psdp = *psdpp); psdpp++, n++) {
393*4882a593Smuzhiyun         if (psdp->fbNum != n)
394*4882a593Smuzhiyun             holes = 1;
395*4882a593Smuzhiyun         devicePtrs[psdp->fbNum] = psdp;
396*4882a593Smuzhiyun     }
397*4882a593Smuzhiyun     if (holes && (f = fopen("/proc/fb", "r")) != NULL) {
398*4882a593Smuzhiyun         /* We could not open one of fb devices, check /proc/fb to see what
399*4882a593Smuzhiyun          * were the types of the cards missed. */
400*4882a593Smuzhiyun         char buffer[64];
401*4882a593Smuzhiyun         int fbNum, devId;
402*4882a593Smuzhiyun         static struct {
403*4882a593Smuzhiyun             int devId;
404*4882a593Smuzhiyun             char *prefix;
405*4882a593Smuzhiyun         } procFbPrefixes[] = {
406*4882a593Smuzhiyun             {SBUS_DEVICE_BW2, "BWtwo"},
407*4882a593Smuzhiyun             {SBUS_DEVICE_CG14, "CGfourteen"},
408*4882a593Smuzhiyun             {SBUS_DEVICE_CG6, "CGsix"},
409*4882a593Smuzhiyun             {SBUS_DEVICE_CG3, "CGthree"},
410*4882a593Smuzhiyun             {SBUS_DEVICE_FFB, "Creator"},
411*4882a593Smuzhiyun             {SBUS_DEVICE_FFB, "Elite 3D"},
412*4882a593Smuzhiyun             {SBUS_DEVICE_LEO, "Leo"},
413*4882a593Smuzhiyun             {SBUS_DEVICE_TCX, "TCX"},
414*4882a593Smuzhiyun             {0, NULL},
415*4882a593Smuzhiyun         };
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun         while (fscanf(f, "%d %63s\n", &fbNum, buffer) == 2) {
418*4882a593Smuzhiyun             for (i = 0; procFbPrefixes[i].devId; i++)
419*4882a593Smuzhiyun                 if (!strncmp(procFbPrefixes[i].prefix, buffer,
420*4882a593Smuzhiyun                              strlen(procFbPrefixes[i].prefix)))
421*4882a593Smuzhiyun                     break;
422*4882a593Smuzhiyun             devId = procFbPrefixes[i].devId;
423*4882a593Smuzhiyun             if (!devId)
424*4882a593Smuzhiyun                 continue;
425*4882a593Smuzhiyun             if (devicePtrs[fbNum]) {
426*4882a593Smuzhiyun                 if (devicePtrs[fbNum]->devId != devId)
427*4882a593Smuzhiyun                     xf86ErrorF("Inconsistent /proc/fb with FBIOGATTR\n");
428*4882a593Smuzhiyun             }
429*4882a593Smuzhiyun             else if (!devicePtrs[fbNum]) {
430*4882a593Smuzhiyun                 devicePtrs[fbNum] = psdp = xnfcalloc(sizeof(sbusDevice), 1);
431*4882a593Smuzhiyun                 psdp->devId = devId;
432*4882a593Smuzhiyun                 psdp->fbNum = fbNum;
433*4882a593Smuzhiyun                 psdp->fd = -2;
434*4882a593Smuzhiyun             }
435*4882a593Smuzhiyun         }
436*4882a593Smuzhiyun         fclose(f);
437*4882a593Smuzhiyun     }
438*4882a593Smuzhiyun     promGetSibling(0);
439*4882a593Smuzhiyun     promWalkAssignNodes(promRootNode, 0, PROM_NODE_PREF, devicePtrs);
440*4882a593Smuzhiyun     for (i = 0, j = 0; i < 32; i++)
441*4882a593Smuzhiyun         if (devicePtrs[i] && devicePtrs[i]->fbNum == -1)
442*4882a593Smuzhiyun             j++;
443*4882a593Smuzhiyun     xf86SbusInfo = xnfreallocarray(xf86SbusInfo, n + j + 1, sizeof(psdp));
444*4882a593Smuzhiyun     for (i = 0, psdpp = xf86SbusInfo; i < 32; i++)
445*4882a593Smuzhiyun         if (devicePtrs[i]) {
446*4882a593Smuzhiyun             if (devicePtrs[i]->fbNum == -1) {
447*4882a593Smuzhiyun                 memmove(psdpp + 1, psdpp, sizeof(psdpp) * (n + 1));
448*4882a593Smuzhiyun                 *psdpp = devicePtrs[i];
449*4882a593Smuzhiyun             }
450*4882a593Smuzhiyun             else
451*4882a593Smuzhiyun                 n--;
452*4882a593Smuzhiyun         }
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun static char *
promGetReg(int type)456*4882a593Smuzhiyun promGetReg(int type)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun     char *prop;
459*4882a593Smuzhiyun     int len;
460*4882a593Smuzhiyun     static char regstr[40];
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun     regstr[0] = 0;
463*4882a593Smuzhiyun     prop = promGetProperty("reg", &len);
464*4882a593Smuzhiyun     if (prop && len >= 4) {
465*4882a593Smuzhiyun         unsigned int *reg = (unsigned int *) prop;
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun         if (!promP1275 || (type == PROM_NODE_SBUS) || (type == PROM_NODE_EBUS))
468*4882a593Smuzhiyun             snprintf(regstr, sizeof(regstr), "@%x,%x", reg[0], reg[1]);
469*4882a593Smuzhiyun         else if (type == PROM_NODE_PCI) {
470*4882a593Smuzhiyun             if ((reg[0] >> 8) & 7)
471*4882a593Smuzhiyun                 snprintf(regstr, sizeof(regstr), "@%x,%x",
472*4882a593Smuzhiyun                          (reg[0] >> 11) & 0x1f, (reg[0] >> 8) & 7);
473*4882a593Smuzhiyun             else
474*4882a593Smuzhiyun                 snprintf(regstr, sizeof(regstr), "@%x", (reg[0] >> 11) & 0x1f);
475*4882a593Smuzhiyun         }
476*4882a593Smuzhiyun         else if (len == 4)
477*4882a593Smuzhiyun             snprintf(regstr, sizeof(regstr), "@%x", reg[0]);
478*4882a593Smuzhiyun         else {
479*4882a593Smuzhiyun             unsigned int regs[2];
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun             /* Things get more complicated on UPA. If upa-portid exists,
482*4882a593Smuzhiyun                then address is @upa-portid,second-int-in-reg, otherwise
483*4882a593Smuzhiyun                it is @first-int-in-reg/16,second-int-in-reg (well, probably
484*4882a593Smuzhiyun                upa-portid always exists, but just to be safe). */
485*4882a593Smuzhiyun             memcpy(regs, reg, sizeof(regs));
486*4882a593Smuzhiyun             prop = promGetProperty("upa-portid", &len);
487*4882a593Smuzhiyun             if (prop && len == 4) {
488*4882a593Smuzhiyun                 reg = (unsigned int *) prop;
489*4882a593Smuzhiyun                 snprintf(regstr, sizeof(regstr), "@%x,%x", reg[0], regs[1]);
490*4882a593Smuzhiyun             }
491*4882a593Smuzhiyun             else
492*4882a593Smuzhiyun                 snprintf(regstr, sizeof(regstr), "@%x,%x", regs[0] >> 4,
493*4882a593Smuzhiyun                          regs[1]);
494*4882a593Smuzhiyun         }
495*4882a593Smuzhiyun     }
496*4882a593Smuzhiyun     return regstr;
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun static int
promWalkNode2Pathname(char * path,int parent,int node,int searchNode,int type)500*4882a593Smuzhiyun promWalkNode2Pathname(char *path, int parent, int node, int searchNode,
501*4882a593Smuzhiyun                       int type)
502*4882a593Smuzhiyun {
503*4882a593Smuzhiyun     int nextnode;
504*4882a593Smuzhiyun     int len, ntype = type;
505*4882a593Smuzhiyun     char *prop, *p;
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun     prop = promGetProperty("name", &len);
508*4882a593Smuzhiyun     *path = '/';
509*4882a593Smuzhiyun     if (!prop || len <= 0)
510*4882a593Smuzhiyun         return 0;
511*4882a593Smuzhiyun     if ((!strcmp(prop, "sbus") || !strcmp(prop, "sbi")) && !type)
512*4882a593Smuzhiyun         ntype = PROM_NODE_SBUS;
513*4882a593Smuzhiyun     else if (!strcmp(prop, "ebus") && type == PROM_NODE_PCI)
514*4882a593Smuzhiyun         ntype = PROM_NODE_EBUS;
515*4882a593Smuzhiyun     else if (!strcmp(prop, "pci") && !type)
516*4882a593Smuzhiyun         ntype = PROM_NODE_PCI;
517*4882a593Smuzhiyun     strcpy(path + 1, prop);
518*4882a593Smuzhiyun     p = promGetReg(type);
519*4882a593Smuzhiyun     if (*p)
520*4882a593Smuzhiyun         strcat(path, p);
521*4882a593Smuzhiyun     if (node == searchNode)
522*4882a593Smuzhiyun         return 1;
523*4882a593Smuzhiyun     nextnode = promGetChild(node);
524*4882a593Smuzhiyun     if (nextnode &&
525*4882a593Smuzhiyun         promWalkNode2Pathname(strchr(path, 0), node, nextnode, searchNode,
526*4882a593Smuzhiyun                               ntype))
527*4882a593Smuzhiyun         return 1;
528*4882a593Smuzhiyun     nextnode = promGetSibling(node);
529*4882a593Smuzhiyun     if (nextnode &&
530*4882a593Smuzhiyun         promWalkNode2Pathname(path, parent, nextnode, searchNode, type))
531*4882a593Smuzhiyun         return 1;
532*4882a593Smuzhiyun     return 0;
533*4882a593Smuzhiyun }
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun char *
sparcPromNode2Pathname(sbusPromNodePtr pnode)536*4882a593Smuzhiyun sparcPromNode2Pathname(sbusPromNodePtr pnode)
537*4882a593Smuzhiyun {
538*4882a593Smuzhiyun     char *ret;
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun     if (!pnode->node)
541*4882a593Smuzhiyun         return NULL;
542*4882a593Smuzhiyun     ret = malloc(4096);
543*4882a593Smuzhiyun     if (!ret)
544*4882a593Smuzhiyun         return NULL;
545*4882a593Smuzhiyun     if (promWalkNode2Pathname
546*4882a593Smuzhiyun         (ret, promRootNode, promGetChild(promRootNode), pnode->node, 0))
547*4882a593Smuzhiyun         return ret;
548*4882a593Smuzhiyun     free(ret);
549*4882a593Smuzhiyun     return NULL;
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun static int
promWalkPathname2Node(char * name,char * regstr,int parent,int type)553*4882a593Smuzhiyun promWalkPathname2Node(char *name, char *regstr, int parent, int type)
554*4882a593Smuzhiyun {
555*4882a593Smuzhiyun     int len, node, ret;
556*4882a593Smuzhiyun     char *prop, *p;
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun     for (;;) {
559*4882a593Smuzhiyun         prop = promGetProperty("name", &len);
560*4882a593Smuzhiyun         if (!prop || len <= 0)
561*4882a593Smuzhiyun             return 0;
562*4882a593Smuzhiyun         if ((!strcmp(prop, "sbus") || !strcmp(prop, "sbi")) && !type)
563*4882a593Smuzhiyun             type = PROM_NODE_SBUS;
564*4882a593Smuzhiyun         else if (!strcmp(prop, "ebus") && type == PROM_NODE_PCI)
565*4882a593Smuzhiyun             type = PROM_NODE_EBUS;
566*4882a593Smuzhiyun         else if (!strcmp(prop, "pci") && !type)
567*4882a593Smuzhiyun             type = PROM_NODE_PCI;
568*4882a593Smuzhiyun         for (node = promGetChild(parent); node; node = promGetSibling(node)) {
569*4882a593Smuzhiyun             prop = promGetProperty("name", &len);
570*4882a593Smuzhiyun             if (!prop || len <= 0)
571*4882a593Smuzhiyun                 continue;
572*4882a593Smuzhiyun             if (*name && strcmp(name, prop))
573*4882a593Smuzhiyun                 continue;
574*4882a593Smuzhiyun             if (*regstr) {
575*4882a593Smuzhiyun                 p = promGetReg(type);
576*4882a593Smuzhiyun                 if (!*p || strcmp(p + 1, regstr))
577*4882a593Smuzhiyun                     continue;
578*4882a593Smuzhiyun             }
579*4882a593Smuzhiyun             break;
580*4882a593Smuzhiyun         }
581*4882a593Smuzhiyun         if (!node) {
582*4882a593Smuzhiyun             for (node = promGetChild(parent); node; node = promGetSibling(node)) {
583*4882a593Smuzhiyun                 ret = promWalkPathname2Node(name, regstr, node, type);
584*4882a593Smuzhiyun                 if (ret)
585*4882a593Smuzhiyun                     return ret;
586*4882a593Smuzhiyun             }
587*4882a593Smuzhiyun             return 0;
588*4882a593Smuzhiyun         }
589*4882a593Smuzhiyun         name = strchr(regstr, 0) + 1;
590*4882a593Smuzhiyun         if (!*name)
591*4882a593Smuzhiyun             return node;
592*4882a593Smuzhiyun         p = strchr(name, '/');
593*4882a593Smuzhiyun         if (p)
594*4882a593Smuzhiyun             *p = 0;
595*4882a593Smuzhiyun         else
596*4882a593Smuzhiyun             p = strchr(name, 0);
597*4882a593Smuzhiyun         regstr = strchr(name, '@');
598*4882a593Smuzhiyun         if (regstr)
599*4882a593Smuzhiyun             *regstr++ = 0;
600*4882a593Smuzhiyun         else
601*4882a593Smuzhiyun             regstr = p;
602*4882a593Smuzhiyun         if (name == regstr)
603*4882a593Smuzhiyun             return 0;
604*4882a593Smuzhiyun         parent = node;
605*4882a593Smuzhiyun     }
606*4882a593Smuzhiyun }
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun int
sparcPromPathname2Node(const char * pathName)609*4882a593Smuzhiyun sparcPromPathname2Node(const char *pathName)
610*4882a593Smuzhiyun {
611*4882a593Smuzhiyun     int i;
612*4882a593Smuzhiyun     char *name, *regstr, *p;
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun     i = strlen(pathName);
615*4882a593Smuzhiyun     name = malloc(i + 2);
616*4882a593Smuzhiyun     if (!name)
617*4882a593Smuzhiyun         return 0;
618*4882a593Smuzhiyun     strcpy(name, pathName);
619*4882a593Smuzhiyun     name[i + 1] = 0;
620*4882a593Smuzhiyun     if (name[0] != '/') {
621*4882a593Smuzhiyun         free(name);
622*4882a593Smuzhiyun         return 0;
623*4882a593Smuzhiyun     }
624*4882a593Smuzhiyun     p = strchr(name + 1, '/');
625*4882a593Smuzhiyun     if (p)
626*4882a593Smuzhiyun         *p = 0;
627*4882a593Smuzhiyun     else
628*4882a593Smuzhiyun         p = strchr(name, 0);
629*4882a593Smuzhiyun     regstr = strchr(name, '@');
630*4882a593Smuzhiyun     if (regstr)
631*4882a593Smuzhiyun         *regstr++ = 0;
632*4882a593Smuzhiyun     else
633*4882a593Smuzhiyun         regstr = p;
634*4882a593Smuzhiyun     if (name + 1 == regstr) {
635*4882a593Smuzhiyun         free(name);
636*4882a593Smuzhiyun         return 0;
637*4882a593Smuzhiyun     }
638*4882a593Smuzhiyun     promGetSibling(0);
639*4882a593Smuzhiyun     i = promWalkPathname2Node(name + 1, regstr, promRootNode, 0);
640*4882a593Smuzhiyun     free(name);
641*4882a593Smuzhiyun     return i;
642*4882a593Smuzhiyun }
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun void *
xf86MapSbusMem(sbusDevicePtr psdp,unsigned long offset,unsigned long size)645*4882a593Smuzhiyun xf86MapSbusMem(sbusDevicePtr psdp, unsigned long offset, unsigned long size)
646*4882a593Smuzhiyun {
647*4882a593Smuzhiyun     void *ret;
648*4882a593Smuzhiyun     unsigned long pagemask = getpagesize() - 1;
649*4882a593Smuzhiyun     unsigned long off = offset & ~pagemask;
650*4882a593Smuzhiyun     unsigned long len = ((offset + size + pagemask) & ~pagemask) - off;
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun     if (psdp->fd == -1) {
653*4882a593Smuzhiyun         psdp->fd = open(psdp->device, O_RDWR);
654*4882a593Smuzhiyun         if (psdp->fd == -1)
655*4882a593Smuzhiyun             return NULL;
656*4882a593Smuzhiyun     }
657*4882a593Smuzhiyun     else if (psdp->fd < 0)
658*4882a593Smuzhiyun         return NULL;
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun     ret = (void *) mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE,
661*4882a593Smuzhiyun                          psdp->fd, off);
662*4882a593Smuzhiyun     if (ret == (void *) -1) {
663*4882a593Smuzhiyun         ret = (void *) mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED,
664*4882a593Smuzhiyun                              psdp->fd, off);
665*4882a593Smuzhiyun     }
666*4882a593Smuzhiyun     if (ret == (void *) -1)
667*4882a593Smuzhiyun         return NULL;
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun     return (char *) ret + (offset - off);
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun void
xf86UnmapSbusMem(sbusDevicePtr psdp,void * addr,unsigned long size)673*4882a593Smuzhiyun xf86UnmapSbusMem(sbusDevicePtr psdp, void *addr, unsigned long size)
674*4882a593Smuzhiyun {
675*4882a593Smuzhiyun     unsigned long mask = getpagesize() - 1;
676*4882a593Smuzhiyun     unsigned long base = (unsigned long) addr & ~mask;
677*4882a593Smuzhiyun     unsigned long len = (((unsigned long) addr + size + mask) & ~mask) - base;
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun     munmap((void *) base, len);
680*4882a593Smuzhiyun }
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun /* Tell OS that we are driving the HW cursor ourselves. */
683*4882a593Smuzhiyun void
xf86SbusHideOsHwCursor(sbusDevicePtr psdp)684*4882a593Smuzhiyun xf86SbusHideOsHwCursor(sbusDevicePtr psdp)
685*4882a593Smuzhiyun {
686*4882a593Smuzhiyun     struct fbcursor fbcursor;
687*4882a593Smuzhiyun     unsigned char zeros[8];
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun     memset(&fbcursor, 0, sizeof(fbcursor));
690*4882a593Smuzhiyun     memset(&zeros, 0, sizeof(zeros));
691*4882a593Smuzhiyun     fbcursor.cmap.count = 2;
692*4882a593Smuzhiyun     fbcursor.cmap.red = zeros;
693*4882a593Smuzhiyun     fbcursor.cmap.green = zeros;
694*4882a593Smuzhiyun     fbcursor.cmap.blue = zeros;
695*4882a593Smuzhiyun     fbcursor.image = (char *) zeros;
696*4882a593Smuzhiyun     fbcursor.mask = (char *) zeros;
697*4882a593Smuzhiyun     fbcursor.size.x = 32;
698*4882a593Smuzhiyun     fbcursor.size.y = 1;
699*4882a593Smuzhiyun     fbcursor.set = FB_CUR_SETALL;
700*4882a593Smuzhiyun     ioctl(psdp->fd, FBIOSCURSOR, &fbcursor);
701*4882a593Smuzhiyun }
702*4882a593Smuzhiyun 
703*4882a593Smuzhiyun /* Set HW cursor colormap. */
704*4882a593Smuzhiyun void
xf86SbusSetOsHwCursorCmap(sbusDevicePtr psdp,int bg,int fg)705*4882a593Smuzhiyun xf86SbusSetOsHwCursorCmap(sbusDevicePtr psdp, int bg, int fg)
706*4882a593Smuzhiyun {
707*4882a593Smuzhiyun     struct fbcursor fbcursor;
708*4882a593Smuzhiyun     unsigned char red[2], green[2], blue[2];
709*4882a593Smuzhiyun 
710*4882a593Smuzhiyun     memset(&fbcursor, 0, sizeof(fbcursor));
711*4882a593Smuzhiyun     red[0] = bg >> 16;
712*4882a593Smuzhiyun     green[0] = bg >> 8;
713*4882a593Smuzhiyun     blue[0] = bg;
714*4882a593Smuzhiyun     red[1] = fg >> 16;
715*4882a593Smuzhiyun     green[1] = fg >> 8;
716*4882a593Smuzhiyun     blue[1] = fg;
717*4882a593Smuzhiyun     fbcursor.cmap.count = 2;
718*4882a593Smuzhiyun     fbcursor.cmap.red = red;
719*4882a593Smuzhiyun     fbcursor.cmap.green = green;
720*4882a593Smuzhiyun     fbcursor.cmap.blue = blue;
721*4882a593Smuzhiyun     fbcursor.set = FB_CUR_SETCMAP;
722*4882a593Smuzhiyun     ioctl(psdp->fd, FBIOSCURSOR, &fbcursor);
723*4882a593Smuzhiyun }
724