home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume26 / sysinfo-1.0 / part01 / os-next.c < prev    next >
C/C++ Source or Header  |  1993-04-10  |  12KB  |  531 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-next.c,v 1.10 1992/04/26 23:32:06 mcooper Exp $";
  9. #endif
  10.  
  11. /*
  12.  * $Log: os-next.c,v $
  13.  * Revision 1.10  1992/04/26  23:32:06  mcooper
  14.  * Add Copyright notice
  15.  *
  16.  * Revision 1.9  1992/04/17  23:27:51  mcooper
  17.  * Add support for ROM Version information (Sun only for now).
  18.  *
  19.  * Revision 1.8  1992/04/17  01:07:59  mcooper
  20.  * More de-linting
  21.  *
  22.  * Revision 1.7  1992/04/15  02:04:16  mcooper
  23.  * Change GetMemoryStr() to GetMemory().
  24.  *
  25.  * Revision 1.6  1992/03/31  02:22:03  mcooper
  26.  * Fix failed return value from CheckNlist().
  27.  *
  28.  * Revision 1.5  1992/03/31  01:55:17  mcooper
  29.  * Use new CheckNlist to check nlist success.
  30.  *
  31.  * Revision 1.4  1992/03/31  00:15:09  mcooper
  32.  * Add error check for nlist.n_type.
  33.  *
  34.  * Revision 1.3  1992/03/28  21:59:28  mcooper
  35.  * Implemented disk and netif device probing.
  36.  *
  37.  * Revision 1.2  1992/03/22  02:03:48  mcooper
  38.  * Add Build*NeXT*() functions.
  39.  *
  40.  * Revision 1.1  1992/03/22  01:04:34  mcooper
  41.  * Initial revision
  42.  *
  43.  */
  44.  
  45.  
  46. /*
  47.  * NeXT specific functions
  48.  */
  49.  
  50. #include <stdio.h>
  51. #include "system.h"
  52. #include "defs.h"
  53.  
  54. #include <nlist.h>
  55. #include <mntent.h>
  56. #include <nextdev/disk.h>
  57. #include <nextdev/busvar.h>
  58.  
  59. #define DV_SIZE        (sizeof(struct bus_device))
  60. #define DR_SIZE        (sizeof(struct bus_driver))
  61. #define CR_SIZE        (sizeof(struct bus_ctrl))
  62.  
  63. /*
  64.  * Build a device tree by searching NeXTBus
  65.  */
  66. static int BuildNeXTBus(TreePtr)
  67.     DEVICE               **TreePtr;
  68. {
  69.     extern struct nlist     NeXTBusNL[];
  70.     static struct bus_device     Device;
  71.     static struct bus_driver     Driver;
  72.     static struct bus_ctrl     Ctlr;
  73.     static char         CtlrName[BUFSIZ], DevName[BUFSIZ];
  74.     u_long             Addr, DeviceAddr;
  75.     static DEVDATA         DevData;
  76.     DEVICE                *Dev;
  77.     kvm_t               *kd;
  78.  
  79.     /*
  80.      * Read table address from kernel
  81.      */
  82.     if (!(kd = KVM_open(NeXTBusNL))) {
  83.     if (Debug) Error("Cannot read NeXTBus device table from kernel.");
  84.     return(-1);
  85.     }
  86.  
  87.     /*
  88.      * See if we got a valid entry
  89.      */
  90.     if (CheckNlist(&NeXTBusNL[0]))
  91.     return(-1);
  92.  
  93.     /*
  94.      * Read each device table entry.  A NULL device.bd_driver
  95.      * indicates that we're at the end of the table.
  96.      */
  97.     for (DeviceAddr = NeXTBusNL[0].n_value; DeviceAddr; 
  98.      DeviceAddr += DV_SIZE) {
  99.  
  100.     /*
  101.      * Read this device
  102.      */
  103.     if (KVM_read(kd, DeviceAddr, (char *) &Device, DV_SIZE)) {
  104.         if (Debug) 
  105.         Error("Cannot read NeXTbus device from address 0x%x.", 
  106.               DeviceAddr);
  107.         KVM_close(kd);
  108.         return(-1);
  109.     }
  110.  
  111.     /*
  112.      * See if we're done.
  113.      */
  114.     if (!Device.bd_driver)
  115.         break;
  116.  
  117.     /*
  118.      * Get the device name
  119.      */
  120.     DevName[0] = C_NULL;
  121.     if (Addr = (u_long) Device.bd_name) {
  122.         if (KVM_read(kd, Addr, (char *) DevName, sizeof(DevName))) {
  123.         if (Debug)
  124.             Error("Cannot read device name from address 0x%x.", Addr);
  125.         continue;
  126.         }
  127.     }
  128.  
  129.     /*
  130.      * Get the controller info
  131.      */
  132.     CtlrName[0] = C_NULL;
  133.     /*
  134.      * First read the controller structure in
  135.      */
  136.     if (Addr = (u_long) Device.bd_bc) {
  137.         if (KVM_read(kd, Addr, (char *) &Ctlr, CR_SIZE)) {
  138.         if (Debug) 
  139.             Error("Cannot read controller from address 0x%x.", Addr);
  140.         } else if (Addr = (u_long) Ctlr.bc_driver) {
  141.         /*
  142.          * Get the controller driver
  143.          */
  144.         if (KVM_read(kd, Addr, (char *) &Driver, DR_SIZE)) {
  145.             if (Debug)
  146.             Error(
  147.                 "Cannot read controller driver from address 0x%x.",
  148.                   Addr);
  149.             continue;
  150.         }
  151.         /*
  152.          * Read the name of the controller from the driver
  153.          */
  154.         if (!(Addr = (u_long) Driver.br_cname)) {
  155.             if (Debug)
  156.             Error("No name for controller at address 0x%x.",
  157.                   Ctlr.bc_driver);
  158.             continue;
  159.         }
  160.         if (KVM_read(kd, Addr, CtlrName, sizeof(CtlrName))) {
  161.             if (Debug)
  162.             Error("Read controller name failed (address 0x%x).",
  163.                   Addr);
  164.             continue;
  165.         }
  166.         }
  167.     }
  168.  
  169.     if (Debug)
  170.         printf("NeXTbus: Found '%s' on '%s'.\n", DevName, CtlrName);
  171.  
  172.     /* Make sure devdata is clean */
  173.     bzero(&DevData, sizeof(DEVDATA));
  174.  
  175.     /* Set what we know */
  176.     if (DevName[0]) {
  177.         DevData.dd_devname = strdup(DevName);
  178.         DevData.dd_devunit = Device.bd_unit;
  179.         DevData.dd_slave = Device.bd_slave;
  180.     }
  181.     if (CtlrName[0]) {
  182.         DevData.dd_ctlrname = strdup(CtlrName);
  183.         DevData.dd_ctlrunit = Ctlr.bc_ctrl;
  184.     }
  185.  
  186.     /* 
  187.      * NeXTbus devices should always exist.
  188.      */
  189.     if (Device.bd_alive)
  190.         DevData.dd_flags |= DD_IS_ALIVE;
  191.  
  192.     /* Probe and add device */
  193.     if (Dev = (DEVICE *) ProbeDevice(&DevData, TreePtr, NULL))
  194.         AddDevice(Dev, TreePtr);
  195.     }
  196.  
  197.     KVM_close(kd);
  198.  
  199.     return(0);
  200. }
  201.  
  202. /*
  203.  * Build list of NeXT devices
  204.  */
  205. extern int BuildDevicesNeXT(TreePtr)
  206.     DEVICE               **TreePtr;
  207. {
  208.     int                Found = 1;
  209.  
  210.     if (BuildNeXTBus(TreePtr) == 0)
  211.     Found = 0;
  212.  
  213.     return(Found);
  214. }
  215.  
  216. /*
  217.  * Get the system model name.  NeXT keeps the system type
  218.  * in a kernel variable called machine_type.
  219.  * The system types are defined in <next/scr.h>.
  220.  */
  221. extern char *GetModelName()
  222. {
  223.     extern NAMETAB        ModelTab[];
  224.     extern struct nlist        MachineTypeNL[];
  225.     u_char            MachineType;
  226.     register int        i;
  227.     kvm_t               *kd;
  228.  
  229.     if (!(kd = KVM_open(MachineTypeNL))) {
  230.     if (Debug) Error("Cannot find machine_type symbol in kernel.");
  231.     return((char *) NULL);
  232.     }
  233.  
  234.     /*
  235.      * See if we got a valid entry
  236.      */
  237.     if (CheckNlist(&MachineTypeNL[0]))
  238.     return((char *) NULL);
  239.  
  240.     if (KVM_read(kd, (u_long) MachineTypeNL[0].n_value, 
  241.          (char *) &MachineType, sizeof(MachineType))) {
  242.     if (Debug) Error("Cannot read \"%s\" from kernel.", 
  243.              GetNlName(MachineTypeNL[0]));
  244.     return((char *) NULL);
  245.     }
  246.  
  247.     KVM_close(kd);
  248.  
  249.     for (i = 0; ModelTab[i].name; ++i)
  250.     if (ModelTab[i].value == MachineType)
  251.         return(ModelTab[i].name);
  252.  
  253.     if (Debug)
  254.     printf("system model/type %d is unknown.\n", MachineType);
  255.  
  256.     return((char *) NULL);
  257. }
  258.  
  259. /*
  260.  * Get kernel version string using Mach HostInfo method
  261.  */
  262. extern char *GetKernelVersionStr()
  263. {
  264.     return(GetKernelVersionFromHostInfo());
  265. }
  266.  
  267. /*
  268.  * Get amount of physical memory using Mach HostInfo method
  269.  */
  270. extern char *GetMemory()
  271. {
  272.     return(GetMemoryFromHostInfo());
  273. }
  274.  
  275. /*
  276.  * Get application architecture name using Mach HostInfo method.
  277.  */
  278. extern char *GetAppArchName()
  279. {
  280.     return(GetAppArchFromHostInfo());
  281. }
  282.  
  283. /*
  284.  * Get kernel architecture name using Mach HostInfo method.
  285.  */
  286. extern char *GetKernArchName()
  287. {
  288.     return(GetKernArchFromHostInfo());
  289. }
  290.  
  291. /*
  292.  * Get system serial number
  293.  */
  294. extern char *GetSerialNoStr()
  295. {
  296.     /* No support */
  297.     return((char *) NULL);
  298. }
  299.  
  300. /*
  301.  * Get OS version using Mach HostInfo method.
  302.  */
  303. extern char *GetOSVersionStr()
  304. {
  305.     return(GetOSVersionFromHostInfo());
  306. }
  307.  
  308. /*
  309.  * Get filesystem mount info for a partition.
  310.  */
  311. static char *GetMountInfo(Name, Part)
  312.     char                *Name;
  313.     char                *Part;
  314. {
  315.     FILE                *mf;
  316.     struct mntent            *mntent;
  317.     char                *file;
  318.  
  319.     if (!Name)
  320.     return((char *) NULL);
  321.  
  322.     file = GetCharFile(Name, Part);
  323.  
  324.     if ((mf = setmntent(MNTTAB, "r")) == NULL) {
  325.     Error("%s: Cannot open for reading: %s.", MNTTAB, SYSERR);
  326.     return(NULL);
  327.     }
  328.  
  329.     while (mntent = getmntent(mf)) {
  330.     if (strcmp(mntent->mnt_fsname, file) == 0)
  331.         break;
  332.     }
  333.  
  334.     endmntent(mf);
  335.  
  336.     return((mntent) ? mntent->mnt_dir : (char *) NULL);
  337. }
  338.  
  339. /*
  340.  * Get disk partition information
  341.  */
  342. static DISKPART *GetDiskPart(Name, DiskLabel)
  343.     char               *Name;
  344.     struct disk_label           *DiskLabel;
  345. {
  346.     register int        i;
  347.     register DISKPART           *Ptr;
  348.     DISKPART               *Base = NULL;
  349.     DISKPART            DiskPart;
  350.     static char            Part[2];
  351.     register char           *p;
  352.  
  353.     Part[1] = C_NULL;
  354.  
  355.     /*
  356.      * Now handle each partition
  357.      */
  358.     for (i = 0; i < NPART; i++) {
  359.     /* Ingore partitins that have no size */
  360.     if (DiskLabel->dl_dt.d_partitions[i].p_size <= 0)
  361.         continue;
  362.  
  363.     Part[0] = 'a' + i;
  364.  
  365.     /* Make a clean slate */
  366.     bzero((char *) &DiskPart, sizeof(DISKPART));
  367.  
  368.     /* Fill in the blanks */
  369.     DiskPart.dp_name = strdup(Part);
  370.     DiskPart.dp_stsect = DiskLabel->dl_dt.d_partitions[i].p_base;
  371.     DiskPart.dp_nsect = DiskLabel->dl_dt.d_partitions[i].p_size;
  372.  
  373.     /* 
  374.      * Get the mount point name.
  375.      */
  376.     if (p = GetMountInfo(Name, Part))
  377.         DiskPart.dp_mnt = strdup(p);
  378.  
  379.     /*
  380.      * Add this partition to the linked list.
  381.      */
  382.     if (Base) {
  383.         for (Ptr = Base; Ptr && Ptr->dp_nxt; Ptr = Ptr->dp_nxt);
  384.         Ptr->dp_nxt = NewDiskPart(&DiskPart);
  385.     } else {
  386.         Base = NewDiskPart(&DiskPart);
  387.     }
  388.     }
  389.  
  390.     return(Base);
  391. }
  392.  
  393. /*
  394.  * Convert disk info into a DEVICE entry.
  395.  */
  396. static DEVICE *diskToDiskDrive(Name, DevData, DevDataTab, DiskLabel, DriveInfo)
  397.     char               *Name;
  398.     DEVDATA               *DevData;
  399.     DEVDATATAB               *DevDataTab;
  400.     struct disk_label           *DiskLabel;
  401.     struct drive_info           *DriveInfo;
  402. {
  403.     DEVICE               *Device;
  404.     DISKDRIVE               *DiskDrive;
  405.     static char         Buf[BUFSIZ];
  406.  
  407.     if ((Device = NewDevice(NULL)) == NULL) {
  408.     Error("Cannot create new device entry.");
  409.     return((DEVICE *) NULL);
  410.     }
  411.  
  412.     if ((DiskDrive = NewDiskDrive(NULL)) == NULL) {
  413.     Error("Cannot create new diskdrive entry.");
  414.     return((DEVICE *) NULL);
  415.     }
  416.  
  417.     Device->dv_name         = strdup(Name);
  418.     Device->dv_type         = DT_DISKDRIVE;
  419.     DiskDrive->dd_label     = strdup(DriveInfo->di_name);
  420.     Device->dv_model         = DiskDrive->dd_label;
  421.     DiskDrive->dd_unit         = DevData->dd_devunit;
  422.     DiskDrive->dd_slave     = DevData->dd_slave;
  423.     DiskDrive->dd_dcyl         = DiskLabel->dl_ncyl;
  424.     DiskDrive->dd_heads     = DiskLabel->dl_ntrack;
  425.     DiskDrive->dd_sect         = DiskLabel->dl_nsect;
  426.     DiskDrive->dd_apc         = DiskLabel->dl_ngroups;
  427.     DiskDrive->dd_rpm         = DiskLabel->dl_rpm;
  428.     DiskDrive->dd_secsize     = DiskLabel->dl_secsize;
  429.     /*
  430.      * Only get partition info we we're going to print it later.
  431.      */
  432.     if (VL_ALL)
  433.     DiskDrive->dd_part     = GetDiskPart(Name, DiskLabel);
  434.  
  435.     /*
  436.      * Determine size (capacity) of media
  437.      */
  438.     if (DiskDrive->dd_dcyl && DiskDrive->dd_sect && DiskDrive->dd_heads)
  439.     DiskDrive->dd_size = nsect_to_bytes(DiskDrive->dd_dcyl * 
  440.                         DiskDrive->dd_sect * 
  441.                         DiskDrive->dd_heads, 
  442.                         DiskDrive->dd_secsize);
  443.  
  444.     /*
  445.      * Create the description
  446.      */
  447.     if (DiskDrive->dd_size > 0) {
  448.     (void) sprintf(Buf, "%.2f MB capacity", 
  449.                (float) bytes_to_mbytes(DiskDrive->dd_size));
  450.     Device->dv_desc = strdup(Buf);
  451.     }
  452.  
  453.     Device->dv_devspec = (caddr_t *) DiskDrive;
  454.     Device->dv_master = MkMasterFromDevData(DevData);
  455.  
  456.     return(Device);
  457. }
  458.  
  459. /*
  460.  * Query and learn about a disk.
  461.  */
  462. extern DEVICE *ProbeDiskDrive(Name, DevData, DevDataTab)
  463.     /*ARGSUSED*/
  464.     char                *Name;
  465.     DEVDATA                *DevData;
  466.     DEVDATATAB                     *DevDataTab;
  467. {
  468.     static struct disk_label    DiskLabel;
  469.     static struct drive_info     DriveInfo;
  470.     int                Desc;
  471.     char               *File;
  472.     DEVICE               *Device;
  473.  
  474.     File = GetRawFile(Name, "a");
  475.  
  476.     if ((Desc = open(File, O_RDONLY|O_NDELAY)) < 0) {
  477.     if (Debug) Error("%s: Cannot open for read: %s.\n", File, SYSERR);
  478.     /*
  479.      * If we know for sure this drive is present and we
  480.      * know something about it, then create a minimal device.
  481.      */
  482.     if ((DevDataTab->ddt_model || DevDataTab->ddt_desc) &&
  483.         FLAGS_ON(DevData->dd_flags, DD_IS_ALIVE)) {
  484.         Device = NewDevice((DEVICE *) NULL);
  485.         Device->dv_name = strdup(Name);
  486.         Device->dv_unit = DevData->dd_devunit;
  487.         Device->dv_master = MkMasterFromDevData(DevData);
  488.         Device->dv_type = DT_DISKDRIVE;
  489.         Device->dv_model = DevDataTab->ddt_model;
  490.         Device->dv_desc = DevDataTab->ddt_desc;
  491.         return(Device);
  492.     } else
  493.         return((DEVICE *) NULL);
  494.     }
  495.  
  496.     /*
  497.      * Read disk label
  498.      */
  499.     if (ioctl(Desc, DKIOCGLABEL, &DiskLabel) < 0) {
  500.     if (Debug) Error("%s: DKIOCGLABEL: %s.", File, SYSERR);
  501.     return((DEVICE *) NULL);
  502.     }
  503.  
  504.     /*
  505.      * Read drive info
  506.      */
  507.     if (ioctl(Desc, DKIOCINFO, &DriveInfo) < 0) {
  508.     if (Debug) Error("%s: DKIOCINFO: %s.", File, SYSERR);
  509.     return((DEVICE *) NULL);
  510.     }
  511.  
  512.     close(Desc);
  513.  
  514.     if (!(Device = diskToDiskDrive(Name, DevData, DevDataTab, 
  515.                    &DiskLabel, &DriveInfo))) {
  516.     Error("%s: Cannot convert diskdrive info.", Name);
  517.     return((DEVICE *) NULL);
  518.     }
  519.  
  520.     return(Device);
  521. }
  522.  
  523. /*
  524.  * Get ROM Version
  525.  */
  526. extern char *GetRomVer()
  527. {
  528.     /* No support */
  529.     return((char *) NULL);
  530. }
  531.