1 | /* |
---|
2 | * Copyright (c) 1992-1998 Michael A. Cooper. |
---|
3 | * This software may be freely used and distributed provided it is not |
---|
4 | * sold for profit or used in part or in whole for commercial gain |
---|
5 | * without prior written agreement, and the author is credited |
---|
6 | * appropriately. |
---|
7 | */ |
---|
8 | |
---|
9 | #ifndef lint |
---|
10 | static char *RCSid = "$Revision: 1.1.1.1 $"; |
---|
11 | #endif |
---|
12 | |
---|
13 | /* |
---|
14 | * SunOS FrameBuffer functions |
---|
15 | */ |
---|
16 | |
---|
17 | #include "defs.h" |
---|
18 | #include "sunos-obp.h" |
---|
19 | |
---|
20 | /* |
---|
21 | * Name of frame buffer "indirect" device. |
---|
22 | */ |
---|
23 | #define FBDEVICE "fb" |
---|
24 | |
---|
25 | /* |
---|
26 | * Find frame buffer device file for FBname. |
---|
27 | */ |
---|
28 | extern char *FBfindFile(ProbeData) |
---|
29 | ProbeData_t *ProbeData; |
---|
30 | { |
---|
31 | char *FBname; |
---|
32 | char *File; |
---|
33 | DevData_t *DevData; |
---|
34 | DevDefine_t *DevDefine; |
---|
35 | static char FileBuff[MAXPATHLEN]; |
---|
36 | |
---|
37 | if (!ProbeData) |
---|
38 | return((char *) NULL); |
---|
39 | FBname = ProbeData->DevName; |
---|
40 | DevData = ProbeData->DevData; |
---|
41 | DevDefine = ProbeData->DevDefine; |
---|
42 | |
---|
43 | #if OSMVER == 4 |
---|
44 | if ((File = GetCharFile(FBname, NULL)) && FileExists(File)) |
---|
45 | return(File); |
---|
46 | if (FileExists("/dev/fb")) |
---|
47 | return("/dev/fb"); |
---|
48 | #else /* OSMVER == 5 */ |
---|
49 | |
---|
50 | if (DevDefine && DevDefine->File) { |
---|
51 | (void) snprintf(FileBuff, sizeof(FileBuff), "%s/%s%d", |
---|
52 | _PATH_DEV_FBS, DevDefine->File, DevData->DevUnit); |
---|
53 | if (FileExists(FileBuff)) |
---|
54 | return(FileBuff); |
---|
55 | } |
---|
56 | |
---|
57 | (void) snprintf(FileBuff, sizeof(FileBuff), "%s/%s", |
---|
58 | _PATH_DEV_FBS, FBname); |
---|
59 | if (FileExists(FileBuff)) |
---|
60 | return(FileBuff); |
---|
61 | |
---|
62 | (void) snprintf(FileBuff, sizeof(FileBuff), "%s/%s", |
---|
63 | _PATH_DEV, FBname); |
---|
64 | if (FileExists(FileBuff)) |
---|
65 | return(FileBuff); |
---|
66 | |
---|
67 | (void) snprintf(FileBuff, sizeof(FileBuff), "%s/%s", |
---|
68 | _PATH_DEV_FBS, FBname); |
---|
69 | if (FileExists(FileBuff)) |
---|
70 | return(FileBuff); |
---|
71 | |
---|
72 | (void) snprintf(FileBuff, sizeof(FileBuff), "%s/%s", |
---|
73 | _PATH_DEV, FBDEVICE); |
---|
74 | if (FileExists(FileBuff)) |
---|
75 | return(FileBuff); |
---|
76 | #endif /* OSMVER == 5 */ |
---|
77 | |
---|
78 | SImsg(SIM_DBG, "Could not find device file for <%s>.", FBname); |
---|
79 | |
---|
80 | return((char *) NULL); |
---|
81 | } |
---|
82 | |
---|
83 | /* |
---|
84 | * Check for a monitor and create a device if found. |
---|
85 | */ |
---|
86 | static DevInfo_t *ProbeMonitor(ProbeData, MonFreq) |
---|
87 | ProbeData_t *ProbeData; |
---|
88 | int *MonFreq; |
---|
89 | { |
---|
90 | DevInfo_t *DevInfo = NULL; |
---|
91 | int GotMonInfo = FALSE; |
---|
92 | static int MonUnit; |
---|
93 | static char DevName[32]; |
---|
94 | Define_t *MonDef; |
---|
95 | char *MonIDstr; |
---|
96 | int MonID = -1; |
---|
97 | DevData_t *FBDevData; |
---|
98 | char *FBFile; |
---|
99 | int FBFileDesc; |
---|
100 | int GotEdid = 0; |
---|
101 | #if defined(HAVE_OPENPROM) |
---|
102 | static Query_t Query; |
---|
103 | OBPprop_t *EdidProp = NULL; |
---|
104 | #endif /* HAVE_OPENPROM */ |
---|
105 | #if defined(FBIOMONINFO) |
---|
106 | struct mon_info mon_info; |
---|
107 | #endif /* FBIOMONINFO */ |
---|
108 | |
---|
109 | FBDevData = ProbeData->DevData; |
---|
110 | FBFile = ProbeData->DevFile; |
---|
111 | FBFileDesc = ProbeData->FileDesc; |
---|
112 | |
---|
113 | |
---|
114 | #if defined(FBIOMONINFO) |
---|
115 | /* |
---|
116 | * Monitor info |
---|
117 | */ |
---|
118 | memset(&mon_info, 0, sizeof(mon_info)); |
---|
119 | if (ioctl(FBFileDesc, FBIOMONINFO, &mon_info) == 0) |
---|
120 | GotMonInfo = TRUE; |
---|
121 | else { |
---|
122 | SImsg(SIM_GERR, "%s: Get monitor info (FBIOMONINFO) failed: %s", |
---|
123 | FBFile, SYSERR); |
---|
124 | } |
---|
125 | #endif /* FBIOMONINFO */ |
---|
126 | |
---|
127 | #if defined(HAVE_OPENPROM) |
---|
128 | /* |
---|
129 | * Ask OBP for the monitor ID. |
---|
130 | */ |
---|
131 | if (MonIDstr = OBPfindPropVal("montype", NULL, FBDevData->NodeID, NULL)) |
---|
132 | MonID = atoi(MonIDstr); |
---|
133 | |
---|
134 | #if OSMVER == 5 |
---|
135 | /* |
---|
136 | * Look for EDID property data in the Frame Buffer Node entry |
---|
137 | */ |
---|
138 | if (EdidProp = OBPfindProp(OBP_EDID, NULL, FBDevData->NodeID, NULL)) |
---|
139 | GotEdid = TRUE; |
---|
140 | #endif /* OSMVER == 5 */ |
---|
141 | #endif /* HAVE_OPENPROM */ |
---|
142 | |
---|
143 | /* |
---|
144 | * Use FBIOMONINFO info if we got nothing from OBP |
---|
145 | */ |
---|
146 | if (GotMonInfo && MonID < 0) |
---|
147 | MonID = mon_info.mon_type; |
---|
148 | |
---|
149 | /* |
---|
150 | * If we have no data, then return now |
---|
151 | */ |
---|
152 | if (!GotMonInfo && !GotEdid && MonID < 0) |
---|
153 | return((DevInfo_t *) NULL); |
---|
154 | |
---|
155 | /* |
---|
156 | * Commit to making a device |
---|
157 | */ |
---|
158 | DevInfo = NewDevInfo(NULL); |
---|
159 | |
---|
160 | DevInfo->Unit = MonUnit++; |
---|
161 | (void) snprintf(DevName, sizeof(DevName), "monitor%d", DevInfo->Unit); |
---|
162 | DevInfo->Name = strdup(DevName); |
---|
163 | DevInfo->Type = DT_MONITOR; |
---|
164 | |
---|
165 | #if defined(HAVE_OPENPROM) |
---|
166 | /* |
---|
167 | * Decode and set EDID info |
---|
168 | */ |
---|
169 | if (EdidProp) { |
---|
170 | (void) memset(&Query, 0, sizeof(Query)); |
---|
171 | Query.DevInfo = DevInfo; |
---|
172 | Query.Data = EdidProp->Raw; |
---|
173 | Query.DataLen = EdidProp->RawLen; |
---|
174 | |
---|
175 | #if OSMVER == 5 |
---|
176 | EdidDecode(&Query); |
---|
177 | #endif /* OSMVER == 5 */ |
---|
178 | } |
---|
179 | #endif /* HAVE_OPENPROM */ |
---|
180 | |
---|
181 | if (MonID >= 0) { |
---|
182 | if (MonDef = DefGet("MonitorID", NULL, (long)MonID, 0)) |
---|
183 | DevInfo->Model = MonDef->ValStr2; |
---|
184 | AddDevDesc(DevInfo, itoa(MonID), "Type", DA_APPEND); |
---|
185 | } |
---|
186 | |
---|
187 | #if defined(FBIOMONINFO) |
---|
188 | if (GotMonInfo) { |
---|
189 | if (MonFreq) |
---|
190 | *MonFreq = mon_info.vfreq; |
---|
191 | AddDevDesc(DevInfo, FreqStr(mon_info.pixfreq), |
---|
192 | "Pixel Frequency", DA_APPEND); |
---|
193 | AddDevDesc(DevInfo, FreqStr(mon_info.hfreq), |
---|
194 | "Horizontal Frequency", DA_APPEND); |
---|
195 | AddDevDesc(DevInfo, FreqStr(mon_info.vfreq), |
---|
196 | "Vertical Frequency", DA_APPEND); |
---|
197 | AddDevDesc(DevInfo, itoa(mon_info.hsync), |
---|
198 | "Horizontal Sync (pixels)", DA_APPEND); |
---|
199 | AddDevDesc(DevInfo, itoa(mon_info.vsync), |
---|
200 | "Vertical Sync (scanlines)", DA_APPEND); |
---|
201 | AddDevDesc(DevInfo, itoa(mon_info.hfporch), |
---|
202 | "Horizontal Front Porch (pixels)", DA_APPEND); |
---|
203 | AddDevDesc(DevInfo, itoa(mon_info.hbporch), |
---|
204 | "Horizontal Back Porch (pixels)", DA_APPEND); |
---|
205 | AddDevDesc(DevInfo, itoa(mon_info.vfporch), |
---|
206 | "Vertical Front Porch (pixels)", DA_APPEND); |
---|
207 | AddDevDesc(DevInfo, itoa(mon_info.vbporch), |
---|
208 | "Vertical Back Porch (pixels)", DA_APPEND); |
---|
209 | } |
---|
210 | #endif /* FBIOMONINFO */ |
---|
211 | |
---|
212 | return(DevInfo); |
---|
213 | } |
---|
214 | |
---|
215 | /* |
---|
216 | * Set PGX (m64) specific information. |
---|
217 | */ |
---|
218 | static void FBsetPGX(ProbeData, ShortName, FBgattr) |
---|
219 | /*ARGSUSED*/ |
---|
220 | ProbeData_t *ProbeData; |
---|
221 | char *ShortName; |
---|
222 | struct fbgattr *FBgattr; |
---|
223 | { |
---|
224 | DevInfo_t *DevInfo; |
---|
225 | |
---|
226 | if (!ProbeData || !ProbeData->UseDevInfo || !FBgattr) |
---|
227 | return; |
---|
228 | |
---|
229 | DevInfo = ProbeData->UseDevInfo; |
---|
230 | |
---|
231 | /* |
---|
232 | * From the m64(7D) man page. |
---|
233 | */ |
---|
234 | AddDevDesc(DevInfo, GetSizeStr(FBgattr->sattr.dev_specific[0], BYTES), |
---|
235 | "Total Mappable Memory", DA_APPEND); |
---|
236 | |
---|
237 | AddDevDesc(DevInfo, itoax(FBgattr->sattr.dev_specific[2]), |
---|
238 | "Chip Revision", DA_APPEND); |
---|
239 | |
---|
240 | AddDevDesc(DevInfo, itoax(FBgattr->sattr.dev_specific[3]), |
---|
241 | "DAC Revision", DA_APPEND); |
---|
242 | |
---|
243 | AddDevDesc(DevInfo, itoax(FBgattr->sattr.dev_specific[4]), |
---|
244 | "PROM Revision", DA_APPEND); |
---|
245 | } |
---|
246 | |
---|
247 | /* |
---|
248 | * Set GX (cgsix) specific information. |
---|
249 | */ |
---|
250 | static void FBsetGX(ProbeData, ShortName, FBgattr) |
---|
251 | /*ARGSUSED*/ |
---|
252 | ProbeData_t *ProbeData; |
---|
253 | char *ShortName; |
---|
254 | struct fbgattr *FBgattr; |
---|
255 | { |
---|
256 | #if defined(FBIOGXINFO) |
---|
257 | struct cg6_info cg6_info; |
---|
258 | FrameBuffer_t *fb; |
---|
259 | DevInfo_t *DevInfo; |
---|
260 | |
---|
261 | if (!ProbeData || !ProbeData->Opaque) |
---|
262 | return; |
---|
263 | |
---|
264 | fb = (FrameBuffer_t *) ProbeData->Opaque; |
---|
265 | DevInfo = ProbeData->UseDevInfo; |
---|
266 | |
---|
267 | memset(&cg6_info, 0, sizeof(cg6_info)); |
---|
268 | if (ioctl(ProbeData->FileDesc, FBIOGXINFO, &cg6_info) != 0) { |
---|
269 | SImsg(SIM_GERR, "%s: FBIOGXINFO failed: %s.", |
---|
270 | ProbeData->DevFile, SYSERR); |
---|
271 | return; |
---|
272 | } |
---|
273 | |
---|
274 | AddDevDesc(DevInfo, itoa(cg6_info.slot), "Slot", DA_APPEND); |
---|
275 | AddDevDesc(DevInfo, itoa(cg6_info.boardrev), "Board Revision", DA_APPEND); |
---|
276 | |
---|
277 | /* |
---|
278 | * Board Revs 0-4 are Double width |
---|
279 | * Board Revs > 4 are Single width |
---|
280 | */ |
---|
281 | if (cg6_info.boardrev <= 4) |
---|
282 | AddDevDesc(DevInfo, NULL, "Double Width Card", DA_APPEND); |
---|
283 | else |
---|
284 | AddDevDesc(DevInfo, NULL, "Single Width Card", DA_APPEND); |
---|
285 | |
---|
286 | AddDevDesc(DevInfo, |
---|
287 | (cg6_info.hdb_capable) ? "Double Buffered" : |
---|
288 | "Single Buffered", "Buffering", DA_APPEND); |
---|
289 | |
---|
290 | if (cg6_info.vmsize) |
---|
291 | fb->VMSize = mbytes_to_bytes(cg6_info.vmsize); |
---|
292 | #endif /* FBIOGXINFO */ |
---|
293 | } |
---|
294 | |
---|
295 | /* |
---|
296 | * Set AFB/FFB specific information. |
---|
297 | */ |
---|
298 | static void FBsetXFB(ProbeData, ShortName, FBgattr) |
---|
299 | /*ARGSUSED*/ |
---|
300 | ProbeData_t *ProbeData; |
---|
301 | char *ShortName; |
---|
302 | struct fbgattr *FBgattr; |
---|
303 | { |
---|
304 | #if defined(HAVE_OPENPROM) |
---|
305 | DevDefine_t *DevDef = NULL; |
---|
306 | FrameBuffer_t *Fb = NULL; |
---|
307 | Define_t *Define; |
---|
308 | char *Name; |
---|
309 | char *BoardType; |
---|
310 | char DefBoardType[32]; |
---|
311 | int btype; |
---|
312 | |
---|
313 | if (!ProbeData || !ProbeData->DevDefine || !ProbeData->DevDefine->Name || |
---|
314 | !ProbeData->DevData || !ShortName) |
---|
315 | return; |
---|
316 | |
---|
317 | (void) snprintf(DefBoardType, sizeof(DefBoardType), "BoardType%s", |
---|
318 | ShortName); |
---|
319 | |
---|
320 | if (BoardType = OBPfindPropVal("board_type", NULL, |
---|
321 | ProbeData->DevData->NodeID, NULL)) { |
---|
322 | btype = atoi(BoardType); |
---|
323 | SImsg(SIM_DBG, "%s board_type=%s/%d/0x%x", |
---|
324 | DefBoardType, BoardType, btype, btype); |
---|
325 | |
---|
326 | Define = DefGet(DefBoardType, NULL, (long)btype, 0); |
---|
327 | if (!Define) |
---|
328 | SImsg(SIM_UNKN, "No %s entry in .cf file for 0x%x", |
---|
329 | DefBoardType, btype); |
---|
330 | if (Define) { |
---|
331 | /* |
---|
332 | * Add what we got |
---|
333 | */ |
---|
334 | ProbeData->UseDevInfo->Model = Define->ValStr1; |
---|
335 | if (ProbeData->Opaque) |
---|
336 | Fb = (FrameBuffer_t *) ProbeData->Opaque; |
---|
337 | else { |
---|
338 | Fb = NewFrameBuffer(NULL); |
---|
339 | ProbeData->Opaque = (void *) Fb; |
---|
340 | } |
---|
341 | if (Define->ValStr2) |
---|
342 | Fb->Depth = atoi(Define->ValStr2); |
---|
343 | if (Define->ValStr3) |
---|
344 | AddDevDesc(ProbeData->UseDevInfo, Define->ValStr3, |
---|
345 | "Board Orientation", DA_APPEND); |
---|
346 | } |
---|
347 | #if defined(FFB_Z_BUFFER) |
---|
348 | /* Do we have Z Buffering? */ |
---|
349 | if (FLAGS_ON(btype, FFB_Z_BUFFER)) |
---|
350 | AddDevDesc(ProbeData->UseDevInfo, NULL, "Z Buffering", DA_INSERT); |
---|
351 | #endif /* FFB_Z_BUFFER */ |
---|
352 | #if defined(FFB_DBL_BUFFER) |
---|
353 | /* |
---|
354 | * Special hardcoded code (sigh!) to determine if this is a Creator |
---|
355 | * or Creator3D FFB. Creator3D is double buffered, Creator is Single. |
---|
356 | * This overrides the OBP Model lookup because the Model info we have |
---|
357 | * does not appear to be consistant. |
---|
358 | */ |
---|
359 | else if (FLAGS_ON(btype, FFB_DBL_BUFFER)) { |
---|
360 | AddDevDesc(ProbeData->UseDevInfo, "Double buffered", "Buffering", |
---|
361 | DA_INSERT); |
---|
362 | if (DevDef = DevDefGet(FFB_DBLNAME, 0, 0)) |
---|
363 | ProbeData->DevDefine = DevDef; |
---|
364 | } |
---|
365 | #endif /* FFB_TYPE_DOUBLE */ |
---|
366 | } |
---|
367 | #endif /* HAVE_OPENPROM */ |
---|
368 | } |
---|
369 | |
---|
370 | /* |
---|
371 | * Probe a FrameBuffer. |
---|
372 | */ |
---|
373 | extern DevInfo_t *ProbeFrameBuffer(ProbeData) |
---|
374 | ProbeData_t *ProbeData; |
---|
375 | { |
---|
376 | char *FBname; |
---|
377 | char *TypeName = NULL; |
---|
378 | DevData_t *DevData; |
---|
379 | DevDefine_t *DevDefine; |
---|
380 | struct fbgattr fbgattrbuf; |
---|
381 | struct fbgattr *FBgattr = NULL; |
---|
382 | DevInfo_t *DevInfo; |
---|
383 | FrameBuffer_t *fb; |
---|
384 | DevDefine_t *FBdef = NULL; |
---|
385 | char *MonID = NULL; |
---|
386 | char *File; |
---|
387 | char *RealModel = NULL; |
---|
388 | char *cp; |
---|
389 | static char Buff[BUFSIZ]; |
---|
390 | int FileDesc; |
---|
391 | int IsKnown = 0; |
---|
392 | int MonFreq = 0; |
---|
393 | int MonHres = 0; |
---|
394 | int MonVres = 0; |
---|
395 | register int i; |
---|
396 | register int l; |
---|
397 | |
---|
398 | if (!ProbeData) |
---|
399 | return((DevInfo_t *) NULL); |
---|
400 | FBname = ProbeData->DevName; |
---|
401 | DevData = ProbeData->DevData; |
---|
402 | DevDefine = ProbeData->DevDefine; |
---|
403 | |
---|
404 | if (!FBname) |
---|
405 | return((DevInfo_t *) NULL); |
---|
406 | |
---|
407 | SImsg(SIM_DBG, "ProbeFrameBuffer(%s)", FBname); |
---|
408 | |
---|
409 | if (!(File = FBfindFile(ProbeData))) |
---|
410 | return((DevInfo_t *) NULL); |
---|
411 | |
---|
412 | if ((FileDesc = open(File, O_RDONLY)) < 0) { |
---|
413 | SImsg(SIM_GERR, "%s: Cannot open for reading: %s.", File, SYSERR); |
---|
414 | return((DevInfo_t *) NULL); |
---|
415 | } |
---|
416 | |
---|
417 | /* |
---|
418 | * Get real fb attributes |
---|
419 | */ |
---|
420 | if (ioctl(FileDesc, FBIOGATTR, &fbgattrbuf) == 0) |
---|
421 | FBgattr = &fbgattrbuf; |
---|
422 | else { |
---|
423 | SImsg(SIM_GERR, "%s: FBIOGATTR failed: %s.", File, SYSERR); |
---|
424 | /* |
---|
425 | * Try to at least get the FB type |
---|
426 | */ |
---|
427 | if (ioctl(FileDesc, FBIOGTYPE, &fbgattrbuf.fbtype) == 0) |
---|
428 | FBgattr = &fbgattrbuf; |
---|
429 | else |
---|
430 | SImsg(SIM_GERR, "%s: FBIOGTYPE failed: %s.", File, SYSERR); |
---|
431 | } |
---|
432 | |
---|
433 | /* |
---|
434 | * We're committed to try |
---|
435 | */ |
---|
436 | if (!(fb = NewFrameBuffer(NULL))) { |
---|
437 | SImsg(SIM_GERR, "Cannot create new frame buffer."); |
---|
438 | return((DevInfo_t *) NULL); |
---|
439 | } |
---|
440 | |
---|
441 | if (!(DevInfo = NewDevInfo(NULL))) { |
---|
442 | SImsg(SIM_GERR, "Cannot create new frame buffer device entry."); |
---|
443 | return((DevInfo_t *) NULL); |
---|
444 | } |
---|
445 | |
---|
446 | /* |
---|
447 | * Prepare data for probing |
---|
448 | */ |
---|
449 | ProbeData->Opaque = (void *) fb; |
---|
450 | ProbeData->DevFile = File; |
---|
451 | ProbeData->FileDesc = FileDesc; |
---|
452 | ProbeData->UseDevInfo = DevInfo; |
---|
453 | if (DevDefine) { |
---|
454 | if (TypeName = strchr(DevDefine->Name, ',')) |
---|
455 | ++TypeName; |
---|
456 | else |
---|
457 | TypeName = DevDefine->Name; |
---|
458 | } |
---|
459 | |
---|
460 | /* |
---|
461 | * Call FB specific functions. |
---|
462 | * Sometimes we always call a function and let it decide if it's |
---|
463 | * the right type of FB. |
---|
464 | */ |
---|
465 | FBsetGX(ProbeData, TypeName, FBgattr); |
---|
466 | if (EQ(TypeName, FFB_NAME) || EQ(TypeName, AFB_NAME)) |
---|
467 | FBsetXFB(ProbeData, TypeName, FBgattr); |
---|
468 | else if (EQ(TypeName, PGX_NAME)) |
---|
469 | FBsetPGX(ProbeData, TypeName, FBgattr); |
---|
470 | |
---|
471 | /* |
---|
472 | * Reset data obtained from FB specific functions. |
---|
473 | */ |
---|
474 | DevData = ProbeData->DevData; |
---|
475 | DevDefine = ProbeData->DevDefine; |
---|
476 | DevInfo = ProbeData->UseDevInfo; |
---|
477 | fb = (FrameBuffer_t *) ProbeData->Opaque; |
---|
478 | |
---|
479 | /* |
---|
480 | * See if there's a monitor attached. |
---|
481 | */ |
---|
482 | DevInfo->Slaves = ProbeMonitor(ProbeData, &MonFreq); |
---|
483 | |
---|
484 | /* |
---|
485 | * We're done doing ioctl()'s |
---|
486 | */ |
---|
487 | close(FileDesc); |
---|
488 | ProbeData->FileDesc = -1; |
---|
489 | |
---|
490 | /* |
---|
491 | * Find out what Model of fb this is. |
---|
492 | */ |
---|
493 | if (!DevInfo->Model) { |
---|
494 | if (DevDefine && (!FBgattr || |
---|
495 | FLAGS_ON(DevDefine->Flags, DDT_DEFINFO))) { |
---|
496 | DevInfo->Model = DevDefine->Model; |
---|
497 | } else if (FBgattr) { |
---|
498 | FBdef = DevDefGet(NULL, DT_FRAMEBUFFER, FBgattr->fbtype.fb_type); |
---|
499 | if (FBdef) { |
---|
500 | if (FBdef->Model) { |
---|
501 | (void) snprintf(Buff, sizeof(Buff), "%s", FBdef->Model); |
---|
502 | if (FBdef->Name) |
---|
503 | (void) snprintf(Buff + (l=strlen(FBdef->Model)), |
---|
504 | sizeof(Buff)-l, " [%s]", |
---|
505 | FBdef->Name); |
---|
506 | DevInfo->Model = strdup(Buff); |
---|
507 | } else |
---|
508 | DevInfo->Model = FBdef->Name; |
---|
509 | IsKnown = TRUE; |
---|
510 | } |
---|
511 | if (!IsKnown) { |
---|
512 | SImsg(SIM_UNKN, |
---|
513 | "Device `%s' is an unknown type (%d) of frame buffer.", |
---|
514 | FBname, FBgattr->fbtype.fb_type); |
---|
515 | DevInfo->Model = "UNKNOWN"; |
---|
516 | } |
---|
517 | } |
---|
518 | } |
---|
519 | |
---|
520 | #if defined(FB_ATTR_NEMUTYPES) |
---|
521 | if (FBgattr) { |
---|
522 | /* |
---|
523 | * See if this fb emulates other fb's. |
---|
524 | */ |
---|
525 | Buff[0] = CNULL; |
---|
526 | for (i = 0; i < FB_ATTR_NEMUTYPES && FBgattr->emu_types[i] >= 0; ++i) |
---|
527 | if (FBgattr->emu_types[i] != FBgattr->fbtype.fb_type && |
---|
528 | (FBdef = DevDefGet(NULL, DT_FRAMEBUFFER, |
---|
529 | (long)FBgattr->emu_types[i]))) { |
---|
530 | if (Buff[0]) |
---|
531 | (void) strcat(Buff, ", "); |
---|
532 | (void) strcat(Buff, |
---|
533 | (FBdef->Name) ? FBdef->Name : |
---|
534 | ((FBdef->Model) ? FBdef->Model : "")); |
---|
535 | } |
---|
536 | if (Buff[0]) |
---|
537 | AddDevDesc(DevInfo, Buff, "Emulates", DA_APPEND); |
---|
538 | } |
---|
539 | #endif /* FB_ATTR_NEMUTYPES */ |
---|
540 | |
---|
541 | /* |
---|
542 | * Put things together |
---|
543 | */ |
---|
544 | DevInfo->Name = FBname; |
---|
545 | DevInfo->Type = DT_FRAMEBUFFER; |
---|
546 | DevInfo->NodeID = DevData->NodeID; |
---|
547 | DevInfo->DevSpec = (void *) fb; |
---|
548 | |
---|
549 | if (FBgattr) { |
---|
550 | MonHres = fb->Height = FBgattr->fbtype.fb_height; |
---|
551 | MonVres = fb->Width = FBgattr->fbtype.fb_width; |
---|
552 | fb->Depth = FBgattr->fbtype.fb_depth; |
---|
553 | fb->Size = FBgattr->fbtype.fb_size; |
---|
554 | fb->CMSize = FBgattr->fbtype.fb_cmsize; |
---|
555 | } |
---|
556 | #if defined(HAVE_OPENPROM) |
---|
557 | else { |
---|
558 | if (cp = OBPfindPropVal("awidth", NULL, DevData->NodeID, NULL)) |
---|
559 | MonVres = atoi(cp); |
---|
560 | if (cp = OBPfindPropVal("height", NULL, DevData->NodeID, NULL)) |
---|
561 | MonHres = atoi(cp); |
---|
562 | } |
---|
563 | /* |
---|
564 | * Obtain the refresh frequency for the monitor from OBP. |
---|
565 | */ |
---|
566 | if ((cp = OBPfindPropVal("vfreq", NULL, DevData->NodeID, NULL)) || |
---|
567 | (cp = OBPfindPropVal("v_freq", NULL, DevData->NodeID, NULL))) |
---|
568 | MonFreq = atoi(cp); |
---|
569 | #endif /* HAVE_OPENPROM */ |
---|
570 | |
---|
571 | /* |
---|
572 | * Create a handy resolution entry. |
---|
573 | */ |
---|
574 | if (MonVres && MonHres) { |
---|
575 | (void) snprintf(Buff, sizeof(Buff), "%dx%d", MonVres, MonHres); |
---|
576 | if (MonFreq) |
---|
577 | (void) snprintf(&Buff[l=strlen(Buff)], |
---|
578 | sizeof(Buff)-l, "@%d", MonFreq); |
---|
579 | AddDevDesc(DevInfo, Buff, "Current Resolution", DA_INSERT); |
---|
580 | } |
---|
581 | |
---|
582 | DevInfo->Master = MkMasterFromDevData(DevData); |
---|
583 | |
---|
584 | return(ProbeData->RetDevInfo = DevInfo); |
---|
585 | } |
---|