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

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