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