source: trunk/third/sysinfo/sunos-fb.c @ 12269

Revision 12269, 15.4 KB checked in by ghudson, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12268, which included commits to RCS files with non-trunk default branches.
Line 
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
10static 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 */
28extern 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 */
86static 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 */
218static 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 */
250static 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 */
298static 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 */
373extern 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}
Note: See TracBrowser for help on using the repository browser.