source: trunk/third/sysinfo/os-sunos4.c @ 11115

Revision 11115, 25.9 KB checked in by ghudson, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r11114, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Copyright (c) 1992-1996 Michael A. Cooper.
3 * This software may be freely used and distributed provided it is not sold
4 * for profit or used for commercial gain and the author is credited
5 * appropriately.
6 */
7
8#ifndef lint
9static char *RCSid = "$Id: os-sunos4.c,v 1.1.1.2 1998-02-12 21:32:18 ghudson Exp $";
10#endif
11
12/*
13 * SunOS 4.x specific routines
14 */
15
16#include "defs.h"
17#include <sys/stat.h>
18#include <sys/mtio.h>
19
20/*
21 * Characters for disk partitions
22 */
23char                    PartChars[] = "abcdefgh";
24
25/*
26 * CPU (model) symbol
27 */
28char                    CpuSYM[] = "_cpu";
29
30/*
31 * Name of generic magnetic tape device.
32 */
33#define MTNAME          "mt"
34
35
36/*
37 * Generally used variables
38 */
39static kvm_t                   *kd = NULL;
40static struct stat              StatBuf;
41static DevInfo_t               *DevInfo;
42static char                     Buf[BUFSIZ];
43extern char                     RomVecSYM[];
44static int                      OpenPROMTraverse();
45
46#if     defined(HAVE_MAINBUS)
47/*
48 * Build a device tree by searching the MainBus
49 */
50
51#define DV_SIZE (sizeof(struct mb_device))
52#define DR_SIZE (sizeof(struct mb_driver))
53extern char                     MainBusSYM[];
54
55/*
56 * Build device tree by looking at mainbus (mb) devices
57 */
58extern int BuildMainBus(TreePtr, SearchNames)
59    DevInfo_t                  **TreePtr;
60    char                       **SearchNames;
61{
62    struct nlist               *nlptr;
63    static struct mb_device     Device;
64    static struct mb_driver     Driver;
65    static char                 CtlrName[BUFSIZ], DevName[BUFSIZ];
66    static DevData_t            DevData;
67    u_long                      Addr, DeviceAddr;
68    DevInfo_t                  *DevInfo;
69
70    /*
71     * Read table address from kernel
72     */
73    if (!(kd = KVMopen()))
74        return(-1);
75
76    if ((nlptr = KVMnlist(kd, MainBusSYM, (struct nlist *)NULL, 0)) == NULL)
77        return(-1);
78
79    if (CheckNlist(nlptr))
80        return(-1);
81
82    /*
83     * Read each device table entry.  A NULL device.mb_driver
84     * indicates that we're at the end of the table.
85     */
86    for (DeviceAddr = nlptr->n_value; DeviceAddr;
87         DeviceAddr += DV_SIZE) {
88
89        /*
90         * Read this device
91         */
92        if (KVMget(kd, DeviceAddr, (char *) &Device, DV_SIZE, KDT_DATA)) {
93            if (Debug)
94                Error("Cannot read mainbus device from address 0x%x.",
95                      DeviceAddr);
96            KVMclose(kd);
97            return(-1);
98        }
99
100        /*
101         * See if we're done.
102         */
103        if (!Device.md_driver)
104            break;
105
106        /*
107         * Read the driver structure
108         */
109        Addr = (u_long) Device.md_driver;
110        if (KVMget(kd, Addr, (char *) &Driver, DR_SIZE, KDT_DATA)) {
111            if (Debug)
112                Error("Cannot read driver for mainbus address 0x%x.", Addr);
113            continue;
114        }
115
116        /*
117         * Get the device name
118         */
119        if (Addr = (u_long) Driver.mdr_dname) {
120            if (KVMget(kd, Addr, (char *) DevName,
121                       sizeof(DevName), KDT_STRING)) {
122                if (Debug)
123                    Error("Cannot read device name from address 0x%x.", Addr);
124                continue;
125            }
126        } else
127            DevName[0] = CNULL;
128
129        /*
130         * Get the controller name
131         * XXX - not if "Device.md_ctlr" is -1; work around botch
132         * in current Auspex releases, where some boards (File Processor,
133         * Primary Memory, etc.) have both a device and a controller name,
134         * despite the fact that there's not both a controller and a
135         * set of 1 or more devices.
136         */
137        if ((Addr = (u_long) Driver.mdr_cname) && Device.md_ctlr != -1) {
138            if (KVMget(kd, Addr, (char *) CtlrName,
139                       sizeof(CtlrName), KDT_STRING)) {
140                if (Debug)
141                    Error("Cannot read controller name from address 0x%x.",
142                          Addr);
143                continue;
144            }
145        } else
146            CtlrName[0] = CNULL;
147
148        /* Make sure devdata is clean */
149        bzero(&DevData, sizeof(DevData_t));
150
151        /* Set what we know */
152        if (DevName[0]) {
153            DevData.DevName = strdup(DevName);
154            DevData.DevUnit = Device.md_unit;
155        }
156        if (CtlrName[0]) {
157            DevData.CtlrName = strdup(CtlrName);
158            DevData.CtlrUnit = Device.md_ctlr;
159        }
160        /*
161         * Mainbus devices such, as SCSI targets, may not exist
162         * but the controller reports them as present
163         */
164        if (Device.md_alive)
165            DevData.Flags |= DD_MAYBE_ALIVE;
166
167        if (Debug)
168            printf("MainBus: Found \"%s\" (Unit %d) on \"%s\" (Unit %d) %s\n",
169                   DevData.DevName, DevData.DevUnit,
170                   DevData.CtlrName, DevData.CtlrUnit,
171                   (DevData.Flags & DD_MAYBE_ALIVE) ? "[MAYBE-ALIVE]" : "");
172
173        /* Probe and add device */
174        if (DevInfo = ProbeDevice(&DevData, TreePtr, SearchNames))
175            AddDevice(DevInfo, TreePtr, (char **)NULL);
176    }
177
178    KVMclose(kd);
179    return(0);
180}
181#endif  /* HAVE_MAINBUS */
182
183/*
184 * Get disk info structure.
185 */
186static DKinfo *GETdk_info(d, file)
187    int                         d;
188    char                       *file;
189{
190    static DKinfo               dk_info;
191
192    if (ioctl(d, DKIOCINFO, &dk_info) < 0) {
193        if (Debug) Error("%s: DKIOCINFO: %s.", file, SYSERR);
194        return(NULL);
195    }
196
197    return(&dk_info);
198}
199
200/*
201 * Get disk configuration structure.
202 */
203static DKconf *GETdk_conf(d, file, disktype)
204    int                         d;
205    char                       *file;
206    int                         disktype;
207{
208    static DKconf               dk_conf;
209
210    if (disktype == DKT_CDROM) {
211        if (Debug)
212            Error("%s: Get CDROM disk configuration info is not supported.",
213                  file);
214        return((DKconf *) NULL);
215    }
216
217    if (ioctl(d, DKIOCGCONF, &dk_conf) < 0) {
218        if (Debug) Error("%s: DKIOCGCONF: %s.", file, SYSERR);
219        return((DKconf *) NULL);
220    }
221
222    return(&dk_conf);
223}
224
225/*
226 * Get disk geometry structure.
227 */
228static DKgeom *GETdk_geom(d, file, disktype)
229    int                         d;
230    char                       *file;
231    int                         disktype;
232{
233    static DKgeom               dk_geom;
234
235    if (disktype == DKT_CDROM) {
236        if (Debug)
237            Error("%s: Get CDROM disk geometry info is not supported.", file);
238        return((DKgeom *) NULL);
239    }
240
241    if (ioctl(d, DKIOCGGEOM, &dk_geom) < 0) {
242        if (Debug) Error("%s: DKIOCGGEOM: %s.", file, SYSERR);
243        return((DKgeom *) NULL);
244    }
245
246    return(&dk_geom);
247}
248
249/*
250 * Get disk type structure.
251 */
252static DKtype *GETdk_type(d, file)
253    int                         d;
254    char                       *file;
255{
256    static DKtype               dk_type;
257
258    if (ioctl(d, DKIOCGTYPE, &dk_type) < 0) {
259        if (errno != ENOTTY)
260            if (Debug) Error("%s: DKIOCGTYPE: %s.", file, SYSERR);
261        return(NULL);
262    }
263
264    return(&dk_type);
265}
266
267/*
268 * Check the checksum of a disklabel.
269 */
270static int DkLblCheckSum(DkLabel)
271    DKlabel                    *DkLabel;
272{
273    register short             *Ptr, Sum = 0;
274    register short              Count;
275
276    Count = (sizeof (DKlabel)) / (sizeof (short));
277    Ptr = (short *)DkLabel;
278
279    /*
280     * Take the xor of all the half-words in the label.
281     */
282    while (Count--)
283        Sum ^= *Ptr++;
284
285    /*
286     * The total should be zero for a correct checksum
287     */
288    return(Sum);
289}
290
291/*
292 * Get label information from label on disk.
293 * The label is stored in the first sector of the disk.
294 * We use the driver specific "read" flag with the DKIOCSCMD
295 * ioctl to read the first sector.  There should be a special
296 * ioctl to just read the label.
297 */
298static DKlabel *GETdk_label(d, file, dk_info, disktype)
299    int                         d;
300    char                       *file;
301    DKinfo                     *dk_info;
302    int                         disktype;
303{
304    struct dk_cmd               dk_cmd;
305    static DKlabel              dk_label;
306    DevDefine_t                *DevDefine;
307
308    if (!file || !dk_info)
309        return((DKlabel *) NULL);
310
311    /*
312     * CDROM's don't support DKIOCSCMD and doing a DKIOCSCMD on
313     * a CDROM drive can sometimes crash a system.
314     */
315    if (disktype == DKT_CDROM) {
316        if (Debug) Error("%s: Reading CDROM labels is not supported.", file);
317        return((DKlabel *) NULL);
318    }
319
320    DevDefine = DevDefGet(NULL, DT_DISKCTLR, dk_info->dki_ctype);
321    if (!DevDefine) {
322        Error("Controller type %d is unknown.", dk_info->dki_ctype);
323        return((DKlabel *) NULL);
324    }
325
326    if (DevDefine->DevFlags <= 0) {
327        if (Debug)
328            Error("Read block on controller type \"%s\" is unsupported.",
329                  DevDefine->Model);
330        return((DKlabel *) NULL);
331    }
332
333    bzero((char *) &dk_cmd, sizeof(dk_cmd));
334    dk_cmd.dkc_cmd = DevDefine->DevFlags;
335    dk_cmd.dkc_flags = DK_SILENT | DK_ISOLATE;
336    dk_cmd.dkc_blkno = (daddr_t)0;
337    dk_cmd.dkc_secnt = 1;
338    dk_cmd.dkc_bufaddr = (char *) &dk_label;
339    dk_cmd.dkc_buflen = SECSIZE;
340
341    if (ioctl(d, DKIOCSCMD, &dk_cmd) < 0) {
342        if (Debug) Error("%s: DKIOCSCMD: %s.", file, SYSERR);
343        return((DKlabel *) NULL);
344    }
345
346    if (dk_label.dkl_magic != DKL_MAGIC) {
347        Error("%s: Disk not labeled.", file);
348        return((DKlabel *) NULL);
349    }
350
351    if (DkLblCheckSum(&dk_label)) {
352        Error("%s: Bad label checksum.", file);
353        return((DKlabel *) NULL);
354    }
355
356    return(&dk_label);
357}
358
359/*
360 * Get the name of a disk (i.e. sd0).
361 */
362static char *GetDiskName(name, dk_conf, dk_info)
363    char                       *name;
364    DKconf                     *dk_conf;
365    DKinfo                     *dk_info;
366{
367    if (!dk_conf || !dk_info) {
368        if (name)
369            return(name);
370        return((char *) NULL);
371    }
372
373#if     defined(DKI_HEXUNIT)
374    if (FLAGS_ON(dk_info->dki_flags, DKI_HEXUNIT))
375        (void) sprintf(Buf, "%s%3.3x", dk_conf->dkc_dname, dk_conf->dkc_unit);
376    else
377#endif  /* DKI_HEXUNIT */
378        (void) sprintf(Buf, "%s%d", dk_conf->dkc_dname, dk_conf->dkc_unit);
379
380    return(strdup(Buf));
381}
382
383/*
384 * Get the name of the controller for a disk.
385 */
386static char *GetDiskCtlrName(dk_conf)
387    DKconf                     *dk_conf;
388{
389    if (!dk_conf)
390        return((char *) NULL);
391
392    (void) sprintf(Buf, "%s%d", dk_conf->dkc_cname, dk_conf->dkc_cnum);
393
394    return(strdup(Buf));
395}
396
397/*
398 * Get a disk controller device from disk info.
399 */
400static DevInfo_t *GetDiskCtlrDevice(DevData, dk_info, dk_conf)
401    DevData_t                  *DevData;
402    DKinfo                     *dk_info;
403    DKconf                     *dk_conf;
404{
405    DevInfo_t                  *MkMasterFromDevData();
406    DevInfo_t                  *DiskCtlr;
407
408    /*
409     * Get name of controller from devdata if available
410     */
411    if (DevData && DevData->CtlrName)
412        DiskCtlr = MkMasterFromDevData(DevData);
413    else {
414        if ((DiskCtlr = NewDevInfo(NULL)) == NULL)
415            return((DevInfo_t *) NULL);
416    }
417
418    DiskCtlr->Type = DT_DISKCTLR;
419
420    if (dk_conf) {
421        if (!DiskCtlr->Name) {
422            DiskCtlr->Name = GetDiskCtlrName(dk_conf);
423            DiskCtlr->Unit = dk_conf->dkc_cnum;
424        }
425        DiskCtlr->Addr = dk_conf->dkc_addr;
426        DiskCtlr->Prio = dk_conf->dkc_prio;
427        DiskCtlr->Vec = dk_conf->dkc_vec;
428    }
429
430    if (dk_info)
431        SetDiskCtlrModel(DiskCtlr, dk_info->dki_ctype);
432
433    return(DiskCtlr);
434}
435
436/*
437 * Get disk label info from the extracted dk_label info.
438 */
439static char *GetDiskLabel(dk_label)
440    DKlabel                    *dk_label;
441{
442    register char              *cp;
443    char                       *label;
444
445    if (!dk_label)
446        return((char *) NULL);
447
448    label = strdup(dk_label->dkl_asciilabel);
449
450    /*
451     * The label normally has geometry information in it we don't want
452     * to see, so we trim out anything starting with " cyl".
453     */
454    for (cp = label; cp && *cp; ++cp)
455        if (*cp == ' ' && strncasecmp(cp, " cyl", 4) == 0)
456            *cp = CNULL;
457
458    return(label);
459}
460
461/*
462 * Get filesystem mount info for a partition.
463 */
464static char *GetMountInfo(name, part)
465    char                       *name;
466    char                       *part;
467{
468    static FILE                *mountedFP = NULL;
469    static FILE                *mnttabFP = NULL;
470    struct mntent              *mntent;
471    char                       *file;
472
473    if (!name)
474        return((char *) NULL);
475
476    file = GetCharFile(name, part);
477
478    /*
479     * First try currently mounted filesystems (/etc/mtab)
480     */
481    if (!mountedFP) {
482        if ((mountedFP = setmntent(MOUNTED, "r")) == NULL) {
483            Error("%s: Cannot open for reading: %s.", MOUNTED, SYSERR);
484            return(NULL);
485        }
486    } else
487        rewind(mountedFP);
488
489    while (mntent = getmntent(mountedFP))
490        if (mntent->mnt_fsname && EQ(mntent->mnt_fsname, file))
491            return(mntent->mnt_dir);
492
493    /*
494     * Now try static information (/etc/fstab)
495     */
496    if (!mnttabFP) {
497        if ((mnttabFP = setmntent(MNTTAB, "r")) == NULL) {
498            Error("%s: Cannot open for reading: %s.", MNTTAB, SYSERR);
499            return(NULL);
500        }
501    } else
502        rewind(mnttabFP);
503
504    while (mntent = getmntent(mnttabFP))
505        if (mntent->mnt_fsname && EQ(mntent->mnt_fsname, file))
506            return(mntent->mnt_dir);
507
508    return((char *) NULL);
509}
510
511/*
512 * Extract the disk partition info from a disk.
513 */
514static DiskPart_t *ExtractDiskPart(name, part, dk_conf, dk_geom)
515    char                       *name;
516    char                       *part;
517    DKconf                     *dk_conf;
518    DKgeom                     *dk_geom;
519{
520    static DiskPart_t           DiskPart;
521    struct dk_map               dk_map;
522    char                       *file;
523    char                       *p;
524    int                         d;
525
526    if (!name || !dk_conf || !dk_geom)
527        return((DiskPart_t *) NULL);
528
529    file = GetRawFile(name, part);
530
531    if (stat(file, &StatBuf) != 0) {
532        if (Debug) Error("%s: No such partition.", file);
533        return((DiskPart_t *) NULL);
534    }
535
536    if ((d = open(file, O_RDONLY)) < 0) {
537        if (Debug)
538            Error("%s: Cannot open for read: %s.", file, SYSERR);
539        return((DiskPart_t *) NULL);
540    }
541
542    if (ioctl(d, DKIOCGPART, &dk_map) != 0) {
543        Error("%s: Cannot extract partition info: %s.",
544                file, SYSERR);
545        return((DiskPart_t *) NULL);
546    }
547 
548    (void) close(d);
549
550    /*
551     * Skip empty partitions
552     */
553    if (!dk_map.dkl_nblk) {
554        if (Debug) Error("%s: partition has no size.", file);
555        return((DiskPart_t *) NULL);
556    }
557
558    bzero((char *) &DiskPart, sizeof(DiskPart_t));
559
560    DiskPart.Name = strdup(part);
561
562    if (p = GetMountInfo(name, part))
563        DiskPart.Usage = strdup(p);
564    /*
565     * If this is the "b" partition on the root device,
566     *  then assume it's swap
567     */
568    else if (dk_conf->dkc_unit == 0 && strcmp(part, "b") == 0)
569        DiskPart.Usage = "swap";
570
571    DiskPart.StartSect = dk_map.dkl_cylno *
572        (dk_geom->dkg_nhead * dk_geom->dkg_nsect);
573    DiskPart.NumSect = dk_map.dkl_nblk;
574
575    return(&DiskPart);
576}
577
578/*
579 * Translate disk partition information from basic
580 * extracted disk info.
581 */
582static DiskPart_t *GetDiskPart(name, dk_conf, dk_geom)
583    char                       *name;
584    DKconf                     *dk_conf;
585    DKgeom                     *dk_geom;
586{
587    extern char                 PartChars[];
588    register DiskPart_t        *Ptr;
589    DiskPart_t                 *DiskPart;
590    DiskPart_t                 *Base = NULL;
591    register int                i;
592    static char                 pname[2];
593
594    if (!name || !dk_conf || !dk_geom)
595        return((DiskPart_t *) NULL);
596
597    pname[1] = CNULL;
598    for (i = 0; PartChars[i]; ++i) {
599        pname[0] = PartChars[i];
600        if (DiskPart = ExtractDiskPart(name, pname, dk_conf, dk_geom)) {
601            if (Base) {
602                for (Ptr = Base; Ptr && Ptr->Next; Ptr = Ptr->Next);
603                Ptr->Next = NewDiskPart(DiskPart);
604            } else {
605                Base = NewDiskPart(DiskPart);
606            }
607        }
608    }
609
610    return(Base);
611}
612
613/*
614 * Convert all we've learned about a disk to a DevInfo_t.
615 */
616static DevInfo_t *dkToDevInfo(name, disktype, DevData,
617                              dk_info, dk_label, dk_conf, dk_geom, dk_type)
618    char                       *name;
619    int                         disktype;
620    DevData_t                  *DevData;
621    DKinfo                     *dk_info;
622    DKlabel                    *dk_label;
623    DKconf                     *dk_conf;
624    DKgeom                     *dk_geom;
625    DKtype                     *dk_type;
626{
627    DevInfo_t                  *DevInfo, *DiskCtlr;
628    DiskDrive_t                        *DiskDrive;
629
630    if ((DevInfo = NewDevInfo(NULL)) == NULL) {
631        Error("Cannot create new device entry.");
632        return((DevInfo_t *) NULL);
633    }
634
635    if ((DiskCtlr = NewDevInfo(NULL)) == NULL) {
636        Error("Cannot create new DiskCtlr device entry.");
637        return((DevInfo_t *) NULL);
638    }
639
640    if ((DiskDrive = NewDiskDrive(NULL)) == NULL) {
641        Error("Cannot create new DiskDrive entry.");
642        return((DevInfo_t *) NULL);
643    }
644
645    DevInfo->Name               = GetDiskName(name, dk_conf, dk_info);
646    DevInfo->Type               = DT_DISKDRIVE;
647    /*
648     * Only read partition info we we're going to print it later.
649     */
650    if (VL_ALL)
651        DiskDrive->DiskPart     = GetDiskPart(name, dk_conf, dk_geom);
652    DiskDrive->Label    = GetDiskLabel(dk_label);
653    DevInfo->Model              = DiskDrive->Label;
654
655    if (disktype == DKT_CDROM && DiskDrive->Label == NULL)
656        DevInfo->Model          = "CD-ROM";
657       
658    if (dk_conf) {
659        DiskDrive->Unit         = dk_conf->dkc_unit;
660        DiskDrive->Slave        = dk_conf->dkc_slave;;
661    }
662    if (dk_geom) {
663        DiskDrive->DataCyl      = dk_geom->dkg_ncyl;
664        DiskDrive->PhyCyl       = dk_geom->dkg_pcyl;
665        DiskDrive->AltCyl       = dk_geom->dkg_acyl;
666        DiskDrive->Heads        = dk_geom->dkg_nhead;
667        DiskDrive->Sect         = dk_geom->dkg_nsect;
668        DiskDrive->APC  = dk_geom->dkg_apc;
669        DiskDrive->RPM  = dk_geom->dkg_rpm;
670        DiskDrive->IntrLv       = dk_geom->dkg_intrlv;
671    }
672    if (dk_type) {
673        DiskDrive->PhySect      = dk_type->dkt_hsect;
674        DiskDrive->PROMRev      = dk_type->dkt_promrev;
675    }
676    if (dk_info) {
677#if     defined(DKI_HEXUNIT)
678        if (FLAGS_ON(dk_info->dki_flags, DKI_HEXUNIT))
679            DiskDrive->Flags |= DF_HEXUNIT;
680#endif  /* DKI_HEXUNIT */
681    }
682    DiskDrive->SecSize  = SECSIZE;
683
684    DiskCtlr                    = GetDiskCtlrDevice(DevData, dk_info, dk_conf);
685
686    DevInfo->DevSpec            = (caddr_t *) DiskDrive;
687    DevInfo->Master             = DiskCtlr;
688
689    return(DevInfo);
690}
691
692/*
693 * Query and learn about a disk.
694 */
695extern DevInfo_t *ProbeDiskDriveGeneric(disktype, name, DevData, DevDefine)
696    /*ARGSUSED*/
697    int                         disktype;
698    char                       *name;
699    DevData_t                  *DevData;
700    DevDefine_t                *DevDefine;
701{
702    DevInfo_t                  *DevInfo;
703    DKinfo                     *dk_info = NULL;
704    DKconf                     *dk_conf = NULL;
705    DKtype                     *dk_type = NULL;
706    DKlabel                    *dk_label = NULL;
707    DKgeom                     *dk_geom = NULL;
708    char                       *rfile;
709    int                         d;
710
711    if (!name)
712        return((DevInfo_t *) NULL);
713
714#if     defined(HAVE_IPI)
715    /*
716     * XXX - Kludge for IPI "id" disks.
717     */
718    if (EQ(DevData->DevName, "id")) {
719        static char             Buf[BUFSIZ];
720
721        (void) sprintf(Buf, "%s%3.3x",
722                       DevData->DevName, DevData->DevUnit);
723        name = Buf;
724    }
725#endif  /* HAVE_IPI */
726
727    if (disktype == DKT_CDROM)
728        rfile = GetRawFile(name, NULL);
729    else {
730        if (stat(rfile = GetRawFile(name, NULL), &StatBuf) != 0)
731            /*
732             * Get the name of the whole disk raw device.
733             */
734            rfile = GetRawFile(name, "c");
735    }
736
737    if ((d = open(rfile, O_RDONLY)) < 0) {
738        if (Debug) Error("%s: Cannot open for reading: %s.", rfile, SYSERR);
739        /*
740         * If we know for sure this drive is present and we
741         * know something about it, then create a minimal device.
742         */
743        if (errno == EBUSY || errno == EIO ||
744            ((DevDefine->Model || DevDefine->Desc) &&
745             FLAGS_ON(DevData->Flags, DD_IS_ALIVE))) {
746            DevInfo = NewDevInfo((DevInfo_t *) NULL);
747            DevInfo->Name = strdup(name);
748            DevInfo->Unit = DevData->DevUnit;
749            DevInfo->Master = MkMasterFromDevData(DevData);
750            DevInfo->Type = DT_DISKDRIVE;
751            DevInfo->Model = DevDefine->Model;
752            DevInfo->ModelDesc = DevDefine->Desc;
753            return(DevInfo);
754        } else
755            return((DevInfo_t *) NULL);
756    }
757
758    if ((dk_conf = GETdk_conf(d, rfile, disktype)) == NULL)
759        if (Debug) Error("%s: get dk_conf failed.", rfile);
760
761    if ((dk_info = GETdk_info(d, rfile)) == NULL)
762        if (Debug) Error("%s: get dk_info failed.", rfile);
763
764    if ((dk_geom = GETdk_geom(d, rfile, disktype)) == NULL)
765        if (Debug) Error("%s: get dk_geom failed.", rfile);
766
767    if ((dk_label = GETdk_label(d, rfile, dk_info, disktype)) == NULL)
768        if (Debug) Error("%s: get dk_label failed.", rfile);
769
770    /*
771     * Not all controllers support dk_type
772     */
773    dk_type = GETdk_type(d, rfile);
774
775    close(d);
776
777    if (!(DevInfo = dkToDevInfo(name, disktype, DevData,
778                                dk_info, dk_label,
779                                dk_conf, dk_geom, dk_type))) {
780        Error("%s: Cannot convert DiskDrive information.", name);
781        return((DevInfo_t *) NULL);
782    }
783
784    return(DevInfo);
785}
786
787/*
788 * Probe normal disk drive by calling Generic probe routine.
789 */
790extern DevInfo_t *ProbeDiskDrive(name, DevData, DevDefine)
791    char                       *name;
792    DevData_t                  *DevData;
793    DevDefine_t                *DevDefine;
794{
795    return(ProbeDiskDriveGeneric(DKT_GENERIC, name, DevData, DevDefine));
796}
797
798/*
799 * Probe CDROM disk drive by calling Generic probe routine.
800 */
801extern DevInfo_t *ProbeCDROMDrive(name, DevData, DevDefine)
802    char                       *name;
803    DevData_t                  *DevData;
804    DevDefine_t                *DevDefine;
805{
806    return(ProbeDiskDriveGeneric(DKT_CDROM, name, DevData, DevDefine));
807}
808
809/*
810 * Probe a tape device
811 * XXX - this loses if somebody's using the tape, as tapes are exclusive-open
812 * devices, and our open will therefore fail.
813 * This also loses if there's no tape in the drive, as the open will fail.
814 * The above probably applies to most other flavors of UNIX.
815 */
816extern DevInfo_t *ProbeTapeDrive(name, DevData, DevDefine)
817     /*ARGSUSED*/
818    char                       *name;
819    DevData_t                  *DevData;
820    DevDefine_t                *DevDefine;
821{
822    DevInfo_t                  *DevInfo;
823    char                       *file;
824    char                       *Model = NULL;
825    char                        rfile[BUFSIZ];
826    static char                 Buf[BUFSIZ];
827    struct mtget                mtget;
828    register char              *cp;
829    int                         d;
830
831    /*
832     * Don't use GetRawFile; that'll just stick an "r" in front of the
833     * device name, meaning it'll return the rewind-on-close device.
834     * Somebody may have left the tape positioned somewhere other than
835     * at the BOT to, for example, write a dump there later in the
836     * evening; it'd be rather rude to reposition it out from under them.
837     *
838     * The above probably applies to most other flavors of UNIX.
839     */
840    if (!name)
841        file = NULL;
842    else {
843        (void) sprintf(rfile, "/dev/nr%s", name);
844        file = rfile;
845    }
846
847    if ((d = open(file, O_RDONLY)) < 0) {
848        if (Debug)
849            Error("%s Cannot open for read: %s.", file, SYSERR);
850
851        /*
852         * --RECURSE--
853         * If we haven't tried the "mt" name yet, try it now
854         */
855        if (strncmp(name, MTNAME, strlen(MTNAME)) != 0) {
856            (void) sprintf(Buf, "%s%d", MTNAME, DevData->DevUnit);
857            DevInfo = ProbeTapeDrive(Buf, DevData, DevDefine);
858            if (DevInfo)
859                return(DevInfo);
860        }
861
862        /*
863         * If we know for sure this drive is present and we
864         * know something about it, then create a minimal device.
865         */
866        if ((DevDefine->Model || DevDefine->Desc) &&
867            FLAGS_ON(DevData->Flags, DD_IS_ALIVE)) {
868            DevInfo = NewDevInfo((DevInfo_t *) NULL);
869            /*
870             * Recreate name from devdata since we might have had to
871             * call ourself with name "rmt?"
872             */
873            (void) sprintf(Buf, "%s%d", DevData->DevName,
874                           DevData->DevUnit);
875            DevInfo->Name = strdup(Buf);
876            DevInfo->Unit = DevData->DevUnit;
877            DevInfo->Master = MkMasterFromDevData(DevData);
878            DevInfo->Type = DT_TAPEDRIVE;
879            DevInfo->Model = DevDefine->Model;
880            DevInfo->ModelDesc = DevDefine->Desc;
881            return(DevInfo);
882        } else
883            return((DevInfo_t *) NULL);
884    }
885
886    if (ioctl(d, MTIOCGET, &mtget) != 0) {
887        Error("%s: Cannot extract tape status: %s.", file, SYSERR);
888        return((DevInfo_t *) NULL);
889    }
890
891    (void) close(d);
892
893    cp = GetTapeModel(mtget.mt_type);
894    if (cp)
895        Model = strdup(cp);
896    else
897        Model = "unknown";
898
899    /*
900     * Create and set device info
901     */
902    DevInfo = NewDevInfo(NULL);
903    DevInfo->Name = strdup(name);
904    DevInfo->Type = DT_TAPEDRIVE;
905    if (Model)
906        DevInfo->Model = Model;
907    else
908        DevInfo->Model = DevDefine->Model;
909    DevInfo->ModelDesc = DevDefine->Desc;
910    DevInfo->Unit = DevData->DevUnit;
911    DevInfo->Master = MkMasterFromDevData(DevData);
912
913    return(DevInfo);
914}
915
916/*
917 * Query and learn about a device attached to an Auspex Storage Processor.
918 * They'll show up as "ad" in the Mainbus info structure, but that
919 * merely reflects the way the slots are set up in the config file.
920 * We need to find out what type of device it is at this particular
921 * instant (it's subject to change - perhaps even while we're running,
922 * but there's not a heck of a lot we can do about that).
923 *
924 * We do that by trying it as a CD-ROM first, then as a disk, then as
925 * a tape; that loses if it's a tape and somebody's using it, but
926 * tapes on most if not all UNIX systems can't be probed by us if
927 * somebody's using it.
928 * The reason why we try it first as a CD-ROM is that if the CD has a
929 * partition table, the Auspex driver lets you open the partitions as
930 * if it were a disk.
931 */
932extern DevInfo_t *ProbeSPDrive(name, DevData, DevDefine)
933     /*ARGSUSED*/
934    char                       *name;
935    DevData_t                  *DevData;
936    DevDefine_t                *DevDefine;
937{
938    DevInfo_t                  *thedevice;
939    char                        devname[BUFSIZ];
940
941    /*
942     * Try it first as a CD-ROM.
943     */
944    (void) sprintf(devname, "acd%d", DevData->DevUnit);
945    DevData->DevName = "acd";
946    DevDefine->Model = "CD-ROM";
947    if (thedevice = ProbeCDROMDrive(devname, DevData, DevDefine))
948        return(thedevice);
949
950    /*
951     * Not a CD-ROM.  Try a disk.
952     */
953    (void) sprintf(devname, "ad%d", DevData->DevUnit);
954    DevData->DevName = "ad";
955    DevDefine->Model = NULL;
956    if (thedevice = ProbeDiskDrive(devname, DevData, DevDefine))
957        return(thedevice);
958
959    /*
960     * Not a disk.  Try a tape.
961     */
962    (void) sprintf(devname, "ast%d", DevData->DevUnit);
963    DevData->DevName = "ast";
964    if (thedevice = ProbeTapeDrive(devname, DevData, DevDefine))
965        return(thedevice);
966
967    /*
968     * None of the above.  Who knows?
969     */
970    return((DevInfo_t *) NULL);
971}
972
973#if     defined(HAVE_SUNROMVEC)
974/*
975 * Be backwards compatible with pre-4.1.2 code
976 */
977#include <mon/sunromvec.h>
978#if     defined(OPENPROMS) && !(defined(ROMVEC_VERSION) && \
979                                (ROMVEC_VERSION == 0 || ROMVEC_VERSION == 1))
980#define v_mon_id op_mon_id
981#endif
982#endif  /* HAVE_SUNROMVEC */
983
984/*
985 * Get ROM Version number
986 *
987 * If "romp" is "defined" (in <mon/sunromvec.h>), then take that
988 * as the address of the kernel pointer to "rom" (struct sunromvec).
989 * Otherwise, nlist "romp" from the kernel.
990 */
991extern char *GetRomVerSun()
992{
993    static char                 RomRev[16];
994    struct nlist               *nlptr;
995#if     defined(HAVE_SUNROMVEC)
996    static struct sunromvec     Rom;
997    kvm_t                      *kd;
998#if     !defined(romp)
999    struct sunromvec           *romp;
1000
1001    if (!(kd = KVMopen()))
1002        return((char *) NULL);
1003
1004    if ((nlptr = KVMnlist(kd, RomVecSYM, (struct nlist *)NULL, 0)) == NULL)
1005        return((char *) NULL);
1006
1007    if (CheckNlist(nlptr))
1008        return((char *) NULL);
1009
1010    /*
1011     * Read the kernel pointer to the sunromvec structure.
1012     */
1013    if (KVMget(kd, (u_long) nlptr->n_value, (char *) &romp,
1014               sizeof(romp), KDT_DATA)) {
1015        if (Debug) Error("Cannot read sunromvec pointer from kernel.");
1016        return((char *) NULL);
1017    }
1018
1019#else   /* romp */
1020
1021    if (!(kd = KVMopen()))
1022        return((char *) NULL);
1023
1024#endif  /* romp */
1025
1026    /*
1027     * Read the sunromvec structure from the kernel
1028     */
1029    /*SUPPRESS 25*/
1030    if (KVMget(kd, (u_long) romp, (char *) &Rom,
1031               sizeof(struct sunromvec), KDT_DATA)) {
1032        if (Debug) Error("Cannot read sunromvec from kernel.");
1033        return((char *) NULL);
1034    }
1035
1036#if     !defined(romp)
1037
1038    /*
1039     * XXX Hardcoded values
1040     */
1041    (void) sprintf(RomRev, "%d.%d", Rom.v_mon_id >> 16, Rom.v_mon_id & 0xFFFF);
1042
1043#else   /* romp */
1044
1045    /*
1046     * Read the version string from the address indicated by Rom.v_mon_id.
1047     */
1048    if (KVMget(kd, (u_long) Rom.v_mon_id, RomRev,
1049               sizeof(RomRev), KDT_STRING)) {
1050        if (Debug) Error("Cannot read rom revision from kernel.");
1051        return((char *) NULL);
1052    }
1053#endif  /* romp */
1054
1055    KVMclose(kd);
1056
1057#endif  /* HAVE_SUNROMVEC */
1058
1059    return((RomRev[0]) ? RomRev : (char *) NULL);
1060}
Note: See TracBrowser for help on using the repository browser.