home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume26 / sysinfo-1.0 / part01 / os-ultrix.c < prev    next >
C/C++ Source or Header  |  1993-04-10  |  19KB  |  872 lines

  1. /*
  2.  * Copyright (c) 1992 Michael A. Cooper.
  3.  * This software may be freely distributed provided it is not sold for 
  4.  * profit and the author is credited appropriately.
  5.  */
  6.  
  7. #ifndef lint
  8. static char *RCSid = "$Header: /src/common/usc/bin/sysinfo/RCS/os-ultrix.c,v 1.14 1992/04/26 23:32:06 mcooper Exp $";
  9. #endif
  10.  
  11. /*
  12.  * $Log: os-ultrix.c,v $
  13.  * Revision 1.14  1992/04/26  23:32:06  mcooper
  14.  * Add Copyright notice
  15.  *
  16.  * Revision 1.13  1992/04/17  23:27:51  mcooper
  17.  * Add support for ROM Version information (Sun only for now).
  18.  *
  19.  * Revision 1.12  1992/04/17  01:07:59  mcooper
  20.  * More de-linting
  21.  *
  22.  * Revision 1.11  1992/04/16  19:56:24  mcooper
  23.  * De-linting stuff.
  24.  *
  25.  * Revision 1.10  1992/04/15  02:04:16  mcooper
  26.  * Change GetMemoryStr() to GetMemory().
  27.  *
  28.  * Revision 1.9  1992/03/31  02:22:03  mcooper
  29.  * Fix failed return value from CheckNlist().
  30.  *
  31.  * Revision 1.8  1992/03/31  01:55:17  mcooper
  32.  * Use new CheckNlist to check nlist success.
  33.  *
  34.  * Revision 1.7  1992/03/31  00:15:09  mcooper
  35.  * Add error check for nlist.n_type.
  36.  *
  37.  * Revision 1.6  1992/03/22  00:20:10  mcooper
  38.  * Major cleanup and re-org.
  39.  *
  40.  * Revision 1.5  1992/03/09  01:07:50  mcooper
  41.  * Add support for determining system model type.
  42.  *
  43.  * Revision 1.4  1992/03/08  23:08:41  mcooper
  44.  * - Add new set_macinfo_packetfilter().
  45.  * - Remove unneeded get_bus().
  46.  *
  47.  * Revision 1.3  1992/03/08  04:57:09  mcooper
  48.  * Set DT_TAPEDRIVE in probe_tapedrive().
  49.  *
  50.  * Revision 1.2  1992/03/08  01:11:39  mcooper
  51.  * Add tape drive support.
  52.  *
  53.  * Revision 1.1  1992/03/06  18:35:40  mcooper
  54.  * Initial revision
  55.  *
  56.  */
  57.  
  58. /*
  59.  * Ultrix specific functions
  60.  */
  61.  
  62. #include <stdio.h>
  63. #include "system.h"
  64. #include "defs.h"
  65.  
  66. #include <fcntl.h>
  67. #include <nlist.h>
  68. #include <fstab.h>
  69. #include <sys/types.h>
  70. #include <sys/param.h>
  71. #include <sys/fs.h>
  72. #include <sys/ioctl.h>
  73. #include <sys/buf.h>
  74. #include <sys/stat.h>
  75.  
  76. #include <machine/cpuconf.h>
  77.  
  78. #include <sys/devio.h>
  79. #include <sys/mtio.h>
  80.  
  81. #include "info-ultrix.h"
  82.  
  83. #if    defined(HAVE_UBA)
  84. /*
  85.  * UBA (UniBus Adapter) specific code
  86.  */
  87. #include <io/uba/ubavar.h>
  88.  
  89. /*
  90.  * Probe specific structure
  91.  */
  92. struct _probespec {
  93.     struct uba_device        *uba_device;
  94. };
  95. typedef struct _probespec PROBESPEC;
  96.  
  97. #define DV_SIZE        (sizeof(struct uba_device))
  98. #define CR_SIZE        (sizeof(struct uba_ctlr))
  99.  
  100. /*
  101.  * Build a device tree by searching Unibus Adapters
  102.  */
  103. static int BuildUBA(TreePtr)
  104.     DEVICE               **TreePtr;
  105. {
  106.     extern struct nlist     UniBusNL[];
  107.     static struct uba_device     Device;
  108.     static struct uba_ctlr     Ctlr;
  109.     static char         CtlrName[BUFSIZ], DevName[BUFSIZ];
  110.     u_long             Addr, DeviceAddr;
  111.     static DEVDATA         DevData;
  112.     static PROBESPEC        ProbeSpec;
  113.     DEVICE                *dev;
  114.     kvm_t               *kd;
  115.     int             cnum;
  116.  
  117.     /*
  118.      * Read table address from kernel
  119.      */
  120.     if (!(kd = KVM_open(UniBusNL))) {
  121.     if (Debug) Error("Cannot read unibus device table from kernel.");
  122.     return(-1);
  123.     }
  124.  
  125.     /*
  126.      * See if we got a valid entry
  127.      */
  128.     if (CheckNlist(&UniBusNL[0]))
  129.     return(-1);
  130.  
  131.     /*
  132.      * Read each device table entry.  A NULL device.ui_driver
  133.      * indicates that we're at the end of the table.
  134.      */
  135.     for (DeviceAddr = UniBusNL[0].n_value; DeviceAddr; 
  136.      DeviceAddr += DV_SIZE) {
  137.  
  138.     /*
  139.      * Read this device
  140.      */
  141.     if (KVM_read(kd, DeviceAddr, (char *) &Device, DV_SIZE)) {
  142.         if (Debug) 
  143.         Error("Cannot read unibus device from address 0x%x.", 
  144.               DeviceAddr);
  145.         KVM_close(kd);
  146.         return(-1);
  147.     }
  148.  
  149.     /*
  150.      * See if we're done.
  151.      */
  152.     if (!Device.ui_driver)
  153.         break;
  154.  
  155.     /*
  156.      * Get the device name
  157.      */
  158.     DevName[0] = C_NULL;
  159.     if (Addr = (u_long) Device.ui_devname) {
  160.         if (KVM_read(kd, Addr, (char *) DevName, sizeof(DevName))) {
  161.         if (Debug)
  162.             Error("Cannot read device name from address 0x%x.", Addr);
  163.         continue;
  164.         }
  165.     }
  166.  
  167.     /*
  168.      * Get the controller info
  169.      */
  170.     CtlrName[0] = C_NULL;
  171.     cnum = -1;
  172.     if (Addr = (u_long) Device.ui_mi) {
  173.         if (KVM_read(kd, Addr, (char *) &Ctlr, CR_SIZE)) {
  174.         if (Debug) 
  175.             Error("Cannot read controller from address 0x%x.", Addr);
  176.         } else {
  177.         /*
  178.          * Get the controller name
  179.          */
  180.         if (Addr = (u_long) Ctlr.um_ctlrname) {
  181.             if (KVM_read(kd, Addr, CtlrName, sizeof(CtlrName))) {
  182.             if (Debug)
  183.                 Error(
  184.           "Cannot read controller name from driver address 0x%x.",
  185.                   Addr);
  186.             continue;
  187.             }
  188.         }
  189.         cnum = Ctlr.um_ctlr;
  190.         }
  191.     }
  192.  
  193.     if (Debug)
  194.         printf("build_unibus(): Found '%s' on '%s'.\n", DevName, CtlrName);
  195.  
  196.     /* Make sure devdata is clean */
  197.     bzero(&DevData, sizeof(DEVDATA));
  198.  
  199.     /* Set what we know */
  200.     if (DevName[0]) {
  201.         DevData.dd_devname = strdup(DevName);
  202.         DevData.dd_devunit = Device.ui_unit;
  203.     }
  204.     if (CtlrName[0]) {
  205.         DevData.dd_ctlrname = strdup(CtlrName);
  206.         DevData.dd_ctlrunit = cnum;
  207.     }
  208.  
  209.     /* 
  210.      * Unibus devices should always exist.
  211.      */
  212.     if (Device.ui_alive)
  213.         DevData.dd_flags |= DD_IS_ALIVE;
  214.  
  215.     ProbeSpec.uba_device = &Device;
  216.  
  217.     /* Probe and add device */
  218.     if (dev = (DEVICE *) ProbeDevice(&DevData, TreePtr, &ProbeSpec))
  219.         AddDevice(dev, TreePtr);
  220.     }
  221.  
  222.     KVM_close(kd);
  223.  
  224.     return(0);
  225. }
  226. #endif    /* HAVE_UBA */
  227.  
  228. /*
  229.  * Build list of Ultrix devices
  230.  */
  231. extern int BuildDevicesUltrix(TreePtr)
  232.     DEVICE               **TreePtr;
  233. {
  234.     int                Found = 1;
  235.  
  236. #if    defined(HAVE_UBA)
  237.     if (BuildUBA(TreePtr) == 0)
  238.     Found = 0;
  239. #endif    /* HAVE_UBA */
  240.  
  241.     return(Found);
  242. }
  243.  
  244. /*
  245.  * Get Device Info structure from device.
  246.  */
  247. static struct devget *GETdevget(File, FileD)
  248.     char               *File;
  249.     int             FileD;
  250. {
  251.     static struct devget     devget;
  252.  
  253.     if (ioctl(FileD, DEVIOCGET, &devget) == SYSFAIL) {
  254.     if (Debug) Error("%s: ioctl DEVIOCGET failed: %s.", File, SYSERR);
  255.     return((struct devget *) NULL);
  256.     }
  257.  
  258.     return(&devget);
  259. }
  260.  
  261. /*
  262.  * Get Device Geometry structure from device.
  263.  */
  264. static DEVGEOMST *GETdevgeom(File, FileD)
  265.     char               *File;
  266.     int             FileD;
  267. {
  268.     static DEVGEOMST         devgeom;
  269.  
  270.     if (ioctl(FileD, DEVGETGEOM, &devgeom) == SYSFAIL) {
  271.     if (Debug) Error("%s: ioctl DEVGETGEOM failed: %s.", File, SYSERR);
  272.     return((DEVGEOMST *) NULL);
  273.     }
  274.  
  275.     return(&devgeom);
  276. }
  277.  
  278. /*
  279.  * Lookup a category type.
  280.  */
  281. static char *GetCategory(val)
  282.     int                val;
  283. {
  284.     extern NAMETAB            Categorys[];
  285.     register int         i;
  286.  
  287.     for (i = 0; Categorys[i].name; ++i)
  288.     if (val == Categorys[i].value)
  289.         return(Categorys[i].name);
  290.  
  291.     return((char *) NULL);
  292. }
  293.  
  294. /*
  295.  * Convert a 'devget' to a 'device'.
  296.  */
  297. static DEVICE *devgetToDEVICE(DevGet, DevData, ProbeSpec)
  298.     struct devget           *DevGet;
  299.     DEVDATA               *DevData;
  300.     PROBESPEC               *ProbeSpec;
  301. {
  302.     DEVICE               *Device;
  303.  
  304.     if (!(Device = NewDevice(NULL)))
  305.     return(Device);
  306.  
  307.     Device->dv_name    = strdup(MkDevName(DevData->dd_devname,
  308.                        DevData->dd_devunit));
  309.     Device->dv_model    = strdup(DevGet->device);
  310.     Device->dv_desc    = GetCategory(DevGet->category);
  311.     Device->dv_unit    = DevGet->unit_num;
  312.  
  313.     /*
  314.      * Set master/controller info
  315.      */
  316.     if (Device->dv_master = MkMasterFromDevData(DevData))
  317.     Device->dv_master->dv_model = strdup(DevGet->interface);
  318.  
  319.     return(Device);
  320. }
  321.  
  322. /*
  323.  * Check a device by trying to perform a devget on it.
  324.  */
  325. static struct devget *CheckDevice(File)
  326.     char               *File;
  327. {
  328.     struct devget           *DevGet;
  329.     int                d;
  330.  
  331.     if ((d = open(File, O_RDONLY|O_NDELAY)) < 0) {
  332.     if (Debug) Error("%s: Cannot open: %s.", File, SYSERR);
  333.     return((struct devget *) NULL);
  334.     }
  335.  
  336.     /*
  337.      * Get generic device info
  338.      */
  339.     if (!(DevGet = GETdevget(File, d))) {
  340.     if (Debug) Error("%s: GETdevget failed.", File);
  341.     close(d);
  342.     return((struct devget *) NULL);
  343.     }
  344.  
  345.     close(d);
  346.  
  347.     return(DevGet);
  348. }
  349.  
  350. /*
  351.  * Retrieve disk partition information from a device file.
  352.  */
  353. static struct pt *ExtractDiskPart(File)
  354.     char               *File;
  355. {
  356.     static struct pt        pt;
  357.     int                d;
  358.  
  359.     if ((d = open(File, O_RDONLY|O_NDELAY)) < 0) {
  360.     if (Debug) Error("%s: open failed: %s.", File, SYSERR);
  361.     return((struct pt *) NULL);
  362.     }
  363.  
  364.     if (ioctl(d, DIOCGETPT, &pt) < 0) {
  365.     if (Debug) Error("%s: ioctl DIOCGETPT failed: %s.", File, SYSERR);
  366.     close(d);
  367.     return((struct pt *) NULL);
  368.     }
  369.  
  370.     close(d);
  371.  
  372.     return(&pt);
  373. }
  374.  
  375. /*
  376.  * Get the mount point for a filesystem.
  377.  */
  378. static char *GetMountInfo(Name, Part)
  379.     char               *Name;
  380.     char               *Part;
  381. {
  382.     char               *File;
  383.     struct fstab           *fstab;
  384.  
  385.     File = GetCharFile(Name, Part);
  386.     if (fstab = getfsspec(File)) {
  387.     if (strcmp(fstab->fs_type, FSTAB_SW) == 0)
  388.         return("swap");
  389.     return(fstab->fs_file);
  390.     }
  391.  
  392.     return((char *) NULL);
  393. }
  394.  
  395. /*
  396.  * Get the partition information for a disk device.
  397.  */
  398. static DISKPART *GetPartInfo(Name, Device)
  399.     char                *Name;
  400.     DEVICE               *Device;
  401. {
  402.     static DISKPART            diskpart;
  403.     static char            Buf[BUFSIZ], part[2];
  404.     register DISKPART           *pdp, *dp;
  405.     register char           *p;
  406.     DISKPART               *base = NULL;
  407.     struct pt               *pt;
  408.     register int        i;
  409.  
  410.     /*
  411.      * First get the partition info.
  412.      */
  413.     (void) sprintf(Buf, "/dev/r%sa", Name);
  414.     if (!(pt = ExtractDiskPart(Buf)))
  415.     return((DISKPART *) NULL);
  416.  
  417.     part[1] = C_NULL;
  418.  
  419.     /*
  420.      * Now deal with each partition.
  421.      */
  422.     for (i = 0; i < MAX_DISK_PARTS; ++i) {
  423.     /* Ignore partitions that have no size */
  424.     if (!pt->pt_part[i].pi_nblocks)
  425.         continue;
  426.  
  427.     part[0] = 'a' + i;
  428.  
  429.     /* Make a clean slate */
  430.     bzero((char *) &diskpart, sizeof(DISKPART));
  431.  
  432.     /* Fill in what we know */
  433.     diskpart.dp_name = strdup(part);
  434.     diskpart.dp_stsect = pt->pt_part[i].pi_blkoff;
  435.     diskpart.dp_nsect = pt->pt_part[i].pi_nblocks;
  436.  
  437.     /* 
  438.      * Get the mount point name.
  439.      * If this is the "b" partition on the 
  440.      * root device, then assume it's swap 
  441.      */
  442.     if (p = GetMountInfo(Name, part))
  443.         diskpart.dp_mnt = strdup(p);
  444.     else if (Device->dv_unit == 0 && strcmp(part, "b") == 0)
  445.         diskpart.dp_mnt = "swap";
  446.  
  447.     /*
  448.      * Add this partition to the linked list.
  449.      */
  450.     if (base) {
  451.         for (pdp = base; pdp && pdp->dp_nxt; pdp = pdp->dp_nxt);
  452.         pdp->dp_nxt = NewDiskPart(&diskpart);
  453.     } else {
  454.         base = NewDiskPart(&diskpart);
  455.     }
  456.     }
  457.  
  458.     return(base);
  459. }
  460.  
  461. /*
  462.  * Probe a disk drive
  463.  */
  464. extern DEVICE *ProbeDiskDrive(Name, DevData, DevDataTab, ProbeSpec)
  465.     char               *Name;
  466.     DEVDATA               *DevData;
  467.     DEVDATATAB               *DevDataTab;
  468.     PROBESPEC               *ProbeSpec;
  469. {
  470.     DEVICE               *Device;
  471.     DISKDRIVE               *DiskDrive;
  472.     DEVGEOMST               *DevGeom;
  473.     struct devget           *DevGet;
  474.     char               *File;
  475.     int                Desc;
  476.  
  477.     if (!Name)
  478.     return((DEVICE *) NULL);
  479.  
  480.     File = GetRawFile(Name, "c");
  481.     if ((Desc = open(File, O_RDONLY|O_NDELAY)) < 0) {
  482.     if (Debug) Error("%s: open failed: %s.", File, SYSERR);
  483.     /*
  484.      * If we know for sure this drive is present and we
  485.      * know something about it, then create a minimal device.
  486.      */
  487.     if ((DevDataTab->ddt_model || DevDataTab->ddt_desc) &&
  488.         FLAGS_ON(DevData->dd_flags, DD_IS_ALIVE)) {
  489.         Device = NewDevice((DEVICE *) NULL);
  490.         Device->dv_name = strdup(Name);
  491.         Device->dv_unit = DevData->dd_devunit;
  492.         Device->dv_master = MkMasterFromDevData(DevData);
  493.         Device->dv_type = DT_DISKDRIVE;
  494.         Device->dv_model = DevDataTab->ddt_model;
  495.         Device->dv_desc = DevDataTab->ddt_desc;
  496.         return(Device);
  497.     } else
  498.         return((DEVICE *) NULL);
  499.     }
  500.  
  501.     /*
  502.      * Get generic device info
  503.      */
  504.     if (!(DevGet = GETdevget(File, Desc))) {
  505.     if (Debug) Error("%s: GETdevget failed.", File);
  506.     close(Desc);
  507.     return((DEVICE *) NULL);
  508.     }
  509.  
  510.     /*
  511.      * Get geometry of device
  512.      */
  513.     if (!(DevGeom = GETdevgeom(File, Desc))) {
  514.     if (Debug) Error("%s: get_geomst failed.", File);
  515.     }
  516.  
  517.     close(Desc);
  518.  
  519.     /*
  520.      * Convert devget info to a device struct
  521.      */
  522.     if (!(Device = devgetToDEVICE(DevGet, DevData, ProbeSpec))) {
  523.     if (Debug) Error("%s: Cannot convert devget to device.");
  524.     return((DEVICE *) NULL);
  525.     }
  526.  
  527.     /*
  528.      * Disks should be on disk controllers.
  529.      */
  530.     if (Device->dv_master)
  531.     Device->dv_master->dv_type = DT_DISKCTLR;
  532.  
  533.     /*
  534.      * Set the disk drive specific info
  535.      */
  536.  
  537.     if ((DiskDrive = NewDiskDrive(NULL)) == NULL) {
  538.     Error("Cannot create new diskdrive entry.");
  539.     return((DEVICE *) NULL);
  540.     }
  541.  
  542.     Device->dv_type         = DT_DISKDRIVE;
  543.     if (DevGet->device)
  544.     DiskDrive->dd_label     = strdup(DevGet->device);
  545.  
  546.     /*
  547.      * Convert Geometry
  548.      */
  549.     if (DevGeom) {
  550.     /*
  551.      * If this is a removable device, indicate so.
  552.      */
  553.     if (FLAGS_ON(DevGeom->geom_info.attributes, DEVGEOM_REMOVE)) {
  554.         if (Device->dv_desc) {
  555.         char Buf[BUFSIZ];
  556.  
  557.         (void) sprintf(Buf, "Removable %s", Device->dv_desc);
  558.         (void) free(Device->dv_desc);
  559.         Device->dv_desc = strdup(Buf);
  560.         } else {
  561.         Device->dv_desc = "Removable disk drive";
  562.         }
  563.     }
  564.  
  565.     DiskDrive->dd_unit     = DevGet->unit_num;
  566.     DiskDrive->dd_slave     = DevGet->slave_num;
  567.     DiskDrive->dd_part     = GetPartInfo(Name, Device);
  568.     DiskDrive->dd_dcyl     = DevGeom->geom_info.ncylinders;
  569.     DiskDrive->dd_heads     = DevGeom->geom_info.ntracks;
  570.     DiskDrive->dd_sect     = DevGeom->geom_info.nsectors;
  571.     DiskDrive->dd_secsize     = SECSIZE;
  572.  
  573.     if (DiskDrive->dd_dcyl && DiskDrive->dd_sect && DiskDrive->dd_heads) {
  574.         static char Buf[BUFSIZ];
  575.  
  576.         DiskDrive->dd_size = nsect_to_bytes(DiskDrive->dd_dcyl * 
  577.                         DiskDrive->dd_sect * 
  578.                         DiskDrive->dd_heads, 
  579.                         DiskDrive->dd_secsize);
  580.  
  581.         (void) sprintf(Buf, "%.2f MB capacity", 
  582.                (float) bytes_to_mbytes(DiskDrive->dd_size));
  583.         Device->dv_desc = strdup(Buf);
  584.     }
  585.     }
  586.     Device->dv_devspec = (caddr_t *) DiskDrive;
  587.  
  588.     return(Device);
  589. }
  590.  
  591. /*
  592.  * Lookup info about a tape drive.
  593.  */
  594. static char *GetTapeInfo(Flag)
  595.     int                Flag;
  596. {
  597.     extern NAMETAB        TapeInfo[];
  598.     static char            Buf[BUFSIZ];
  599.     register int        i;
  600.  
  601.     if (!Flag)
  602.     return((char *) NULL);
  603.  
  604.     Buf[0] = C_NULL;
  605.  
  606.     /*
  607.      * Values are flag bits and are appended together.
  608.      */
  609.     for (i = 0; TapeInfo[i].name; i++) {
  610.     if (Flag & TapeInfo[i].value) {
  611.         if (Buf[0]) {
  612.         (void) strcat(Buf, ", ");
  613.         (void) strcat(Buf, TapeInfo[i].name);
  614.         } else
  615.         (void) strcpy(Buf, TapeInfo[i].name);
  616.     }
  617.     }
  618.  
  619.     return(Buf);
  620. }
  621.  
  622. /*
  623.  * Probe a tape drive
  624.  */
  625. extern DEVICE *ProbeTapeDrive(Name, DevData, DevDataTab, ProbeSpec)
  626.     char               *Name;
  627.     DEVDATA               *DevData;
  628.     DEVDATATAB               *DevDataTab;
  629.     PROBESPEC               *ProbeSpec;
  630. {
  631.     struct devget           *DevGet;
  632.     DEVICE               *Device;
  633.     char               *File;
  634.     char               *p;
  635.     char                Buf[BUFSIZ];
  636.     register int        i;
  637.  
  638.     /*
  639.      * XXX Kludge Alert! ! !
  640.      *
  641.      * Ultrix tape device files are numbered independently of actual
  642.      * unit number.  Additionally, not all tape devices support the same
  643.      * set of minor devices types, so we can't look at the minor device 
  644.      * number.  
  645.      *
  646.      * The code below will open(), ioctl(), close() all tape
  647.      * devices between 0 and MAXTAPES until a matching unit number is found.
  648.      * This means that on systems with lots of tape drives, this can be 
  649.      * very slow.
  650.      */
  651.     for (i = 0; i < MAXTAPES; ++i) {
  652.     (void) sprintf(Buf, "/dev/nrmt%dh", i);
  653.     if ((DevGet = CheckDevice(Buf)) && 
  654.         (DevGet->unit_num == DevData->dd_devunit))
  655.         break;
  656.     }
  657.  
  658.     if (!DevGet) {
  659.     if (Debug) Error("%s: Cannot find device file.", Name);
  660.     return((DEVICE *) NULL);
  661.     }
  662.  
  663.     /*
  664.      * Convert devget info to a device struct
  665.      */
  666.     if (!(Device = devgetToDEVICE(DevGet, DevData, ProbeSpec))) {
  667.     if (Debug) Error("%s: Cannot convert devget to device.");
  668.     return((DEVICE *) NULL);
  669.     }
  670.  
  671.     /*
  672.      * Set our device type
  673.      */
  674.     Device->dv_type = DT_TAPEDRIVE;
  675.  
  676.     /*
  677.      * Get and add Tape Info
  678.      */
  679.     if (p = GetTapeInfo(DevGet->category_stat)) {
  680.     if (Device->dv_desc) {
  681.         (void) sprintf(Buf, "%s %s", p, Device->dv_desc);
  682.         free(Device->dv_desc);
  683.         Device->dv_desc = strdup(Buf);
  684.     } else {
  685.         Device->dv_desc = p;
  686.     }
  687.     }
  688.  
  689.     /*
  690.      * Tapes should be on tape controllers.
  691.      */
  692.     if (Device->dv_master)
  693.     Device->dv_master->dv_type = DT_TAPECTLR;
  694.  
  695.     return(Device);
  696. }
  697.  
  698. /*
  699.  * Get network type information
  700.  */
  701. static char *GetNetType(type)
  702.     int                type;
  703. {
  704.     extern NAMETAB        NetTypes[];
  705.     register int        i;
  706.  
  707.     for (i = 0; NetTypes[i].name; i++)
  708.     if (NetTypes[i].value == type)
  709.         return(NetTypes[i].name);
  710.  
  711.     return((char *) NULL);
  712. }
  713.  
  714.  
  715. #if    defined(HAVE_PACKETFILTER)
  716.  
  717. #include <sys/time.h>
  718. #include <net/pfilt.h>
  719.  
  720. #include <sys/socket.h>
  721. #include <net/if.h>
  722. #include <netinet/in.h>
  723. #include <netinet/if_ether.h>
  724.  
  725. /*
  726.  * Find and set the MAC info using the Packet Filter
  727.  */
  728. extern void SetMacInfoPacketFilter(DevName, Netif, Device)
  729.      char                *DevName;
  730.      NETIF                *Netif;
  731.      DEVICE               *Device;
  732. {
  733.     struct endevp        endevp;
  734.     struct ether_addr        ether_addr;
  735.     char                *ether_ntoa(), HostBuf[MAXHOSTNAMLEN+1];
  736.     char                *p;
  737.     int                 Desc;
  738.  
  739.     if (!DevName || !Netif)
  740.     return;
  741.  
  742.     /*
  743.      * Open this device using the packet filter
  744.      */
  745.     if ((Desc = pfopen(DevName, O_RDONLY)) < 0) {
  746.     if (Debug) Error("pfopen %s failed: %s.", DevName, SYSERR);
  747.     return;
  748.     }
  749.  
  750.     /*
  751.      * Retrieve info
  752.      */
  753.     if (ioctl(Desc, EIOCDEVP, &endevp) < 0) {
  754.     if (Debug) Error("ioctl EIOCDEVP of %s failed: %s.", DevName, SYSERR);
  755.     return;
  756.     }
  757.  
  758.     close(Desc);
  759.  
  760.     /*
  761.      * Convert address into ethers(5) format
  762.      */
  763.     bcopy((char *) endevp.end_addr,
  764.       (char *) ether_addr.ether_addr_octet,
  765.       endevp.end_addr_len);
  766.  
  767.     /*
  768.      * Set what we now know.
  769.      */
  770.     if (p = ether_ntoa(ðer_addr))
  771.     Netif->ni_macaddr = strdup(p);
  772.  
  773.     if (ether_ntohost(HostBuf, ðer_addr) == 0)
  774.     Netif->ni_macname = strdup(HostBuf);
  775.  
  776.     if (Device && (p = GetNetType(endevp.end_dev_type)))
  777.     Device->dv_desc = p;
  778. }
  779. #endif    /* HAVE_PACKETFILTER */
  780.  
  781. /*
  782.  * Get the system model name.  Ultrix keeps the system type
  783.  * in a kernel structure called cpusw as cpusw.system_type.
  784.  * The system types are defined in <machine/cpuconf.h>.
  785.  */
  786. extern char *GetModelName()
  787. {
  788.     extern NAMETAB        ModelTab[];
  789.     extern struct nlist        CpuSwNL[];
  790.     static struct cpusw            CpuSw;
  791.     register int        i;
  792.     kvm_t               *kd;
  793.  
  794.     if (!(kd = KVM_open(CpuSwNL))) {
  795.     if (Debug) Error("Cannot find cpusw symbol in kernel.");
  796.     return((char *) NULL);
  797.     }
  798.  
  799.     /*
  800.      * See if we got a valid entry
  801.      */
  802.     if (CheckNlist(&CpuSwNL[0]))
  803.     return((char *) NULL);
  804.  
  805.     if (KVM_read(kd, (u_long) CpuSwNL[0].n_value, (char *) &CpuSw,
  806.          sizeof(struct cpusw))) {
  807.     if (Debug) Error("Cannot read cpusw from kernel.");
  808.     return((char *) NULL);
  809.     }
  810.  
  811.     KVM_close(kd);
  812.  
  813.     for (i = 0; ModelTab[i].name; ++i)
  814.     if (ModelTab[i].value == CpuSw.system_type)
  815.         return(ModelTab[i].name);
  816.  
  817.     if (Debug)
  818.     printf("system model/type %d is unknown.\n", CpuSw.system_type);
  819.  
  820.     return((char *) NULL);
  821. }
  822.  
  823. /*
  824.  * Get kernel version string from kernel symbol "version".
  825.  */
  826. extern char *GetKernelVersionStr()
  827. {
  828.     return(GetKernelVersionFromVersion());
  829. }
  830.  
  831. /*
  832.  * Get amount of physical memory using kernel symbol "physmem".
  833.  */
  834. extern char *GetMemory()
  835. {
  836.     return(GetMemoryFromPhysmem());
  837. }
  838.  
  839. /*
  840.  * Get system serial number
  841.  */
  842. extern char *GetSerialNoStr()
  843. {
  844.     /* No support */
  845.     return((char *) NULL);
  846. }
  847.  
  848. /*
  849.  * Get name of OS
  850.  */
  851. extern char *GetOSNameStr()
  852. {
  853.     return(GetOSNameFromUname());
  854. }
  855.  
  856. /*
  857.  * Get version of OS
  858.  */
  859. extern char *GetOSVersionStr()
  860. {
  861.     return(GetOSVersionFromUname());
  862. }
  863.  
  864. /*
  865.  * Get ROM Version
  866.  */
  867. extern char *GetRomVer()
  868. {
  869.     /* No support */
  870.     return((char *) NULL);
  871. }
  872.