source: trunk/third/sysinfo/os-irix.c @ 12269

Revision 12269, 64.5 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.3 $";
11#endif
12
13/*
14 * SGI IRIX specific functions
15 *
16 * Basic device information is derived via getinvent(3) and reverse engineering
17 * the IRIX hinv(1m) command which uses getinvent(3).  Many parts of the
18 * device code found here remains untested.  Some code is #ifdef disabled
19 * because I don't know how some #define's in some files (like sys/invent.h)
20 * coorespond to "code" names in other .h files.  This is especially true
21 * of the graphics code.
22 *
23 * Special Graphics information is derived from getinvent(3), and the
24 * "gfx_info" structure, various graphics device specific *.h files
25 * and reverse engineering the IRIX /usr/gfx/gfxinfo command.
26 */
27
28#include "defs.h"
29#include "myscsi.h"
30#include <invent.h>
31#include <mntent.h>
32#include <sys/systeminfo.h>
33#include <sys/conf.h>
34#include <sys/stat.h>
35#include <sys/syssgi.h>
36#include <sys/dsreq.h>
37
38/*
39 * Disk
40 */
41#include <sys/dkio.h>
42#include <sys/dvh.h>
43
44/*
45 * These are usually only defined if _KERNEL is defined
46 */
47#ifndef GR2_TYPE_GR2
48#define GR2_TYPE_GR2    0
49#endif
50#ifndef GR2_TYPE_HI1
51#define GR2_TYPE_HI1    1
52#endif
53
54/*
55 * Platform Specific Interfaces
56 */
57extern char                            *GetModelSGI();
58PSI_t GetModelPSI[] = {                 /* Get system Model */
59    { GetModelSGI },
60    { GetModelFile },
61    { GetModelDef },
62    { NULL },
63};
64extern char                            *GetSerialSGI();
65PSI_t GetSerialPSI[] = {                /* Get Serial Number */
66    { GetSerialSGI },
67    { NULL },
68};
69PSI_t GetRomVerPSI[] = {                /* Get ROM Version */
70    { NULL },
71};
72
73PSI_t GetKernArchPSI[] = {              /* Get Kernel Architecture */
74    { GetKernArchSysinfo },
75    { NULL },
76};
77
78PSI_t GetAppArchPSI[] = {               /* Get Application Architecture */
79    { GetAppArchSysinfo },
80    { NULL },
81};
82extern char                            *GetCpuTypeSGI();
83PSI_t GetCpuTypePSI[] = {               /* Get CPU Type */
84    { GetCpuTypeSGI },
85    { NULL },
86};
87extern char                            *GetNumCpuSGI();
88PSI_t GetNumCpuPSI[] = {                /* Get Number of CPU's */
89    { GetNumCpuSGI },
90    { NULL },
91};
92extern char                             *GetKernVerSGI();
93PSI_t GetKernVerPSI[] = {               /* Get Kernel Version */
94    { GetKernVerSGI },
95    { NULL },
96};
97PSI_t GetOSNamePSI[] = {                /* Get OS Name */
98    { GetOSNameUname },
99    { NULL },
100};
101PSI_t GetOSDistPSI[] = {                /* Get OS Dist */
102    { NULL },
103};
104extern char                            *GetOSVerSGI();
105PSI_t GetOSVerPSI[] = {                 /* Get OS Version */
106    { GetOSVerSGI },
107    { GetOSVerSysinfo },
108    { NULL },
109};
110PSI_t GetManShortPSI[] = {              /* Get Short Man Name */
111    { GetManShortSysinfo },
112    { GetManShortDef },
113    { NULL },
114};
115extern char                            *GetManLongSysinfoSGI();
116PSI_t GetManLongPSI[] = {               /* Get Long Man Name */
117    { GetManLongSysinfoSGI },
118    { GetManLongDef },
119    { NULL },
120};
121PSI_t GetMemoryPSI[] = {                /* Get amount of memory */
122    { GetMemoryPhysmemSym },
123    { NULL },
124};
125extern char                            *GetVirtMemSGI();
126PSI_t GetVirtMemPSI[] = {               /* Get amount of virtual memory */
127    { GetVirtMemSwapctl },
128    { GetVirtMemSGI },
129    { NULL },
130};
131PSI_t GetBootTimePSI[] = {              /* Get System Boot Time */
132    { GetBootTimeUtmp },
133    { NULL },
134};
135
136/*
137 * SGI Get Model
138 */
139extern char *GetModelSGI()
140{
141    inventory_t                *Inv;
142    register char              *cp;
143    char                       *CpuType = NULL;
144    char                       *CpuBoard = NULL;
145    char                       *Graphics = NULL;
146    char                       *Video = NULL;
147    Define_t                   *Def;
148    static char                 Query[256];
149
150    setinvent();
151
152    while (Inv = getinvent()) {
153        switch (Inv->inv_class) {
154        case INV_PROCESSOR:
155            if (Inv->inv_type == INV_CPUBOARD) {
156                Def = DefGet("cpuboard", NULL, Inv->inv_state, 0);
157                if (Def && Def->ValStr2)
158                    CpuBoard = Def->ValStr2;
159                else {
160                    /*
161                     * We couldn't find a definetion so we'll use the
162                     * numeric value in case that's in the config file.
163                     */
164                    SImsg(SIM_UNKN, "Unknown CPU Board Type (%d)",
165                                     Inv->inv_state);
166                    CpuBoard = strdup(itoa(Inv->inv_state));
167                }
168            }
169            break;
170        case INV_GRAPHICS:
171            Def = DefGet("GraphicsTypes", NULL, Inv->inv_type, 0);
172            if (Def && Def->ValStr2)
173                Graphics = Def->ValStr2;
174            break;
175        case INV_VIDEO:
176            Def = DefGet("VideoTypes", NULL, Inv->inv_type, 0);
177            if (Def && Def->ValStr2)
178                Video = Def->ValStr2;
179            break;
180        }
181    }
182
183    endinvent();
184
185    /*
186     * Ya gotta have a CpuBoard right?
187     */
188    if (!CpuBoard) {
189        SImsg(SIM_DBG, "GetModelSGI(): No CPU Board found.");
190        return((char *) NULL);
191    }
192
193    cp = GetCpuTypeSGI();
194    if (cp) {
195        CpuType = strdup(cp);
196        /*
197         * Turn "mips R4000 2.0" into "R4000".
198         */
199        if (cp = strchr(CpuType, ' '))
200            CpuType = cp + 1;
201        if (cp = strchr(CpuType, ' '))
202            *cp = CNULL;
203    }
204    if (!CpuType) {
205        SImsg(SIM_GERR, "GetModelSGI(): Cannot determine CPUType.");
206        return((char *) NULL);
207    }
208
209    /*
210     * Format query (CpuType,CpuBoard,Graphics,Video) and see if we
211     * can find a match.
212     */
213    (void) snprintf(Query, sizeof(Query),  "%s,%s,%s,%s",
214                    CpuType, CpuBoard,
215                    (Graphics) ? Graphics : "-",
216                    (Video) ? Video : "-");
217    SImsg(SIM_DBG, "GetModelSGI: Look for <%s>", Query);
218    Def = DefGet("SysModels", Query, -1, DO_REGEX);
219    if (Def && Def->ValStr1)
220        return(Def->ValStr1);
221
222    return ((char *) NULL);
223}
224
225/*
226 * Get serial number using the syssgi() system call.
227 */
228extern char *GetSerialSGI()
229{
230    static char                 Serial[MAXSYSIDSIZE];
231    register char              *cp;
232    int                         Okay;
233
234    if (Serial[0])
235        return(Serial);
236
237    if (syssgi(SGI_SYSID, Serial) == 0) {
238        /*
239         * Silly kludge to see if Serial contains valid information.
240         */
241        Okay = TRUE;
242        for (cp = Serial; cp && *cp; ++cp)
243            if (!isalnum(*cp)) {
244                Okay = FALSE;
245                break;
246            }
247        if (Okay)
248            return(Serial);
249    } else
250        SImsg(SIM_GERR, "syssgi(SGI_SYSID, ...) failed: %s", SYSERR);
251
252    return(GetSerialSysinfo());
253}
254
255/*
256 * SGI Get Kernel Version
257 */
258extern char *GetKernVerSGI()
259{
260    static char                 Buff[128];
261    char                        Version[256];
262    long                        Style = -1;
263 
264#if     defined(_SC_KERN_POINTERS)
265    Style = sysconf(_SC_KERN_POINTERS);
266#endif
267    sysinfo(SI_VERSION, Version, sizeof(Version));
268    /* IRIX Release 6.0 IP21 Version 08241804 System V - 64 Bit */
269    snprintf(Buff, sizeof(Buff),
270             "IRIX Release %s %s Version %s System V (%d bit)",
271             GetOSVer(), GetKernArch(),
272             Version, (Style == -1) ? 32 : Style);
273
274    return( (char *) Buff);
275}
276
277/*
278 * SGI Get OS Version number
279 */
280extern char *GetOSVerSGI()
281{
282    static char                 Build[256];
283    char                        Patch[50];      /* To hold patch version */
284    char                       *pos = Build;
285    char                        MinVer[50];
286    int                         Len;
287    static int                  done = 0;
288    static char                *RetVal;
289
290    if (done)                   /* Already did it */
291        return((char *) RetVal);
292
293    if (sysinfo(_MIPS_SI_OSREL_MAJ, Build, sizeof(Build)) < 0) {
294        (void) snprintf(Build, sizeof(Build), "%s", GetOSVerUname());
295        done = 1;
296        return ((RetVal = (char *) Build));
297    } else
298        pos += strlen(Build);
299
300    if (sysinfo(_MIPS_SI_OSREL_MIN, MinVer, sizeof(MinVer)) >= 0) {
301        if (MinVer[0] != '.')
302            *pos++ = '.';
303        Len = pos - &Build[0];
304        (void) snprintf(pos, sizeof(Build)-Len, "%s", MinVer);
305
306        /* Pre-load buffer with an initial '.', then stuff in version after */
307        if (sysinfo(_MIPS_SI_OSREL_PATCH, Patch+1, sizeof(Patch)) >= 0) {
308            Patch[0] = '.';     /* Pre-load string with a '.' delimiter */
309            if ( ! ((strlen(Patch) == 2) && (Patch[1] == '0')) ) {
310                Len = pos - Build;
311                (void) snprintf(pos, sizeof(Build)-Len, "%s", Patch);
312            }
313        }
314    }
315
316    done = 1;                   /* We're done! */
317
318    if (pos == Build)           /* If we didn't get anything, return NULL */
319        return((RetVal = (char *) NULL));
320    else
321        return((RetVal = (char *) Build));
322}
323
324/*
325 * Determine CPU type using sysinfo().
326 */
327extern char *GetCpuTypeSGI()
328{
329    static char                 Build[128];
330    char                       *pos = Build;
331    static int                  done = 0;
332    static char                *RetVal;
333    int                         Len = 0;
334
335    if (done)
336        return((char *) RetVal);
337
338    if (sysinfo(SI_ARCHITECTURE, Build, sizeof(Build)) >= 0) {
339        Len = strlen(Build);
340        pos += Len;
341        *(pos++) = ' ';
342    }
343    if (sysinfo(_MIPS_SI_PROCESSORS, pos, sizeof(Build) - Len + 2) >= 0)
344        if ( ( pos = strchr(Build,',')) != NULL)
345            *pos = CNULL;
346
347    done = 1;
348    if (pos == Build)
349        return((RetVal = (char *) NULL));
350    else
351        return((RetVal =(char *) Build));
352}
353
354/*
355 * Get Number of CPU's using sysinfo()
356 */
357extern char *GetNumCpuSGI()
358{
359    static char                 Buff[32];
360    static int                  done = 0;
361    static char                *RetVal;
362
363    if (done)
364        return ((char *) RetVal);
365    done = 1;
366
367    if (sysinfo(_MIPS_SI_NUM_PROCESSORS, Buff, sizeof(Buff)) < 0)
368        return((RetVal = (char *) NULL));
369    else
370        return((RetVal = Buff));
371}
372
373/*
374 * Get the long manufacterers name
375 */
376extern char *GetManLongSysinfoSGI()
377{
378    static char                 Buff[128];
379
380    if (sysinfo(_MIPS_SI_VENDOR, Buff, sizeof(Buff)) < 0)
381        return((char *) NULL);
382    else
383        return((char *) Buff);
384}
385
386/*
387 * Get size of virtual memory.
388 */
389extern char *GetVirtMemSGI()
390{
391    kvm_t                      *kd;
392    long                        AvailMem;
393    long                        UsedMem;
394    off_t                       Amount = 0;
395    nlist_t                    *nlPtr;
396
397    if (kd = KVMopen()) {
398        if ((nlPtr = KVMnlist(kd, "availsmem", (nlist_t *)NULL, 0)) == NULL)
399            return((char *) NULL);
400
401        if (CheckNlist(nlPtr))
402            return((char *) NULL);
403
404        if (KVMget(kd, nlPtr->n_value, (char *) &AvailMem,
405                   sizeof(AvailMem), KDT_DATA) >= 0)
406            Amount = AvailMem;
407
408        if ((nlPtr = KVMnlist(kd, "usermem", (nlist_t *)NULL, 0)) == NULL)
409            return((char *) NULL);
410
411        if (CheckNlist(nlPtr))
412            return((char *) NULL);
413
414        if (KVMget(kd, nlPtr->n_value, (char *) &UsedMem,
415                   sizeof(UsedMem), KDT_DATA) >= 0)
416            Amount += UsedMem;
417
418        Amount = Amount * (GETPAGESIZE() / KBYTES);
419        KVMclose(kd);
420    }
421
422    return(GetVirtMemStr(Amount));
423}
424
425/*
426 * Initialize the OS specific parts of the Device Types table
427 */
428void DevTypesInit()
429{
430}
431
432/*
433 * Issue a SCSI command and return the results.
434 * Uses the ds(7M) interface.
435 */
436extern int ScsiCmd(ScsiCmd)
437     ScsiCmd_t                 *ScsiCmd;
438{
439#if     defined(DS_ENTER)
440    static char                 Buff[SCSI_BUF_LEN];
441    static dsreq_t              Cmd;
442    ScsiCdbG0_t                *CdbPtr = NULL;
443
444    if (!ScsiCmd || !ScsiCmd->Cdb || !ScsiCmd->CdbLen ||
445        ScsiCmd->DevFD < 0 || !ScsiCmd->DevFile) {
446        SImsg(SIM_DBG, "ScsiCmd: Bad parameters.");
447        return(-1);
448    }
449
450    (void) memset(Buff, 0, sizeof(Buff));
451    (void) memset(&Cmd, 0, sizeof(Cmd));
452
453    Cmd.ds_cmdbuf = (caddr_t) ScsiCmd->Cdb;
454    Cmd.ds_cmdlen = ScsiCmd->CdbLen;
455    Cmd.ds_databuf = (caddr_t) Buff;
456    Cmd.ds_datalen = sizeof(Buff);
457    Cmd.ds_time = MySCSI_CMD_TIMEOUT * 1000;    /* ds_time==milliseconds */
458    Cmd.ds_flags = DSRQ_READ;
459
460    /*
461     * We just need Cdb.cmd so it's ok to assume ScsiCdbG0_t here
462     */
463    CdbPtr = (ScsiCdbG0_t *) ScsiCmd->Cdb;
464
465    /*
466     * Send cmd to device
467     */
468    if (ioctl(ScsiCmd->DevFD,  DS_ENTER, &Cmd) == -1) {
469        SImsg(SIM_GERR, "%s: ioctl DS_ENTER for SCSI 0x%x failed: %s",
470              ScsiCmd->DevFile, CdbPtr->cmd, SYSERR);
471        return(-1);
472    }
473
474    if (Cmd.ds_status != 0) {
475        SImsg(SIM_GERR, "%s: SCSI command 0x%x failed with ds_status=%d",
476              ScsiCmd->DevFile, CdbPtr->cmd, Cmd.ds_status);
477        return(-1);
478    }
479
480    ScsiCmd->Data = (void *) Buff;
481#endif  /* DS_ENTER */
482    return(0);
483}
484
485/*
486 * Clean a string of unprintable characters and excess white-space.
487 */
488static char *CleanStr(String, StrSize)
489    char                       *String;
490    int                         StrSize;
491{
492    register int                i, n;
493    char                       *NewString;
494
495    NewString = (char *) xcalloc(1, StrSize + 1);
496
497    for (i = 0, n = 0; i < StrSize; ++i) {
498        if (i == 0)
499            /* Skip initial white space */
500            while (isspace(String[i]))
501                ++i;
502        /* Skip extra white space */
503        if (i > 0 && isspace(String[i-1]) && isspace(String[i]))
504            continue;
505        if (isprint(String[i]))
506            NewString[n++] = String[i];
507    }
508
509    /* Remove trailing white space */
510    while (isspace(NewString[n]))
511        NewString[n--] = CNULL;
512
513    return(NewString);
514}
515
516/*
517 * Check to see if MntDevice is one of the "special" ones
518 * that IRIX uses.
519 */
520static int IsSpecialUse(MntDevice, DevName)
521    char                       *MntDevice;
522    char                       *DevName;
523{
524    static char                 DevFile[256];
525    static struct stat          MntStat;
526    static struct stat          DevStat;
527
528    if (!EQ(MntDevice, "/dev/root") &&
529        !EQ(MntDevice, "/dev/usr") &&
530        !EQ(MntDevice, "/dev/swap"))
531        return(0);
532
533    (void) snprintf(DevFile, sizeof(DevFile), "%s/%s", _PATH_DEV_DSK, DevName);
534    if (stat(MntDevice, &MntStat) != 0) {
535        SImsg(SIM_GERR, "stat failed: %s: %s", MntDevice, SYSERR);
536        return(0);
537    }
538    if (stat(DevFile, &DevStat) != 0) {
539        SImsg(SIM_GERR, "stat failed: %s: %s", DevFile, SYSERR);
540        return(0);
541    }
542
543    if (MntStat.st_rdev == DevStat.st_rdev)
544        return(1);
545    else
546        return(0);
547}
548
549/*
550 * Look for a partition named DevName in the mount table.
551 */
552static char *_GetMountInfo(FilePtr, DevName)
553    FILE                       *FilePtr;
554    char                       *DevName;
555{
556    struct mntent              *MntEnt;
557    register char              *cp;
558
559    while (MntEnt = getmntent(FilePtr)) {
560        if (cp = strrchr(MntEnt->mnt_fsname, '/'))
561            ++cp;
562        else
563            cp = MntEnt->mnt_fsname;
564        if (EQ(cp, DevName) || IsSpecialUse(MntEnt->mnt_fsname, DevName)) {
565            if (EQ(MntEnt->mnt_type, MNTTYPE_SWAP))
566                return(MNTTYPE_SWAP);
567            else
568                return(MntEnt->mnt_dir);
569        }
570    }
571
572    return((char *) NULL);
573}
574
575/*
576 * Lookup the usage for a given partition.
577 */
578static char *LookupPartUse(DevName, PartName)
579    char                       *DevName;
580    char                       *PartName;
581{
582    static FILE                *mntFilePtr = NULL;
583    static FILE                *fstabFilePtr = NULL;
584    static char                 Name[256];
585    char                       *Use = NULL;
586    register char              *cp;
587
588    if (!DevName || !PartName)
589        return((char *) NULL);
590
591    (void) snprintf(Name, sizeof(Name), "%s%s", DevName, PartName);
592
593    /*
594     * First try the current mount table
595     */
596    if (!mntFilePtr) {
597        if ((mntFilePtr = setmntent(MOUNTED, "r")) == NULL) {
598            SImsg(SIM_GERR, "%s: Cannot open for reading: %s.", MNTTAB, SYSERR);
599            return(NULL);
600        }
601    } else
602        rewind(mntFilePtr);
603
604    if (Use = _GetMountInfo(mntFilePtr, Name))
605        return(Use);
606
607    /*
608     * Now try the static mount table (/etc/fstab),
609     * which may not reflect current reality.
610     */
611    if (!fstabFilePtr) {
612        if ((fstabFilePtr = setmntent(MNTTAB, "r")) == NULL) {
613            SImsg(SIM_GERR, "%s: Cannot open for reading: %s.", MNTTAB, SYSERR);
614            return(NULL);
615        }
616    } else
617        rewind(fstabFilePtr);
618
619    if (Use = _GetMountInfo(fstabFilePtr, Name))
620        return(Use);
621
622    return((char *) NULL);
623}
624
625/*
626 * Find out what a partition is being used for.
627 */
628static void GetPartUse(DiskName, Part, PartType, DiskPart)
629    char                       *DiskName;
630    char                       *Part;
631    int                         PartType;
632    DiskPart_t                 *DiskPart;
633{
634    char                        Type[128];
635    char                        Usage[128];
636    char                       *Use;
637
638    Type[0] = Usage[0] = CNULL;
639
640    switch (PartType) {
641#if     defined(PTYPE_VOLHDR)
642    case PTYPE_VOLHDR: 
643        strcpy(Type, "volhdr");         strcpy(Usage, "Volume Header");
644        break;
645#endif
646#if     defined(PTYPE_TRKREPL)
647    case PTYPE_TRKREPL:
648        strcpy(Type, "trkrepl");        strcpy(Usage, "Track Replacement");
649        break;
650#endif
651#if     defined(PTYPE_SECREPL)
652    case PTYPE_SECREPL:
653        strcpy(Type, "secrepl");        strcpy(Usage, "Sector Replacement");
654        break;
655#endif
656#if     defined(PTYPE_LVOL)
657    case PTYPE_LVOL:   
658        strcpy(Type, "lvol");           strcpy(Usage, "Logical Volume");
659        break;
660#endif
661#if     defined(PTYPE_RLVOL)
662    case PTYPE_RLVOL:
663        strcpy(Type, "rlvol");          strcpy(Usage, "Raw Logical Volume");
664        break;
665#endif
666#if     defined(PTYPE_VOLUME)
667    case PTYPE_VOLUME: 
668        strcpy(Type, "volume");         strcpy(Usage, "Entire Volume");
669        break;
670#endif
671#if     defined(PTYPE_XLV)
672    case PTYPE_XLV:
673        strcpy(Type, "xlv");            strcpy(Usage, "XLV Volume");
674        break;
675#endif
676#if     defined(PTYPE_XFSLOG)
677    case PTYPE_XFSLOG:
678        strcpy(Type, "xfslog");         strcpy(Usage, "XFS Log");
679        break;
680#endif
681
682        /*
683         * These types of partitions should be looked up
684         */
685#if     defined(PTYPE_RAW)
686    case PTYPE_RAW:     strcpy(Type, "raw");                    break;
687#endif
688#if     defined(PTYPE_EFS)
689    case PTYPE_EFS:     strcpy(Type, "efs");                    break;
690#endif
691#if     defined(PTYPE_SYSV)
692    case PTYPE_SYSV:    strcpy(Type, "sysv");                   break;
693#endif
694#if     defined(PTYPE_BSD)
695    case PTYPE_BSD:     strcpy(Type, "bsd");                    break;
696#endif
697#if     defined(PTYPE_XFS)
698    case PTYPE_XFS:     strcpy(Type, "xfs");                    break;
699#endif
700
701    default:            strcpy(Type, "UNKNOWN");                break;
702    }
703
704    if (Type[0])
705        DiskPart->Type = strdup(Type);
706
707    if (Usage[0])
708        DiskPart->Usage = strdup(Usage);
709    else if (Use = LookupPartUse(DiskName, Part))
710        DiskPart->Usage = strdup(Use);
711}
712
713/*
714 * Get Disk Partition information for a given disk
715 */
716static DiskPart_t *GetDiskPart(DevInfo, VolHdr)
717    DevInfo_t                  *DevInfo;
718    struct volume_header       *VolHdr;
719{
720    DiskPart_t                 *DiskPart;
721    DiskPart_t                 *Base = NULL;
722    static char                 PName[4];
723    register DiskPart_t        *Ptr;
724    register int                i;
725
726    for (i = 0; i < NPARTAB; ++i) {
727        if (VolHdr->vh_pt[i].pt_nblks == 0)
728            continue;
729        DiskPart = (DiskPart_t *) xcalloc(1, sizeof(DiskPart_t));
730        (void) snprintf(PName, sizeof(PName),  "s%d", i);
731        DiskPart->Name = strdup(PName);
732        DiskPart->StartSect = (Large_t) VolHdr->vh_pt[i].pt_firstlbn;
733        DiskPart->NumSect = (Large_t) VolHdr->vh_pt[i].pt_nblks;
734        /* Store pt_type for possible later use in finding drive capacity */
735        DiskPart->NumType = VolHdr->vh_pt[i].pt_type;
736        GetPartUse(DevInfo->Name, PName,
737                   VolHdr->vh_pt[i].pt_type, DiskPart);
738
739        if (Base) {
740            for (Ptr = Base; Ptr && Ptr->Next; Ptr = Ptr->Next);
741            Ptr->Next = DiskPart;
742        } else
743            Base = DiskPart;
744    }
745
746    return(Base);
747}
748
749/*
750 * Get total disk size (capacity) in bytes.
751 * Look for the PTYPE_VOLUME (entire disk) partiton and use its
752 * size as return value.
753 */
754float IRIXGetDiskSize(DiskDrive)
755    DiskDrive_t                *DiskDrive;
756{
757    DiskPart_t                 *dp;
758
759#if     defined(PTYPE_VOLUME)
760    for (dp = DiskDrive->DiskPart; dp; dp = dp->Next) {
761        if (dp->NumType == PTYPE_VOLUME) {
762            SImsg(SIM_DBG, "DISK PTYPE_VOLUME numsects=%.0f size=%.0f",
763                  (float) dp->NumSect, (float) DiskDrive->SecSize);
764            return((float) ((float)dp->NumSect * (float)DiskDrive->SecSize));
765        }
766    }
767#else
768    SImsg(SIM_DBG, "PTYPE_VOLUME is not defined on this OS");
769#endif  /* PTYPE_VOLUME */
770
771    return((float) 0);
772}
773
774/*
775 * Find the Disk Device.
776 * Stores device name in DevNamePtr and File name in DevFilePtr.
777 * Returns 0 on success.
778 */
779static int FindDiskDev(CtlrDev, Inv, DevName, DevNameSize,
780                       DevFile, DevFileSize)
781     DevInfo_t                 *CtlrDev;
782     inventory_t               *Inv;
783     char                      *DevName;
784     size_t                     DevNameSize;
785     char                      *DevFile;
786     size_t                     DevFileSize;
787{
788    register int                i;
789
790    /*
791     * INV_SCSIFLOPPY is for various types of floppy devices
792     */
793    if (Inv->inv_type == INV_SCSIFLOPPY) {
794        (void) snprintf(DevName, DevNameSize, "fds%dd%d",
795                        Inv->inv_controller, Inv->inv_unit);
796        (void) snprintf(DevFile, DevFileSize, "%s/%svh",
797                        _PATH_DEV_RDSK, DevName);
798        return(0);
799    }
800
801    /*
802     * Normal disk drive name?
803     */
804    (void) snprintf(DevName, DevNameSize, "%sd%d",
805                    CtlrDev->Name, Inv->inv_unit);
806    (void) snprintf(DevFile, DevFileSize, "%s/%svh",
807                    _PATH_DEV_RDSK, DevName);
808    if (FileExists(DevFile))
809        return(0);
810
811    /*
812     * Check for Logical Unit Number (LUN) devices.
813     * i.e. dksXdXlX
814     */
815    for (i = 0; i < SI_MAX_LUN; ++i) {
816        (void) snprintf(DevName, DevNameSize, "%sd%dl%d",
817                        CtlrDev->Name, Inv->inv_unit, i);
818        (void) snprintf(DevFile, DevFileSize, "%s/%svh",
819                        _PATH_DEV_RDSK, DevName);
820        if (FileExists(DevFile))
821            return(0);
822    }
823
824    return(1);
825}
826
827/*
828 * Query disk using SCSI methods
829 */
830static int ProbeDiskDriveScsi(DevInfo, DevFile)
831     DevInfo_t                 *DevInfo;
832     char                      *DevFile;
833{
834    int                         fd;
835
836    fd = open(DevFile, O_RDONLY|O_NDELAY|O_NONBLOCK);
837    if (fd < 0) {
838        SImsg(SIM_GERR, "open failed: %s: %s", DevFile, SYSERR);
839        return(-1);
840    }
841
842    (void) ScsiQuery(DevInfo, DevFile, fd, TRUE);
843
844    (void) close(fd);
845
846    return(0);
847}
848
849/*
850 * Query disk using normal OS methods
851 */
852static int ProbeDiskDriveQuery(DevInfo, DevFile)
853     DevInfo_t                 *DevInfo;
854     char                      *DevFile;
855{
856    DiskDriveData_t            *DiskDriveData = NULL;
857    DiskDrive_t                *OSdisk = NULL;
858    DiskDrive_t                *HWdisk = NULL;
859    char                       *Vendor = NULL;
860    char                       *Model = NULL;
861    u_int                       DiskCap = 0;
862    static struct volume_header VolHdr;
863    static char                 DriveType[SCSI_DEVICE_NAME_SIZE + 1];
864    int                         fd;
865
866    fd = open(DevFile, O_RDONLY);
867    if (fd < 0) {
868        SImsg(SIM_GERR, "open failed: %s: %s", DevFile, SYSERR);
869        return(-1);
870    }
871
872    if (!DevInfo->Model || !DevInfo->Vendor) {
873        /*
874         * Get the Drive Type
875         */
876        if (ioctl(fd, DIOCDRIVETYPE, DriveType) < 0)
877            SImsg(SIM_GERR, "ioctl DIOCDRIVETYPE failed: %s: %s",
878                  DevFile,SYSERR);
879        else {
880            if (Vendor = strchr(DriveType, ' ')) {
881                *Vendor = CNULL;
882                ++Vendor;
883            } else
884                Vendor = DriveType;
885            if (!DevInfo->Vendor)
886                DevInfo->Vendor = strdup(Vendor);
887            if (!DevInfo->Model)
888                DevInfo->Model = strdup(DriveType);
889        }
890    }
891
892    DiskDriveData = (DiskDriveData_t *) DevInfo->DevSpec;
893    OSdisk = DiskDriveData->OSdata;
894    HWdisk = DiskDriveData->HWdata;
895
896    /*
897     * Get the volume header data.
898     */
899    if (ioctl(fd, DIOCGETVH, &VolHdr) < 0) {
900        SImsg(SIM_GERR, "ioctl DIOCGETVH failed: %s: %s", DevFile, SYSERR);
901    } else {
902        OSdisk->DiskPart = GetDiskPart(DevInfo, &VolHdr);
903        OSdisk->SecSize = VolHdr.vh_dp.dp_secbytes;
904#if     OSVER <= 63
905        /*
906         * This stuff was removed starting with IRIX 6.4
907         */
908        OSdisk->DataCyl = VolHdr.vh_dp.dp_cyls;
909        OSdisk->Tracks = VolHdr.vh_dp.dp_trks0;
910        OSdisk->Sect = VolHdr.vh_dp.dp_secs;
911        OSdisk->IntrLv = VolHdr.vh_dp.dp_interleave;
912        OSdisk->APC = VolHdr.vh_dp.dp_spares_cyl;
913#endif  /* OSVER <= 63 */
914        if (isprint(VolHdr.vh_bootfile[0]))
915            AddDevDesc(DevInfo, VolHdr.vh_bootfile, "Boot File", 0);
916    }
917
918#if     defined(DIOCREADCAPACITY)
919    /*
920     * Get the Disk Capacity
921     */
922    if (ioctl(fd, DIOCREADCAPACITY, &DiskCap) < 0)
923        SImsg(SIM_GERR, "ioctl DIOCREADCAPACITY failed: %s: %s",
924              DevFile, SYSERR);
925    else {
926        SImsg(SIM_DBG, "DISK: %s DIOCREADCAPACITY = %d", DevFile, DiskCap);
927        /*
928         * If we still don't have the disk capacity, try getting it
929         * from the partition table.
930         */
931        DiskCap = (u_int) IRIXGetDiskSize(OSdisk);
932        if (!HWdisk->Size && DiskCap && OSdisk->SecSize) {
933            HWdisk->Size = (float) nsect_to_mbytes(DiskCap, OSdisk->SecSize);
934            SImsg(SIM_DBG, "DISK: %s: size=%.0f MB",
935                  DevInfo->Name, OSdisk->Size);
936        }
937    }
938#endif  /* DIOCREADCAPACITY */
939
940    (void) close(fd);
941
942    return(0);
943}
944
945/*
946 * Probe a Disk Drive
947 */
948extern DevInfo_t *ProbeDiskDrive(Inv, TreePtr)
949    inventory_t                *Inv;
950    DevInfo_t                  *TreePtr;
951{
952    static char                 DevName[50];
953    static char                 DevFile[sizeof(DevName) +
954                                       sizeof(_PATH_DEV_RDSK) + 4];
955    static DevFind_t            Find;
956    DiskDriveData_t            *DiskDriveData = NULL;
957    DiskDrive_t                *OSdisk = NULL;
958    DiskDrive_t                *HWdisk = NULL;
959    DevInfo_t                  *DevInfo = NULL;
960    DevInfo_t                  *CtlrDev;
961    DevType_t                  *DevType = NULL;
962    ClassType_t                *ClassType = NULL;
963    Define_t                   *Def;
964
965    if (!Inv)
966        return((DevInfo_t *) NULL);
967
968    DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
969    DevInfo->Type = DT_DISKDRIVE;
970
971    /*
972     * Find the disk controller for this disk so that we
973     * can figure out the correct disk device name.
974     */
975    (void) memset(&Find, 0, sizeof(Find));
976    Find.Tree = TreePtr;
977    Find.DevType = DT_CONTROLLER;
978    Find.ClassType = -1;
979    Find.Unit = Inv->inv_controller;
980    CtlrDev = DevFind(&Find);
981    if (!CtlrDev) {
982        SImsg(SIM_DBG,
983              "No disk controller found for type %d ctlr %d unit %d",
984              Inv->inv_type, Inv->inv_controller, Inv->inv_unit);
985        (void) snprintf(DevName, sizeof(DevName), "c%dd%d",
986                        Inv->inv_controller, Inv->inv_unit);
987        DevInfo->Name = strdup(DevName);
988        return(DevInfo);
989    }
990
991    /*
992     * Setup DiskDrive data
993     */
994    if (DevInfo->DevSpec)
995        DiskDriveData = (DiskDriveData_t *) DevInfo->DevSpec;
996    else {
997        DiskDriveData = NewDiskDriveData(NULL);
998        DevInfo->DevSpec = (void *) DiskDriveData;
999    }
1000    if (DiskDriveData->OSdata)
1001        OSdisk = DiskDriveData->OSdata;
1002    else
1003        DiskDriveData->OSdata = OSdisk = NewDiskDrive(NULL);
1004    if (DiskDriveData->HWdata)
1005        HWdisk = DiskDriveData->HWdata;
1006    else
1007        DiskDriveData->HWdata = HWdisk = NewDiskDrive(NULL);
1008
1009    /*
1010     * Put it all together
1011     */
1012    DevInfo->Master = CtlrDev;
1013    DevInfo->Name = DevName;
1014    OSdisk->Unit = Inv->inv_unit;
1015
1016    /*
1017     * Perform SCSI query of drive
1018     */
1019    (void) snprintf(DevFile, sizeof(DevFile), "%s/sc%dd%dl0",
1020                    _PATH_DEV_SCSI, Inv->inv_controller, Inv->inv_unit);
1021    ProbeDiskDriveScsi(DevInfo, DevFile);
1022
1023    /*
1024     * If we know this to be a Floppy, set it here, AFTER the SCSI
1025     * query has been done to override that.
1026     */
1027    if (Inv->inv_type == INV_SCSIFLOPPY)
1028        DevInfo->Type = DT_FLOPPY;
1029
1030    /*
1031     * Find name of disk device (DevName) and device file (DevFile)
1032     */
1033    if (FindDiskDev(CtlrDev, Inv, DevName, sizeof(DevName),
1034                    DevFile, sizeof(DevFile)) != 0) {
1035        SImsg(SIM_GERR,
1036              "Cannot find disk device file for type %d ctlr %d unit %d",
1037              Inv->inv_type, Inv->inv_controller, Inv->inv_unit);
1038        return((DevInfo_t *) NULL);
1039    }
1040    DevAddFile(DevInfo, strdup(DevFile));
1041    /*
1042     * Do OS Query's
1043     */
1044    ProbeDiskDriveQuery(DevInfo, DevFile);
1045
1046    /*
1047     * See if there's a generic name in the .cf files
1048     */
1049    Def = DefGet("DiskTypes", NULL, Inv->inv_type, 0);
1050    if (Def->ValStr2)
1051        if (DevType = TypeGetByName(Def->ValStr2))
1052            DevInfo->Type = DevType->Type;
1053    if (Def->ValStr3)
1054        if (ClassType = ClassTypeGetByName(DevInfo->Type, Def->ValStr3))
1055            DevInfo->ClassType = ClassType->Type;
1056
1057    if (!DevInfo->Model && Def && Def->ValStr1)
1058        DevInfo->Model = Def->ValStr1;
1059
1060    return(DevInfo);
1061}
1062
1063/*
1064 * Get Disk info from Inventory
1065 */
1066static DevInfo_t *InvGetDisk(Inv, TreePtr)
1067    inventory_t                *Inv;
1068    DevInfo_t                  *TreePtr;
1069{
1070    DevInfo_t                  *DevInfo;
1071    static char                 Buff[128];
1072    char                       *DiskName = NULL;
1073    char                        CtlrModel[128];
1074    char                        CtlrName[20];
1075    int                         ClassType = -1;
1076    Define_t                   *Def;
1077    static DevDesc_t            DevDesc;
1078
1079    CtlrModel[0] = CtlrName[0] = CNULL;
1080    memset(&DevDesc, CNULL, sizeof(DevDesc_t));
1081
1082    /*
1083     * See if this is a Disk Controller
1084     */
1085    switch (Inv->inv_type) {
1086#if     defined(INV_SCSICONTROL)
1087    case INV_SCSICONTROL:
1088        /*
1089         * SCSI
1090         */
1091        ClassType = CT_SCSI;
1092        (void) snprintf(CtlrName, sizeof(CtlrName), "dks%d",
1093                        Inv->inv_controller);
1094
1095        Def = DefGet("scsi-ctlr", NULL, Inv->inv_state, 0);
1096        if (Def && Def->ValStr1)
1097            (void) strcpy(CtlrModel, Def->ValStr1);
1098        else
1099            (void) snprintf(CtlrModel, sizeof(CtlrModel),
1100                            "Cannot lookup SCSI Cltr (Type=%d)",
1101                            Inv->inv_state);
1102        /*
1103         * Check for additional bits of info
1104         */
1105        if (Inv->inv_unit) {
1106            (void) snprintf(Buff, sizeof(Buff),  "%X", Inv->inv_unit);
1107            DevDesc.Desc = Buff;
1108            DevDesc.Label = "Revision";
1109        }
1110
1111        break;
1112#endif  /* INV_SCSICONTROL */
1113#if     defined(INV_DKIPCONTROL)
1114    case INV_DKIPCONTROL:
1115        /*
1116         * IPI
1117         */
1118        ClassType = CT_IPI;
1119        (void) snprintf(CtlrName, sizeof(CtlrName), "ipi%d",
1120                        Inv->inv_controller);
1121        Def = DefGet("DiskTypes", NULL, Inv->inv_state, 0);
1122        if (Def && Def->ValStr1)
1123            (void) strcpy(CtlrModel, Def->ValStr1);
1124        else
1125            (void) snprintf(CtlrModel, sizeof(CtlrModel),
1126                            "Cannot lookup INV_DKIPCONTROL (Type=%d)",
1127                            Inv->inv_state);
1128        break;
1129#endif  /* INV_DKIPCONTROL */
1130#if     defined(INV_XYL714)
1131    case INV_XYL714:
1132#endif  /* INV_XYL714 */
1133#if     defined(INV_XYL754)
1134    case INV_XYL754:
1135        /*
1136         * SMD
1137         */
1138        ClassType = CT_SMD;
1139        (void) snprintf(CtlrName, sizeof(CtlrName), "xyl%d",
1140                        Inv->inv_controller);
1141        Def = DefGet("DiskTypes", NULL, Inv->inv_state, 0);
1142        if (Def && Def->ValStr1)
1143            (void) strcpy(CtlrModel, Def->ValStr1);
1144        else
1145            (void) snprintf(CtlrModel, sizeof(CtlrModel), 
1146                           "Cannot lookup INV_XYL* (Type=%d)", Inv->inv_state);
1147        break;
1148#endif  /* INV_XYL754 */
1149    }
1150
1151    if (CtlrName[0]) {
1152        /*
1153         * It's a controller so finish creating device entry.
1154         */
1155        DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
1156
1157        DevInfo->Name = strdup(CtlrName);
1158        if (CtlrModel[0])
1159            DevInfo->Model = strdup(CtlrModel);
1160        DevInfo->Unit = Inv->inv_controller;
1161        DevInfo->Type = DT_CONTROLLER;
1162        DevInfo->ClassType = ClassType;
1163        if (DevDesc.Desc || DevDesc.Label)
1164            AddDevDesc(DevInfo, DevDesc.Desc, DevDesc.Label, 0);
1165    } else {
1166        /*
1167         * Must be a Disk Drive
1168         */
1169        DevInfo = ProbeDiskDrive(Inv, TreePtr);
1170        if (DevInfo)
1171            DevInfo->ClassType = ClassType;
1172    }
1173
1174    return(DevInfo);
1175}
1176
1177/*
1178 * Get I/O Board info from Inventory
1179 */
1180static DevInfo_t *InvGetIOBoard(Inv)
1181    inventory_t                *Inv;
1182{
1183    DevInfo_t                  *DevInfo = NULL;
1184    Define_t                   *Def;
1185    char                        Model[256];
1186    char                        DevName[128];
1187    static char                 Desc[128];
1188    static int                  DevNum = 0;
1189
1190    DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
1191    DevInfo->Unit = DevInfo->Addr = DevInfo->Prio = DevInfo->Vec = -1;
1192    DevInfo->Type = DT_CARD;
1193    if (Inv->inv_unit > 0) {
1194        DevInfo->Unit = Inv->inv_unit;
1195        AddDevDesc(DevInfo, itoa(Inv->inv_unit), "Ebus Slot", 0);
1196    }
1197
1198#if     defined(INV_O200IO)
1199    if (Inv->inv_type == INV_O200IO)
1200        /* See if we can find the specific type of O2000 board */
1201        Def = DefGet("O2000ioTypes", NULL, Inv->inv_state, 0);
1202    else
1203#endif  /* INV_O200IO */
1204        /* Just get the generic I/O Board type */
1205        Def = DefGet("IOBoardTypes", NULL, Inv->inv_type, 0);
1206    if (Def) {
1207        if (Def->ValStr1)
1208            DevInfo->Model = Def->ValStr1;
1209        if (Def->ValStr2) {
1210            (void) snprintf(DevName, sizeof(DevName),  "%s%d", Def->ValStr2,
1211                           (DevInfo->Unit) ? DevInfo->Unit : DevNum++);
1212            DevInfo->Name = strdup(DevName);
1213        }
1214    }
1215
1216    if (!DevInfo->Name) {
1217        (void) snprintf(DevName, sizeof(DevName), "IOBoard%d", DevNum++);
1218        DevInfo->Name = strdup(DevName);
1219    }
1220    if (!DevInfo->Model) {
1221        (void) snprintf(Model, sizeof(Model), "Unknown IOBoard Type (%d)",
1222                        Inv->inv_type);
1223        DevInfo->Model = strdup(Model);
1224    }
1225
1226    Def = NULL;
1227    if (Inv->inv_type == INV_EVIO)
1228        Def = DefGet("EVIOBoardStates", NULL, Inv->inv_state, 0);
1229    if (Def && Def->ValStr1)
1230        AddDevDesc(DevInfo, Def->ValStr1, NULL, 0);
1231
1232    return(DevInfo);
1233}
1234
1235/*
1236 * Get Bus info from Inventory
1237 */
1238static DevInfo_t *InvGetBus(Inv)
1239    inventory_t                *Inv;
1240{
1241    DevInfo_t                  *DevInfo = NULL;
1242    ClassType_t                *Class;
1243    Define_t                   *Def;
1244    char                        Model[256];
1245    char                        DevName[128];
1246    static char                 Desc[128];
1247
1248    DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
1249    DevInfo->Unit = DevInfo->Addr = DevInfo->Prio = DevInfo->Vec = -1;
1250    DevInfo->Type = DT_BUS;
1251    DevInfo->Unit = Inv->inv_controller;
1252
1253    Def = DefGet("BusTypes", NULL, Inv->inv_type, 0);
1254    if (Def) {
1255        if (Def->ValStr1)
1256            DevInfo->Model = Def->ValStr1;
1257        if (Def->ValStr2) {
1258            (void) snprintf(DevName, sizeof(DevName), "%s%d",
1259                            Def->ValStr2, DevInfo->Unit);
1260            DevInfo->Name = strdup(DevName);
1261        }
1262        if (Def->ValStr3)
1263            if (Class = ClassTypeGetByName(DT_BUS, Def->ValStr3))
1264                DevInfo->ClassType = Class->Type;
1265    }
1266
1267    if (!DevInfo->Name) {
1268        (void) snprintf(DevName, sizeof(DevName), "bus%d", DevInfo->Unit);
1269        DevInfo->Name = strdup(DevName);
1270    }
1271    if (!DevInfo->Model && !DevInfo->ClassType) {
1272        (void) snprintf(Model, sizeof(Model), "Unknown BusTypes (%d)",
1273                        Inv->inv_type);
1274        DevInfo->Model = strdup(Model);
1275    }
1276
1277    return(DevInfo);
1278}
1279
1280/*
1281 * Get Compression Device info from Inventory
1282 */
1283static DevInfo_t *InvGetComp(Inv)
1284    inventory_t                *Inv;
1285{
1286    DevInfo_t                  *DevInfo = NULL;
1287    Define_t                   *Def;
1288    char                        Model[256];
1289    char                        DevName[128];
1290    static char                 Desc[128];
1291
1292    DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
1293    DevInfo->Unit = DevInfo->Addr = DevInfo->Prio = DevInfo->Vec = -1;
1294    DevInfo->Type = DT_GENERIC;
1295    DevInfo->Unit = Inv->inv_unit;
1296
1297    Def = DefGet("CompressionTypes", NULL, Inv->inv_type, 0);
1298    if (Def) {
1299        if (Def->ValStr1)
1300            DevInfo->Model = Def->ValStr1;
1301        if (Def->ValStr2) {
1302            (void) snprintf(DevName, sizeof(DevName), "%s%d",
1303                            Def->ValStr2, DevInfo->Unit);
1304            DevInfo->Name = strdup(DevName);
1305        }
1306    }
1307
1308    if (!DevInfo->Name) {
1309        (void) snprintf(DevName, sizeof(DevName), "compress%d", DevInfo->Unit);
1310        DevInfo->Name = strdup(DevName);
1311    }
1312    if (!DevInfo->Model) {
1313        (void) snprintf(Model, sizeof(Model), "Unknown CompressionTypes (%d)",
1314                        Inv->inv_type);
1315        DevInfo->Model = strdup(Model);
1316    }
1317
1318    return(DevInfo);
1319}
1320
1321/*
1322 * Get Misc Device info from Inventory
1323 */
1324static DevInfo_t *InvGetMisc(Inv)
1325    inventory_t                *Inv;
1326{
1327    DevInfo_t                  *DevInfo = NULL;
1328    Define_t                   *Def;
1329    char                        Model[256];
1330    char                        DevName[128];
1331    static char                 Desc[128];
1332
1333    DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
1334    DevInfo->Unit = DevInfo->Addr = DevInfo->Prio = DevInfo->Vec = -1;
1335    DevInfo->Type = DT_GENERIC;
1336    DevInfo->Unit = Inv->inv_unit;
1337
1338    Def = DefGet("MiscTypes", NULL, Inv->inv_type, 0);
1339    if (Def) {
1340        if (Def->ValStr1)
1341            DevInfo->Model = Def->ValStr1;
1342        if (Def->ValStr2) {
1343            (void) snprintf(DevName, sizeof(DevName), "%s%d",
1344                            Def->ValStr2, DevInfo->Unit);
1345            DevInfo->Name = strdup(DevName);
1346        }
1347    }
1348
1349    if (!DevInfo->Name) {
1350        (void) snprintf(DevName, sizeof(DevName), "misc%d", DevInfo->Unit);
1351        DevInfo->Name = strdup(DevName);
1352    }
1353    if (!DevInfo->Model) {
1354        (void) snprintf(Model, sizeof(Model), "Unknown MiscTypes (%d)",
1355                        Inv->inv_type);
1356        DevInfo->Model = strdup(Model);
1357    }
1358
1359    return(DevInfo);
1360}
1361
1362/*
1363 * Get PROM Device info from Inventory
1364 */
1365static DevInfo_t *InvGetPROM(Inv)
1366    inventory_t                *Inv;
1367{
1368    DevInfo_t                  *DevInfo = NULL;
1369    Define_t                   *Def;
1370    char                        Model[256];
1371    char                        DevName[128];
1372    static char                 Desc[128];
1373
1374    DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
1375    DevInfo->Unit = DevInfo->Addr = DevInfo->Prio = DevInfo->Vec = -1;
1376    DevInfo->Type = DT_GENERIC;
1377    DevInfo->Unit = Inv->inv_unit;
1378
1379    Def = DefGet("PROMTypes", NULL, Inv->inv_type, 0);
1380    if (Def) {
1381        if (Def->ValStr1)
1382            DevInfo->Model = Def->ValStr1;
1383        if (Def->ValStr2) {
1384            (void) snprintf(DevName, sizeof(DevName), "%s%d",
1385                            Def->ValStr2, DevInfo->Unit);
1386            DevInfo->Name = strdup(DevName);
1387        }
1388    }
1389
1390    if (!DevInfo->Name) {
1391        (void) snprintf(DevName, sizeof(DevName), "prom%d", DevInfo->Unit);
1392        DevInfo->Name = strdup(DevName);
1393    }
1394    if (!DevInfo->Model) {
1395        (void) snprintf(Model, sizeof(Model), "Unknown PROMTypes (%d)",
1396                        Inv->inv_type);
1397        DevInfo->Model = strdup(Model);
1398    }
1399
1400    return(DevInfo);
1401}
1402
1403#if     defined(HAVE_GRAPHICS_HDRS)
1404/*
1405 * Probe Frame Buffer
1406 */
1407extern DevInfo_t *ProbeFrameBuffer(DevInfo, Inv)
1408    DevInfo_t                  *DevInfo;
1409    inventory_t                *Inv;
1410{
1411    int                         fd;
1412    struct gfx_getboardinfo_args BoardInfo;
1413    struct gfx_info             GFXinfo;
1414    struct gfx_info            *GFXinfoPtr = NULL;
1415    struct ng1_info             NG1info;
1416    struct gr1_info             GR1info;
1417    struct gr2_info             GR2info;
1418    struct lg1_info             LG1info;
1419    struct venice_info          VENICEinfo;
1420    FrameBuffer_t              *Frame = NULL;
1421    static char                 Desc[256];
1422
1423    fd = open(_PATH_DEV_GRAPHICS, O_RDONLY);
1424    if (fd < 0) {
1425        SImsg(SIM_GERR, "Open failed: %s: %s", _PATH_DEV_GRAPHICS, SYSERR);
1426        return((DevInfo_t *) NULL);
1427    }
1428
1429    switch (Inv->inv_type) {
1430    case INV_NEWPORT:
1431        BoardInfo.buf = &NG1info;
1432        BoardInfo.len = sizeof(NG1info);
1433        GFXinfoPtr = &NG1info.gfx_info;
1434        break;
1435    case INV_GR1BOARD:
1436        BoardInfo.buf = &GR1info;
1437        BoardInfo.len = sizeof(GR1info);
1438        GFXinfoPtr = &GR1info.gfx_info;
1439        break;
1440    case INV_GR2:
1441        BoardInfo.buf = &GR2info;
1442        BoardInfo.len = sizeof(GR2info);
1443        GFXinfoPtr = &GR2info.gfx_info;
1444        break;
1445    case INV_LIGHT:
1446        BoardInfo.buf = &LG1info;
1447        BoardInfo.len = sizeof(LG1info);
1448        GFXinfoPtr = &LG1info.gfx_info;
1449        break;
1450#if     defined(INV_VENICE)     /* I don't know what type of GFX this is */
1451    case INV_VENICE:
1452        BoardInfo.buf = &VENICEinfo;
1453        BoardInfo.len = sizeof(VENICEinfo);
1454        GFXinfoPtr = &VENICEinfo.gfx_info;
1455        break;
1456#endif  /* INV_VENICE */
1457    default:
1458        BoardInfo.buf = &GFXinfo;
1459        BoardInfo.len = sizeof(GFXinfo);
1460        GFXinfoPtr = &GFXinfo;
1461    }
1462
1463    /*
1464     * inv_unit hopefully will always be the board number we want.
1465     */
1466    BoardInfo.board = Inv->inv_unit;
1467    if (ioctl(fd, GFX_GETBOARDINFO, &BoardInfo) < 0) {
1468        SImsg(SIM_GERR, "ioctl GFX_GETBOARDINFO failed: %s", SYSERR);
1469        return((DevInfo_t *) NULL);
1470    }
1471
1472    Frame = (FrameBuffer_t *) xcalloc(1, sizeof(FrameBuffer_t));
1473    DevInfo->DevSpec = (void *) Frame;
1474
1475    /*
1476     * Get Graphics Device specific info
1477     */
1478    switch (Inv->inv_type) {
1479    case INV_NEWPORT:
1480        Frame->Depth = NG1info.bitplanes;
1481
1482        AddDevDesc(DevInfo, itoa(NG1info.boardrev), "Board Revision", 0);
1483        AddDevDesc(DevInfo, itoa(NG1info.ng1_vof_info.fields_sec),
1484                   "Frequency (Hz)", 0);
1485        AddDevDesc(DevInfo, itoa(NG1info.monitortype),
1486                   "Monitor Type", 0);
1487        if (NG1info.videoinstalled)
1488            AddDevDesc(DevInfo, "Video is Installed", NULL, 0);
1489
1490        (void) snprintf(Desc, sizeof(Desc), "%c", 'A' + NG1info.rex3rev);
1491        AddDevDesc(DevInfo, Desc, "REX3 Revision", 0);
1492
1493        (void) snprintf(Desc, sizeof(Desc), "%c", 'A' + NG1info.vc2rev);
1494        AddDevDesc(DevInfo, Desc, "VC2 Revision", 0);
1495
1496        (void) snprintf(Desc, sizeof(Desc), "%c", 'A' + NG1info.mcrev);
1497        AddDevDesc(DevInfo, Desc, "MC Revision", 0);
1498
1499        (void) snprintf(Desc, sizeof(Desc), "%c", 'A' + NG1info.xmap9rev);
1500        AddDevDesc(DevInfo, Desc, "XMAP9 Revision", 0);
1501
1502        (void) snprintf(Desc, sizeof(Desc), "%c", 'A' + NG1info.cmaprev);
1503        AddDevDesc(DevInfo, Desc, "CMAP Revision", 0);
1504
1505        (void) snprintf(Desc, sizeof(Desc), "%c", 'A' + NG1info.bt445rev);
1506        AddDevDesc(DevInfo, Desc, "BT445 Revision", 0);
1507        break;
1508
1509    case INV_GR1BOARD:
1510        Frame->Depth = (int) GR1info.Bitplanes;
1511
1512        switch (GR1info.BoardType) {
1513        case GR1_TYPE_GR1:     
1514            (void) strcpy(Desc, "Personal Iris GR1");           break;
1515        case GR1_TYPE_VGR_PB:   
1516            (void) strcpy(Desc, "9U Sized on Private Bus");     break;
1517        case GR1_TYPE_PGR:     
1518            (void) strcpy(Desc, "6U Sized on Private Bus");     break;
1519        default:
1520            (void) snprintf(Desc, sizeof(Desc), "Unknown (Type %d)",
1521                            GR1info.BoardType);
1522        }
1523        AddDevDesc(DevInfo, Desc, "Board Type", 0);
1524
1525        (void) snprintf(Desc, sizeof(Desc), "%d", GR1info.REversion);
1526        AddDevDesc(DevInfo, Desc, "REversion", 0);
1527
1528        (void) snprintf(Desc, sizeof(Desc), "%d", GR1info.Auxplanes);
1529        AddDevDesc(DevInfo, Desc, "Auxilary Planes", 0);
1530
1531        (void) snprintf(Desc, sizeof(Desc), "%d", GR1info.Widplanes);
1532        AddDevDesc(DevInfo, Desc, "Wid Planes", 0);
1533
1534        (void) snprintf(Desc, sizeof(Desc), "%d", GR1info.Zplanes);
1535        AddDevDesc(DevInfo, Desc, "Zplanes", 0);
1536
1537        (void) snprintf(Desc, sizeof(Desc), "%d", GR1info.Cursorplanes);
1538        AddDevDesc(DevInfo, Desc, "Cursor Planes", 0);
1539
1540        if (GR1info.Turbo)
1541            AddDevDesc(DevInfo, "Turbo Option", "Has", 0);
1542
1543        if (GR1info.SmallMonitor)
1544            AddDevDesc(DevInfo, "Small Monitor", "Has", 0);
1545
1546        if (GR1info.VRAM1Meg)
1547            AddDevDesc(DevInfo, "1 megabit VRAMs", "Has", 0);
1548
1549        (void) snprintf(Desc, sizeof(Desc),  "%c", GR1info.picrev);
1550        AddDevDesc(DevInfo, Desc, "PIC Revision", 0);
1551        break;
1552
1553    case INV_GR2:
1554        Frame->Depth = (int) GR2info.Bitplanes;
1555
1556        switch (GR2info.BoardType) {
1557        case GR2_TYPE_GR2:     
1558            (void) strcpy(Desc, "Express GR2");         break;
1559        case GR2_TYPE_HI1:     
1560            (void) strcpy(Desc, "HI1");                 break;
1561        default:
1562            (void) snprintf(Desc, sizeof(Desc), "Unknown (Type %d)",
1563                            GR2info.BoardType);
1564        }
1565        AddDevDesc(DevInfo, Desc, "Board Type", 0);
1566
1567        (void) snprintf(Desc, sizeof(Desc), "%d", GR2info.Auxplanes);
1568        AddDevDesc(DevInfo, Desc, "Auxilary Planes", 0);
1569
1570        (void) snprintf(Desc, sizeof(Desc), "%d", GR2info.Wids);
1571        AddDevDesc(DevInfo, Desc, "Wids", 0);
1572
1573        (void) snprintf(Desc, sizeof(Desc), "%d", GR2info.GEs);
1574        AddDevDesc(DevInfo, Desc, "GEs", 0);
1575 
1576        if (GR2info.Zbuffer)
1577            AddDevDesc(DevInfo, "Z-Buffer", "Has", 0);
1578
1579        (void) snprintf(Desc, sizeof(Desc), "%c", 'A' + GR2info.VidBckEndRev);
1580        AddDevDesc(DevInfo, Desc, "Video Back End Revision", 0);
1581 
1582        (void) snprintf(Desc, sizeof(Desc), "%c", 'A' + GR2info.VidBrdRev);
1583        AddDevDesc(DevInfo, Desc, "Video Board Revision", 0);
1584 
1585        (void) snprintf(Desc, sizeof(Desc), "%d", GR2info.MonitorType);
1586        AddDevDesc(DevInfo, Desc, "Monitor Type", 0);
1587 
1588        (void) snprintf(Desc, sizeof(Desc), "%d", GR2info.MonTiming);
1589        AddDevDesc(DevInfo, Desc, "Monitor Timing", 0);
1590 
1591        (void) snprintf(Desc, sizeof(Desc), "%d", GR2info.GfxBoardRev);
1592        AddDevDesc(DevInfo, Desc, "GFX Board Revision", 0);
1593 
1594        (void) snprintf(Desc, sizeof(Desc), "%c", 'A' + GR2info.PICRev - 1);
1595        AddDevDesc(DevInfo, Desc, "PIC Revision", 0);
1596 
1597        (void) snprintf(Desc, sizeof(Desc), "%c", 'A' + GR2info.HQ2Rev - 1);
1598        AddDevDesc(DevInfo, Desc, "HQ2 Revision", 0);
1599 
1600        (void) snprintf(Desc, sizeof(Desc), "%c", 'A' + GR2info.GE7Rev - 1);
1601        AddDevDesc(DevInfo, Desc, "GE7 Revision", 0);
1602 
1603        (void) snprintf(Desc, sizeof(Desc), "%c", GR2info.RE3Rev);
1604        AddDevDesc(DevInfo, Desc, "RE3 Revision", 0);
1605 
1606        (void) snprintf(Desc, sizeof(Desc), "%c", 'A' + GR2info.VC1Rev - 1);
1607        AddDevDesc(DevInfo, Desc, "VC1 Revision", 0);
1608 
1609        break;
1610
1611    case INV_LIGHT:
1612        (void) snprintf(Desc, sizeof(Desc), "%d", LG1info.boardrev);
1613        AddDevDesc(DevInfo, Desc, "Board Revision", 0);
1614
1615        if (LG1info.boardrev >= 1) {
1616            (void) snprintf(Desc, sizeof(Desc), "%d", LG1info.monitortype);
1617            AddDevDesc(DevInfo, Desc, "Monitor Type", 0);
1618
1619            if (LG1info.videoinstalled)
1620                AddDevDesc(DevInfo, "Video is Installed", NULL, 0);
1621        }
1622
1623        (void) snprintf(Desc, sizeof(Desc), "%c", 'A' + LG1info.rexrev);
1624        AddDevDesc(DevInfo, Desc, "REX Revision", 0);
1625
1626        (void) snprintf(Desc, sizeof(Desc), "%c", 'A' + LG1info.vc1rev);
1627        AddDevDesc(DevInfo, Desc, "VC1 Revision", 0);
1628
1629        (void) snprintf(Desc, sizeof(Desc), "%c", 'A' + LG1info.picrev);
1630        AddDevDesc(DevInfo, Desc, "PIC Revision", 0);
1631
1632        break;
1633
1634#if     defined(INV_VENICE)
1635    case INV_VENICE:
1636        Frame->Depth = VENICEinfo.pixel_depth;
1637
1638        (void) snprintf(Desc, sizeof(Desc), "%d", VENICEinfo.ge_rev);
1639        AddDevDesc(DevInfo, Desc, "GE Revision", 0);
1640
1641        (void) snprintf(Desc, sizeof(Desc), "%d", VENICEinfo.ge_count);
1642        AddDevDesc(DevInfo, Desc, "GE Count", 0);
1643
1644        (void) snprintf(Desc, sizeof(Desc), "%d", VENICEinfo.rm_rev);
1645        AddDevDesc(DevInfo, Desc, "RM Revision", 0);
1646
1647        (void) snprintf(Desc, sizeof(Desc), "%d", VENICEinfo.rm_count);
1648        AddDevDesc(DevInfo, Desc, "RM Count", 0);
1649
1650        (void) snprintf(Desc, sizeof(Desc), "%d", VENICEinfo.ge_rev);
1651        AddDevDesc(DevInfo, Desc, "GT Revision", 0);
1652
1653        (void) snprintf(Desc, sizeof(Desc), "%d", VENICEinfo.tiles_per_line);
1654        AddDevDesc(DevInfo, Desc, "Tiles/Line", 0);
1655
1656        (void) snprintf(Desc, sizeof(Desc), "%d", VENICEinfo.ilOffset);
1657        AddDevDesc(DevInfo, Desc, "Initial Line Offset", 0);
1658
1659        (void) snprintf(Desc, sizeof(Desc), "%d", VENICEinfo.pixel_density);
1660        AddDevDesc(DevInfo, Desc, "Pixel Density", 0);
1661
1662        (void) snprintf(Desc, sizeof(Desc), "%d", VENICEinfo.hwalk_length);
1663        AddDevDesc(DevInfo, Desc, "No. of ops available in hblank", 0);
1664
1665        (void) snprintf(Desc, sizeof(Desc), "%d", VENICEinfo.tex_memory_size);
1666        AddDevDesc(DevInfo, Desc, "Texture Memory Size", 0);
1667
1668        break;
1669#endif  /* INV_VENICE */
1670    }
1671
1672    /*
1673     * Put together generic information
1674     */
1675    Frame->Width = GFXinfoPtr->xpmax;
1676    Frame->Height = GFXinfoPtr->ypmax;
1677    if (isprint(GFXinfoPtr->name[0]))
1678        DevInfo->Name = strdup(GFXinfoPtr->name);
1679    if (isprint(GFXinfoPtr->label[0]))
1680        AddDevDesc(DevInfo, GFXinfoPtr->label, "Managed By", 0);
1681
1682    (void) close(fd);
1683
1684    /* Return something */
1685    return(DevInfo);
1686}
1687#endif  /* HAVE_GRAPHICS_HDRS */
1688
1689/*
1690 * Get Graphics info from Inventory
1691 */
1692static DevInfo_t *InvGetGraphics(Inv)
1693    inventory_t                *Inv;
1694{
1695#if     defined(HAVE_GRAPHICS_HDRS)
1696    DevInfo_t                  *DevInfo = NULL;
1697    Define_t                   *Def;
1698    Define_t                   *DefList;
1699    char                       *ListName = NULL;
1700    char                       *GrType = NULL;
1701    char                        Model[256];
1702    char                        Desc[256];
1703    char                        DevName[256];
1704    static char                 GrTmp[128];
1705
1706    Model[0] = DevName[0] = CNULL;
1707
1708    DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
1709    DevInfo->Unit = DevInfo->Addr = DevInfo->Prio = DevInfo->Vec = -1;
1710    DevInfo->Type = DT_FRAMEBUFFER;
1711    DevInfo->Unit = Inv->inv_unit;
1712
1713    Def = DefGet("GraphicsTypes", NULL, Inv->inv_type, 0);
1714    if (Def && Def->ValStr1)
1715        DevInfo->Model = Def->ValStr1;
1716    else {
1717        (void) snprintf(Model, sizeof(Model), "Unknown Graphics (Type=%d)",
1718                        Inv->inv_type);
1719        DevInfo->Model = strdup(Model);
1720    }
1721
1722    (void) ProbeFrameBuffer(DevInfo, Inv);
1723
1724    if (!DevInfo->Name) {
1725        (void) snprintf(DevName, sizeof(DevName), "%s%d",
1726                        (Def && Def->ValStr2) ? Def->ValStr2 : "gfx",
1727                        Inv->inv_unit);
1728        DevInfo->Name = strdup(DevName);
1729    }
1730
1731    if (Inv->inv_state)
1732        switch (Inv->inv_type) {
1733        case INV_GR1BOARD:
1734        case INV_GR1BP:
1735        case INV_GR1ZBUFFER:
1736            ListName = "GR1States";
1737            break;
1738        case INV_GR2:
1739            ListName = "GR2States";
1740            GrType = "GR2";
1741            break;
1742        case INV_NEWPORT:
1743            ListName = "NEWPORTStates";
1744            break;
1745        case INV_MGRAS:
1746#if     defined(INV_MGRAS_ARCHS)
1747            Def = DefGet("MGRASarchs", NULL,
1748                         Inv->inv_state & INV_MGRAS_ARCHS, 0);
1749            if (Def)
1750                AddDevDesc(DevInfo, Def->ValStr1, NULL, 0);
1751            else
1752                if (Debug) printf("Unknown MGRASarchs: 0x%x\n",
1753                                  Inv->inv_state & INV_MGRAS_ARCHS);
1754#endif  /* INV_MGRAS_ARCHS */
1755
1756            Def = DefGet("MGRASges", NULL,
1757                         Inv->inv_state & INV_MGRAS_GES, 0);
1758            if (Def) AddDevDesc(DevInfo, Def->ValStr1, NULL, 0);
1759
1760            Def = DefGet("MGRASres", NULL,
1761                         Inv->inv_state & INV_MGRAS_RES, 0);
1762            if (Def) AddDevDesc(DevInfo, Def->ValStr1, NULL, 0);
1763
1764            Def = DefGet("MGRAStrs", NULL,
1765                         Inv->inv_state & INV_MGRAS_TRS, 0);
1766            if (Def) AddDevDesc(DevInfo, Def->ValStr1, NULL, 0);
1767
1768            break;
1769        }
1770
1771    if (ListName)
1772        for (Def = DefGetList(ListName); Def; Def = Def->Next)
1773            if ((Inv->inv_state & Def->KeyNum) && Def->ValStr1)
1774                AddDevDesc(DevInfo, Def->ValStr1, NULL, 0);
1775
1776    /*
1777     * See if there's a more specific submodel defined.
1778     */
1779    if (GrType) {
1780        SImsg(SIM_DBG,
1781              "GRDEBUG: GraphicsType=`%s' class=%d type=%d state=0x%x",
1782              GrType, Inv->inv_class, Inv->inv_type, Inv->inv_state);
1783        (void) snprintf(GrTmp, sizeof(GrTmp), "%sconfigs", GrType);
1784        Def = DefGetList(GrTmp, NULL, Inv->inv_state, 0);
1785        if (Def)
1786            DevInfo->Model = Def->ValStr1;
1787    }
1788
1789    return(DevInfo);
1790#else   /* !defined(HAVE_GRAPHICS_HDRS) */
1791    SImsg(SIM_GERR,
1792"Graphics/FrameBuffer found, but SysInfo compiled without HAVE_GRAPHICS_HDRS."
1793          );
1794    return((DevInfo_t *) NULL);
1795#endif  /* HAVE_GRAPHICS_HDRS */
1796}
1797
1798/*
1799 * Get Network info from Inventory
1800 */
1801static DevInfo_t *InvGetNetwork(Inv)
1802    inventory_t                *Inv;
1803{
1804    DevInfo_t                  *DevInfo = NULL;
1805    Define_t                   *Def;
1806    ClassType_t                *Class = NULL;
1807    char                        ModelBuff[256];
1808    char                       *Model = NULL;
1809    char                        DevName[128];
1810    char                       *DevBase = NULL;
1811
1812    /*
1813     * The inventory_t for networks looks like:
1814     *
1815     *  inv_type        - Class of device (ether, fddi, etc)
1816     *  inv_controller  - Model of device
1817     *  inv_state       - Model? specific
1818     */
1819    Def = DefGet("NetworkTypes", NULL, Inv->inv_controller, 0);
1820    if (Def) {
1821        if (Def->ValStr1)
1822            Model = Def->ValStr1;
1823        if (Def->ValStr2)
1824            DevBase = Def->ValStr2;
1825        if (Def->ValStr3)
1826            Class = ClassTypeGetByName(DT_NETIF, Def->ValStr3);
1827    }
1828
1829    if (!Model) {
1830        (void) snprintf(ModelBuff, sizeof(ModelBuff),
1831                        "Unknown Network Device (Type=%d)", Inv->inv_type);
1832        Model = ModelBuff;
1833    }
1834
1835    (void) snprintf(DevName, sizeof(DevName), "%s%d",
1836                    (DevBase) ? DevBase : "netif", Inv->inv_unit);
1837
1838    if (DevBase) {
1839        /*
1840         * Attempt to check system for device
1841         */
1842        ProbeData_t             ProbeData;
1843
1844        memset(&ProbeData, CNULL, sizeof(ProbeData));
1845        ProbeData.DevName = DevName;
1846        DevInfo = ProbeNetif(&ProbeData);
1847    }
1848    if (!DevInfo) {
1849        DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
1850        DevInfo->Unit = DevInfo->Addr = DevInfo->Prio = DevInfo->Vec = -1;
1851        DevInfo->Type = DT_NETIF;
1852        DevInfo->Name = strdup(DevName);
1853    }
1854
1855    if (Model)
1856        DevInfo->Model = strdup(Model);
1857    if (Class)
1858        DevInfo->ClassType = Class->Type;
1859           
1860    /*
1861     * Set what we know
1862     */
1863    switch (Inv->inv_controller) {
1864    case INV_FDDI_IPG:
1865    case INV_ETHER_EC:
1866        AddDevDesc(DevInfo, itoa(Inv->inv_state), "Version", 0);
1867        break;
1868    case INV_ETHER_EE:
1869        AddDevDesc(DevInfo, itoa(Inv->inv_state), "Ebus Slot", 0);
1870        break;
1871    default:
1872        /*
1873         * We don't know what inv_state means, but it may be useful
1874         * so we'll just add it.
1875         */
1876        AddDevDesc(DevInfo, itoa(Inv->inv_state), "State", 0);
1877    }
1878
1879    /*
1880     * Certain models indicate the actual controller number in
1881     * inv_state.  We try to make sure inv_controller only is set
1882     * when we know it means something so that the calling function
1883     * doesn't use it by mistake.
1884     */
1885    switch (Inv->inv_controller) {
1886    case INV_ETHER_EE:
1887        Inv->inv_controller = Inv->inv_state;
1888        break;
1889    default:
1890        Inv->inv_controller = 0;
1891    }
1892
1893    return(DevInfo);
1894}
1895
1896/*
1897 * Get Tape info from Inventory
1898 */
1899static DevInfo_t *InvGetTape(Inv)
1900    inventory_t                *Inv;
1901{
1902    DevInfo_t                  *DevInfo = NULL;
1903    Define_t                   *Def;
1904    static char                 DevFile[MAXPATHLEN];
1905    char                        Model[256];
1906    char                        DevName[128];
1907    int                         ClassType = 0;
1908    ClassType_t                *Class = NULL;
1909
1910    Model[0] = DevName[0] = CNULL;
1911
1912    DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
1913    DevInfo->Unit = DevInfo->Addr = DevInfo->Prio = DevInfo->Vec = -1;
1914    DevInfo->Type = DT_TAPEDRIVE;
1915
1916    switch (Inv->inv_type) {
1917    case INV_SCSIQIC:
1918    case INV_VSCSITAPE:
1919        /*
1920         * Lookup as a SCSI Tape
1921         */
1922        Def = DefGet("SCSITapeTypes", NULL, Inv->inv_state, 0);
1923        ClassType = CT_SCSI;
1924        /*
1925         * Perform SCSI queries
1926         */
1927        (void) snprintf(DevFile, sizeof(DevFile), "%s/sc%dd%dl0",
1928                        _PATH_DEV_SCSI, Inv->inv_controller, Inv->inv_unit);
1929        (void) ScsiQuery(DevInfo, DevFile, -1, TRUE);
1930        break;
1931    default:
1932        /*
1933         * Lookup as a general tape type
1934         */
1935        Def = DefGet("TapeTypes", NULL, Inv->inv_type, 0);
1936        if (Def && Def->ValStr3)
1937            if (Class = ClassTypeGetByName(DT_TAPEDRIVE, Def->ValStr3))
1938                ClassType = Class->Type;
1939        break;
1940    }
1941
1942    if (Def) {
1943        if (Def->ValStr1)
1944            DevInfo->Model = Def->ValStr1;
1945        if (Def->ValStr2)
1946            (void) snprintf(DevName, sizeof(DevName), "%s%dd%d", Def->ValStr2,
1947                            Inv->inv_controller, Inv->inv_unit);
1948    }
1949    if (!DevName[0])
1950        (void) snprintf(DevName, sizeof(DevName), "tape%d", Inv->inv_unit);
1951    if (!DevInfo->Model) {
1952        (void) snprintf(Model, sizeof(Model), "Unknown Tape Drive Type %d",
1953                        Inv->inv_state);
1954        DevInfo->Model = strdup(Model);
1955    }
1956
1957    DevInfo->Name = strdup(DevName);
1958    DevInfo->ClassType = ClassType;
1959
1960    return(DevInfo);
1961}
1962
1963/*
1964 * Get Parallel info from Inventory
1965 */
1966static DevInfo_t *InvGetParallel(Inv)
1967    inventory_t                *Inv;
1968{
1969    DevInfo_t                  *DevInfo = NULL;
1970    Define_t                   *Def;
1971    char                        Model[256];
1972    char                        DevName[128];
1973    static int                  ParallelNum = 0;
1974
1975    Model[0] = DevName[0] = CNULL;
1976
1977    DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
1978    DevInfo->Unit = DevInfo->Addr = DevInfo->Prio = DevInfo->Vec = -1;
1979    DevInfo->Type = DT_PARALLEL;
1980
1981    Def = DefGet("ParallelTypes", NULL, Inv->inv_type, 0);
1982    if (Def) {
1983        if (Def->ValStr1)
1984            DevInfo->Model = Def->ValStr1;
1985        if (Def->ValStr2) {
1986            (void) snprintf(DevName, sizeof(DevName), "%s%d",
1987                            Def->ValStr2, ParallelNum++);
1988            DevInfo->Name = strdup(DevName);
1989        }
1990    }
1991
1992    if (!DevInfo->Name) {
1993        (void) snprintf(DevName, sizeof(DevName), "parallel%d", ParallelNum++);
1994        DevInfo->Name = strdup(DevName);
1995    }
1996    if (!DevInfo->Model) {
1997        (void) snprintf(Model, sizeof(Model), "Unknown Parallel Type (%d)",
1998                        Inv->inv_type);
1999        DevInfo->Model = strdup(Model);
2000    }
2001
2002    return(DevInfo);
2003}
2004
2005/*
2006 * Get Serial info from Inventory
2007 */
2008static DevInfo_t *InvGetSerial(Inv)
2009    inventory_t                *Inv;
2010{
2011    DevInfo_t                  *DevInfo = NULL;
2012    Define_t                   *Def;
2013    char                        Model[256];
2014    char                        DevName[128];
2015    static int                  DevNum = 0;
2016
2017#if     defined(INV_INVISIBLE)
2018    if (Inv->inv_type == INV_INVISIBLE)
2019        return((DevInfo_t *) NULL);
2020#endif  /* INV_INVISIBLE */
2021
2022    DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
2023    DevInfo->Unit = DevInfo->Addr = DevInfo->Prio = DevInfo->Vec = -1;
2024    DevInfo->Type = DT_SERIAL;
2025
2026    Model[0] = DevName[0] = CNULL;
2027
2028    Def = DefGet("SerialTypes", NULL, Inv->inv_type, 0);
2029    if (Def) {
2030        if (Def->ValStr1)
2031            DevInfo->Model = Def->ValStr1;
2032        if (Def->ValStr2) {
2033            (void) snprintf(DevName, sizeof(DevName), "%s%d",
2034                            Def->ValStr2, DevNum++);
2035            DevInfo->Name = strdup(DevName);
2036        }
2037    }
2038
2039    if (!DevInfo->Name) {
2040        (void) snprintf(DevName, sizeof(DevName), "serial%d", DevNum++);
2041        DevInfo->Name = strdup(DevName);
2042    }
2043    if (!DevInfo->Model) {
2044        (void) snprintf(Model, sizeof(Model), "Unknown Serial Type (%d)",
2045                        Inv->inv_type);
2046        DevInfo->Model = strdup(Model);
2047    }
2048
2049    /*
2050     * Get what else we can find.
2051     */
2052    if (Inv->inv_state > 0)
2053        AddDevDesc(DevInfo, strdup(itoa(Inv->inv_state)),
2054                   "Number of Ports", 0);
2055
2056    return(DevInfo);
2057}
2058
2059/*
2060 * Get SCSI info from Inventory
2061 */
2062static DevInfo_t *InvGetSCSI(Inv, TreePtr)
2063    inventory_t                *Inv;
2064    DevInfo_t                  *TreePtr;
2065{
2066    DevInfo_t                  *DevInfo = NULL;
2067    DevInfo_t                  *CtlrDev = NULL;
2068    DevType_t                  *DevType = NULL;
2069    Define_t                   *Def;
2070    static DevFind_t            Find;
2071    char                        Model[256];
2072    char                        DevName[128];
2073    static int                  DevNum = 0;
2074
2075    DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
2076    DevInfo->Unit = DevInfo->Addr = DevInfo->Prio = DevInfo->Vec = -1;
2077    DevInfo->Type = DT_GENERIC;
2078    DevInfo->ClassType = CT_SCSI;
2079    DevInfo->Unit = Inv->inv_unit;
2080
2081    (void) memset(&Find, 0, sizeof(Find));
2082    Find.Tree = TreePtr;
2083    Find.DevType = DT_CONTROLLER;
2084    Find.ClassType = CT_SCSI;
2085    Find.Unit = Inv->inv_controller;
2086    if (CtlrDev = DevFind(&Find))
2087        DevInfo->Master = CtlrDev;
2088
2089    Model[0] = DevName[0] = CNULL;
2090
2091    Def = DefGet("SCSITypes", NULL, Inv->inv_type, 0);
2092    if (Def) {
2093        if (Def->ValStr2) {
2094            if (DevType = TypeGetByName(Def->ValStr2))
2095                DevInfo->Type = DevType->Type;
2096            (void) snprintf(DevName, sizeof(DevName), "%s%d",
2097                            Def->ValStr2, DevNum++);
2098            DevInfo->Name = strdup(DevName);
2099        }
2100        if (Def->ValStr1)
2101            /*
2102             * If we were unable to lookup ValStr2 (the DevType) then
2103             * go ahead and use ValStr1 as the Model.
2104             */
2105            if (!DevInfo->Type)
2106                DevInfo->Model = Def->ValStr1;
2107    }
2108
2109    if (!DevInfo->Model && !DevInfo->Type) {
2110        (void) snprintf(Model, sizeof(Model), "Unknown SCSITypes (%d)",
2111                        Inv->inv_type);
2112        DevInfo->Model = strdup(Model);
2113    }
2114    if (!DevInfo->Name) {
2115        DevInfo->Name = strdup(DevName);
2116        (void) snprintf(DevName, sizeof(DevName), "scsi%d", DevNum++);
2117    }
2118
2119    /*
2120     * Get what else we can find.
2121     */
2122    if (Inv->inv_state > 0) {
2123        AddDevDesc(DevInfo, strdup(itoa(Inv->inv_state)), "State", DA_APPEND);
2124        if (Inv->inv_state & INV_REMOVE)
2125            AddDevDesc(DevInfo, "Is Removable", NULL, 0);
2126    }
2127
2128    return(DevInfo);
2129}
2130
2131/*
2132 * Get Audio info from Inventory
2133 */
2134static DevInfo_t *InvGetAudio(Inv)
2135    inventory_t                *Inv;
2136{
2137    DevInfo_t                  *DevInfo = NULL;
2138    Define_t                   *Def;
2139    char                        Model[256];
2140    char                        DevName[128];
2141    static int                  DevNum = 0;
2142
2143    DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
2144    DevInfo->Unit = DevInfo->Addr = DevInfo->Prio = DevInfo->Vec = -1;
2145    DevInfo->Type = DT_AUDIO;
2146
2147    Model[0] = DevName[0] = CNULL;
2148
2149    Def = DefGet("AudioTypes", NULL, Inv->inv_type, 0);
2150    if (Def) {
2151        if (Def->ValStr1)
2152            DevInfo->Model = Def->ValStr1;
2153        if (Def->ValStr2) {
2154            (void) snprintf(DevName, sizeof(DevName), "%s%d",
2155                            Def->ValStr2, DevNum++);
2156            DevInfo->Name = strdup(DevName);
2157        }
2158    }
2159
2160    if (!DevInfo->Model) {
2161        (void) snprintf(Model, sizeof(Model), "Unknown AudioTypes (%d)",
2162                        Inv->inv_type);
2163        DevInfo->Model = strdup(Model);
2164    }
2165    if (!DevInfo->Name) {
2166        DevInfo->Name = strdup(DevName);
2167        (void) snprintf(DevName, sizeof(DevName), "audio%d", DevNum++);
2168    }
2169
2170    /*
2171     * Get what else we can find.
2172     */
2173    if (Inv->inv_state > 0) {
2174        AddDevDesc(DevInfo, strdup(itoa(Inv->inv_state)),
2175                   "State", 0);
2176    }
2177
2178    return(DevInfo);
2179}
2180
2181/*
2182 * Get Video info from Inventory
2183 */
2184static DevInfo_t *InvGetVideo(Inv)
2185    inventory_t                *Inv;
2186{
2187    DevInfo_t                  *DevInfo = NULL;
2188    Define_t                   *Def;
2189    char                       *StateList = NULL;
2190    char                        Model[256];
2191    char                        DevName[128];
2192
2193    DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
2194    DevInfo->Unit = DevInfo->Addr = DevInfo->Prio = DevInfo->Vec = -1;
2195    DevInfo->Type = DT_GENERIC;
2196    DevInfo->Unit = Inv->inv_unit;
2197
2198    Model[0] = DevName[0] = CNULL;
2199
2200    Def = DefGet("VideoTypes", NULL, Inv->inv_type, 0);
2201    if (Def) {
2202        if (Def->ValStr1)
2203            DevInfo->Model = Def->ValStr1;
2204        if (Def->ValStr2) {
2205            (void) snprintf(DevName, sizeof(DevName), "%s%d",
2206                            Def->ValStr2, Inv->inv_unit);
2207            DevInfo->Name = strdup(DevName);
2208        }
2209    }
2210
2211    if (!DevInfo->Model) {
2212        (void) snprintf(Model, sizeof(Model), "Unknown VideoTypes (%d)",
2213                        Inv->inv_type);
2214        DevInfo->Model = strdup(Model);
2215    }
2216    if (!DevInfo->Name) {
2217        DevInfo->Name = strdup(DevName);
2218        (void) snprintf(DevName, sizeof(DevName), "video%d", Inv->inv_unit);
2219    }
2220
2221    /*
2222     * Get what else we can find.
2223     */
2224    if (Inv->inv_state > 0) {
2225        AddDevDesc(DevInfo, strdup(itoa(Inv->inv_state)),
2226                   "State", 0);
2227        switch (Inv->inv_type) {
2228        case INV_VIDEO_EXPRESS:
2229            StateList = "ExpressVideoStates";
2230            break;
2231        case INV_VIDEO_VINO:
2232            StateList = "VinoVideoStates";
2233            break;
2234        }
2235        if (StateList)
2236            for (Def = DefGetList(StateList); Def; Def = Def->Next)
2237                if ((Inv->inv_state & Def->KeyNum) && Def->ValStr1)
2238                    AddDevDesc(DevInfo, Def->ValStr1, NULL, 0);
2239    }
2240
2241    return(DevInfo);
2242}
2243
2244/*
2245 * Get Display info from Inventory
2246 */
2247static DevInfo_t *InvGetDisplay(Inv)
2248    inventory_t                *Inv;
2249{
2250    DevInfo_t                  *DevInfo = NULL;
2251    Define_t                   *Def;
2252    char                       *StateList = NULL;
2253    char                        Model[256];
2254    char                        DevName[128];
2255
2256    DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
2257    DevInfo->Unit = DevInfo->Addr = DevInfo->Prio = DevInfo->Vec = -1;
2258    DevInfo->Type = DT_GENERIC;
2259    DevInfo->Unit = Inv->inv_unit;
2260
2261    Model[0] = DevName[0] = CNULL;
2262
2263    Def = DefGet("DisplayTypes", NULL, Inv->inv_type, 0);
2264    if (Def) {
2265        if (Def->ValStr1)
2266            DevInfo->Model = Def->ValStr1;
2267        if (Def->ValStr2) {
2268            (void) snprintf(DevName, sizeof(DevName), "%s%d",
2269                            Def->ValStr2, Inv->inv_unit);
2270            DevInfo->Name = strdup(DevName);
2271        }
2272    }
2273
2274    if (!DevInfo->Model) {
2275        (void) snprintf(Model, sizeof(Model), "Unknown DisplayTypes (%d)",
2276                        Inv->inv_type);
2277        DevInfo->Model = strdup(Model);
2278    }
2279    if (!DevInfo->Name) {
2280        DevInfo->Name = strdup(DevName);
2281        (void) snprintf(DevName, sizeof(DevName), "display%d", Inv->inv_unit);
2282    }
2283
2284    return(DevInfo);
2285}
2286
2287/*
2288 * Get Memory info from Inventory
2289 */
2290static DevInfo_t *InvGetMemory(Inv)
2291    inventory_t                *Inv;
2292{
2293    DevInfo_t                  *DevInfo = NULL;
2294    Define_t                   *Def;
2295    char                        Model[256];
2296    char                        DevName[20];
2297    static char                 Desc[128];
2298    char                       *SizeStr;
2299    static int                  MemNum = 0;
2300
2301    /*
2302     * INV_MAIN_MB is really just the amount of
2303     * main memory in MBytes.  It's not needed because
2304     * we count on INV_MAIN.
2305     */
2306    if (Inv->inv_type == INV_MAIN_MB)
2307        return((DevInfo_t *) NULL);
2308
2309    Desc[0] = Model[0] = CNULL;
2310
2311    DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
2312    DevInfo->Unit = DevInfo->Addr = DevInfo->Prio = DevInfo->Vec = -1;
2313    DevInfo->Type = DT_MEMORY;
2314
2315    SizeStr = GetSizeStr((Large_t)Inv->inv_state, BYTES);
2316    Def = DefGet("MemoryTypes", NULL, Inv->inv_type, 0);
2317    if (Def) {
2318        if (Def->ValStr1) {
2319            (void) snprintf(Model, sizeof(Model), "%s %s",
2320                            SizeStr, Def->ValStr1);
2321            DevInfo->Model = strdup(Model);
2322        }
2323        if (Def->ValStr2)
2324            DevInfo->Name = Def->ValStr2;
2325    }
2326
2327    if (!DevInfo->Name) {
2328        (void) snprintf(DevName, sizeof(DevName), "mem%d", MemNum++);
2329        DevInfo->Name = strdup(DevName);
2330    }
2331    if (!DevInfo->Model) {
2332        (void) snprintf(Model, sizeof(Model), "Unknown Memory Type (%d) %s",
2333                       Inv->inv_type, SizeStr);
2334        DevInfo->Model = strdup(Model);
2335    }
2336
2337    /*
2338     * Get what else we can find.
2339     */
2340    if (Inv->inv_unit > 0) {
2341        (void) snprintf(Desc, sizeof(Desc), "%d-way", Inv->inv_unit);
2342        AddDevDesc(DevInfo, Desc, "Interleave", 0);
2343    }
2344
2345    return(DevInfo);
2346}
2347
2348/*
2349 * Get CPU info from Inventory
2350 */
2351static DevInfo_t *InvGetCPU(Inv)
2352    inventory_t                *Inv;
2353{
2354    DevInfo_t                  *DevInfo = NULL;
2355    char                        Model[256];
2356    char                        DevName[128];
2357    char                        Desc[256];
2358    char                        Label[128];
2359    static int                  CPUboardNum = 0;
2360    static int                  CPUNum = 0;
2361    static int                  ProcessorNum = 0;
2362    Define_t                   *Def;
2363
2364    Model[0] = DevName[0] = Desc[0] = Label[0] = CNULL;
2365
2366    switch (Inv->inv_type) {
2367    case INV_CPUBOARD:
2368        /*
2369         * It doesn't appear there is a real unit number assigned
2370         * to a system board, so we'll make one up for now.
2371         */
2372        (void) snprintf(DevName, sizeof(DevName), "cpuboard%d", CPUboardNum++);
2373
2374        Def = DefGet("cpuboard", NULL, Inv->inv_state, 0);
2375        if (Def && Def->ValStr1)
2376            (void) strcpy(Model, Def->ValStr1);
2377        else
2378            (void) snprintf(Model, sizeof(Model), "Type %d CPU Board",
2379                            Inv->inv_state);
2380
2381        /*
2382         * What vague CPU info there is is associated with the cpuboard
2383         * for some silly reason.
2384         */
2385        (void) snprintf(Desc, sizeof(Desc), "%s %d MHz %s CPUs",
2386                       GetNumCpu(), Inv->inv_controller,
2387                       strupper(GetCpuType()));
2388        break;
2389    case INV_CPUCHIP:
2390        /* This doesn't tell us anything */
2391        break;
2392    case INV_FPUCHIP:
2393        (void) snprintf(DevName, sizeof(DevName), "fpu%d", Inv->inv_unit);
2394        (void) snprintf(Model, sizeof(Model), "Floating Point Unit");
2395        (void) snprintf(Label, sizeof(Label), "Revision");
2396        (void) snprintf(Desc, sizeof(Desc), "%d", Inv->inv_state);
2397        break;
2398    case INV_CCSYNC:
2399        /* What the hell is this? */
2400        (void) strcpy(DevName, "ccsync");
2401        (void) strcpy(Model, "CC Revision 2+ sync join counter");
2402        break;
2403    default:
2404        (void) snprintf(DevName, sizeof(DevName), "processor%d",
2405                        ProcessorNum++);
2406        (void) snprintf(Model, sizeof(Model), "Unknown Processor Type (%d)",
2407                        Inv->inv_type);
2408    }
2409
2410    if (DevName[0]) {
2411        DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
2412        DevInfo->Unit = DevInfo->Addr = DevInfo->Prio = DevInfo->Vec = -1;
2413        DevInfo->Name = strdup(DevName);
2414        if (Model[0])
2415            DevInfo->Model = strdup(Model);
2416        if (Desc[0])
2417            AddDevDesc(DevInfo, Desc, (Label[0]) ? Label : NULL, 0);
2418    }
2419
2420    return(DevInfo);
2421}
2422
2423/*
2424 * Use the SGI getinvent(3) interface.
2425 */
2426static int BuildDevicesInvent(TreePtrPtr, Names)
2427    DevInfo_t                  **TreePtrPtr;
2428    char                       **Names;
2429{
2430    static DevData_t            DevData;
2431    static DevFind_t            Find;
2432    DevInfo_t                  *DevInfo;
2433    DevInfo_t                  *CtlrDev = NULL;
2434    inventory_t                *Inv;
2435    char                        Buff[256];
2436    static int                  DevNum = 0;
2437
2438    setinvent();
2439
2440    while (Inv = getinvent()) {
2441        DevInfo = NULL;
2442        SImsg(SIM_DBG,
2443              "INV: Class = %d Type = %d ctrl = %d unit = %d state = %d",
2444              Inv->inv_class, Inv->inv_type, Inv->inv_controller,
2445              Inv->inv_unit, Inv->inv_state);
2446        switch (Inv->inv_class) {
2447        case INV_PROCESSOR:
2448            DevInfo = InvGetCPU(Inv);
2449            break;
2450        case INV_IOBD:
2451            DevInfo = InvGetIOBoard(Inv);
2452            break;
2453        case INV_BUS:
2454            DevInfo = InvGetBus(Inv);
2455            break;
2456        case INV_DISK:
2457            DevInfo = InvGetDisk(Inv, *TreePtrPtr);
2458            break;
2459        case INV_MEMORY:
2460            DevInfo = InvGetMemory(Inv);
2461            break;
2462        case INV_SERIAL:
2463            DevInfo = InvGetSerial(Inv);
2464            break;
2465        case INV_PARALLEL:
2466            DevInfo = InvGetParallel(Inv);
2467            break;
2468        case INV_TAPE:
2469            DevInfo = InvGetTape(Inv);
2470            break;
2471        case INV_GRAPHICS:
2472            DevInfo = InvGetGraphics(Inv);
2473            break;
2474        case INV_NETWORK:
2475            DevInfo = InvGetNetwork(Inv);
2476            break;
2477        case INV_SCSI:
2478            DevInfo = InvGetSCSI(Inv, *TreePtrPtr);
2479            break;
2480        case INV_AUDIO:
2481            DevInfo = InvGetAudio(Inv);
2482            break;
2483        case INV_VIDEO:
2484            DevInfo = InvGetVideo(Inv);
2485            break;
2486        case INV_DISPLAY:
2487            DevInfo = InvGetDisplay(Inv);
2488            break;
2489        case INV_COMPRESSION:
2490            DevInfo = InvGetComp(Inv);
2491            break;
2492        case INV_MISC:
2493            DevInfo = InvGetMisc(Inv);
2494            break;
2495#if     OSVER >= 64
2496        case INV_PROM:
2497            DevInfo = InvGetPROM(Inv);
2498            break;
2499#endif  /* OSVER >= 64 */
2500        default:
2501            DevInfo = (DevInfo_t *) xcalloc(1, sizeof(DevInfo_t));
2502            (void) snprintf(Buff, sizeof(Buff), "unknown%d", DevNum++);
2503            DevInfo->Name = strdup(Buff);
2504            DevInfo->Unit = Inv->inv_unit;
2505            (void) snprintf(Buff, sizeof(Buff),
2506           "Unknown Device Type (class=%d type=%d ctlr=%d unit=%d state=%d)",
2507                            Inv->inv_class, Inv->inv_type, Inv->inv_controller,
2508                            Inv->inv_unit, Inv->inv_state);
2509            DevInfo->Model = strdup(Buff);
2510        }
2511        /*
2512         * See if we can find a generic controller card for this device
2513         */
2514        if (DevInfo && !DevInfo->Master && Inv->inv_controller > 0) {
2515            (void) memset(&Find, 0, sizeof(Find));
2516            Find.Tree = *TreePtrPtr;
2517            Find.DevType = DT_CARD;
2518            Find.ClassType = -1;
2519            Find.Unit = Inv->inv_controller;
2520            if (CtlrDev = DevFind(&Find))
2521                DevInfo->Master = CtlrDev;
2522        }
2523        if (DevInfo)
2524            AddDevice(DevInfo, TreePtrPtr, Names);
2525    }
2526
2527    endinvent();
2528
2529    return(0);
2530}
2531
2532/*
2533 * Build device tree using TreePtr.
2534 * Calls bus and method specific functions to
2535 * search for devices.
2536 */
2537extern int BuildDevices(TreePtr, Names)
2538    DevInfo_t                  **TreePtr;
2539    char                       **Names;
2540{
2541    int                          Found = 1;
2542
2543    if (BuildDevicesInvent(TreePtr, Names) == 0)
2544        Found = 0;
2545
2546    return(Found);
2547}
Note: See TracBrowser for help on using the repository browser.