ftp.nice.ch/pub/next/unix/admin/sysinfo.1.1.0.s.tar.gz#/os-next.c

This is os-next.c in view mode; [Download] [Up]

/*
 * Copyright (c) 1992 Michael A. Cooper.
 * This software may be freely distributed provided it is not sold for 
 * profit and the author is credited appropriately.
 */

#ifndef lint
static char *RCSid = "$Header: /src/common/usc/bin/sysinfo/RCS/os-next.c,v 1.11 1992/11/24 04:05:57 mcooper Exp mcooper $";
#endif

/*
 * $Log: os-next.c,v $
 * Revision 1.11  1992/11/24  04:05:57  mcooper
 * New/cleaner KVM/nlist interface.
 *
 * Revision 1.10  1992/04/26  23:32:06  mcooper
 * Add Copyright notice
 *
 * Revision 1.9  1992/04/17  23:27:51  mcooper
 * Add support for ROM Version information (Sun only for now).
 *
 * Revision 1.8  1992/04/17  01:07:59  mcooper
 * More de-linting
 *
 * Revision 1.7  1992/04/15  02:04:16  mcooper
 * Change GetMemoryStr() to GetMemory().
 *
 * Revision 1.6  1992/03/31  02:22:03  mcooper
 * Fix failed return value from CheckNlist().
 *
 * Revision 1.5  1992/03/31  01:55:17  mcooper
 * Use new CheckNlist to check nlist success.
 *
 * Revision 1.4  1992/03/31  00:15:09  mcooper
 * Add error check for nlist.n_type.
 *
 * Revision 1.3  1992/03/28  21:59:28  mcooper
 * Implemented disk and netif device probing.
 *
 * Revision 1.2  1992/03/22  02:03:48  mcooper
 * Add Build*NeXT*() functions.
 *
 * Revision 1.1  1992/03/22  01:04:34  mcooper
 * Initial revision
 *
 */


/*
 * NeXT specific functions
 */

#include <stdio.h>
#include "system.h"
#include "defs.h"

#include <nlist.h>
#include <mntent.h>
#include <nextdev/disk.h>
#include <nextdev/busvar.h>

#define DV_SIZE		(sizeof(struct bus_device))
#define DR_SIZE		(sizeof(struct bus_driver))
#define CR_SIZE		(sizeof(struct bus_ctrl))

/*
 * Build a device tree by searching NeXTBus
 */
static int BuildNeXTBus(TreePtr)
    DEVICE 		      **TreePtr;
{
    extern char		 	NeXTBusSYM[];
    struct nlist	       *nlptr;
    static struct nlist		nlistbuf;
    static struct bus_device 	Device;
    static struct bus_driver 	Driver;
    static struct bus_ctrl 	Ctlr;
    static char 		CtlrName[BUFSIZ], DevName[BUFSIZ];
    u_long 			Addr, DeviceAddr;
    static DEVDATA 		DevData;
    DEVICE 		       *Dev;
    kvm_t		       *kd;

    /*
     * Read table address from kernel
     */
    if (!(kd = KVMopen()))
	return(-1);

    if ((nlptr = KVMnlist(kd, NeXTBusSYM, &nlistbuf)) == NULL)
	return(-1);

    if (CheckNlist(nlptr))
	return(-1);

    /*
     * Read each device table entry.  A NULL device.bd_driver
     * indicates that we're at the end of the table.
     */
    for (DeviceAddr = nlptr->n_value; DeviceAddr; 
	 DeviceAddr += DV_SIZE) {

	/*
	 * Read this device
	 */
	if (KVMread(kd, DeviceAddr, (char *) &Device, DV_SIZE)) {
	    if (Debug) 
		Error("Cannot read NeXTbus device from address 0x%x.", 
		      DeviceAddr);
	    KVMclose(kd);
	    return(-1);
	}

	/*
	 * See if we're done.
	 */
	if (!Device.bd_driver)
	    break;

	/*
	 * Get the device name
	 */
	DevName[0] = C_NULL;
	if (Addr = (u_long) Device.bd_name) {
	    if (KVMread(kd, Addr, (char *) DevName, sizeof(DevName))) {
		if (Debug)
		    Error("Cannot read device name from address 0x%x.", Addr);
		continue;
	    }
	}

	/*
	 * Get the controller info
	 */
	CtlrName[0] = C_NULL;
	/*
	 * First read the controller structure in
	 */
	if (Addr = (u_long) Device.bd_bc) {
	    if (KVMread(kd, Addr, (char *) &Ctlr, CR_SIZE)) {
		if (Debug) 
		    Error("Cannot read controller from address 0x%x.", Addr);
	    } else if (Addr = (u_long) Ctlr.bc_driver) {
		/*
		 * Get the controller driver
		 */
		if (KVMread(kd, Addr, (char *) &Driver, DR_SIZE)) {
		    if (Debug)
			Error(
			    "Cannot read controller driver from address 0x%x.",
			      Addr);
		    continue;
		}
		/*
		 * Read the name of the controller from the driver
		 */
		if (!(Addr = (u_long) Driver.br_cname)) {
		    if (Debug)
			Error("No name for controller at address 0x%x.",
			      Ctlr.bc_driver);
		    continue;
		}
		if (KVMread(kd, Addr, CtlrName, sizeof(CtlrName))) {
		    if (Debug)
			Error("Read controller name failed (address 0x%x).",
			      Addr);
		    continue;
		}
	    }
	}

	if (Debug)
	    printf("NeXTbus: Found '%s' on '%s'.\n", DevName, CtlrName);

	/* Make sure devdata is clean */
	bzero(&DevData, sizeof(DEVDATA));

	/* Set what we know */
	if (DevName[0]) {
	    DevData.dd_devname = strdup(DevName);
	    DevData.dd_devunit = Device.bd_unit;
	    DevData.dd_slave = Device.bd_slave;
	}
	if (CtlrName[0]) {
	    DevData.dd_ctlrname = strdup(CtlrName);
	    DevData.dd_ctlrunit = Ctlr.bc_ctrl;
	}

	/* 
	 * NeXTbus devices should always exist.
	 */
	if (Device.bd_alive)
	    DevData.dd_flags |= DD_IS_ALIVE;

	/* Probe and add device */
	if (Dev = (DEVICE *) ProbeDevice(&DevData, TreePtr, NULL))
	    AddDevice(Dev, TreePtr);
    }

    KVMclose(kd);

    return(0);
}

/*
 * Build list of NeXT devices
 */
extern int BuildDevicesNeXT(TreePtr)
    DEVICE 		      **TreePtr;
{
    int				Found = 1;

    if (BuildNeXTBus(TreePtr) == 0)
	Found = 0;

    return(Found);
}

/*
 * Get the system model name.  NeXT keeps the system type
 * in a kernel variable called machine_type.
 * The system types are defined in <next/scr.h>.
 */
extern char *GetModelName()
{
    struct nlist	       *nlptr;
    extern NAMETAB		ModelTab[];
    extern char			MachineTypeSYM[];
    u_char			MachineType;
    register int		i;
    kvm_t		       *kd;

    if (!(kd = KVMopen()))
	return((char *) NULL);

    if ((nlptr = KVMnlist(kd, MachineTypeSYM, (struct nlist *)NULL)) == NULL)
	return((char *) NULL);

    if (CheckNlist(nlptr))
	return((char *) NULL);

    if (KVMread(kd, (u_long) nlptr->n_value, 
		(char *) &MachineType, sizeof(MachineType))) {
	if (Debug) Error("Cannot read \"%s\" from kernel.", MachineTypeSYM);
	return((char *) NULL);
    }

    KVMclose(kd);

    for (i = 0; ModelTab[i].name; ++i)
	if (ModelTab[i].value == MachineType)
	    return(ModelTab[i].name);

    if (Debug)
	printf("system model/type %d is unknown.\n", MachineType);

    return((char *) NULL);
}

/*
 * Get kernel version string using Mach HostInfo method
 */
extern char *GetKernelVersionStr()
{
    return(GetKernelVersionFromHostInfo());
}

/*
 * Get amount of physical memory using Mach HostInfo method
 */
extern char *GetMemory()
{
    return(GetMemoryFromHostInfo());
}

/*
 * Get application architecture name using Mach HostInfo method.
 */
extern char *GetAppArchName()
{
    return(GetAppArchFromHostInfo());
}

/*
 * Get kernel architecture name using Mach HostInfo method.
 */
extern char *GetKernArchName()
{
    return(GetKernArchFromHostInfo());
}

/*
 * Get system serial number
 */
extern char *GetSerialNoStr()
{
    /* No support */
    return((char *) NULL);
}

/*
 * Get OS version using Mach HostInfo method.
 */
extern char *GetOSVersionStr()
{
    return(GetOSVersionFromHostInfo());
}

/*
 * Get filesystem mount info for a partition.
 */
static char *GetMountInfo(Name, Part)
    char 		       *Name;
    char 		       *Part;
{
    FILE 		       *mf;
    struct mntent 	       *mntent;
    char 		       *file;

    if (!Name)
	return((char *) NULL);

    file = GetCharFile(Name, Part);

    if ((mf = setmntent(MNTTAB, "r")) == NULL) {
	Error("%s: Cannot open for reading: %s.", MNTTAB, SYSERR);
	return(NULL);
    }

    while (mntent = getmntent(mf)) {
	if (strcmp(mntent->mnt_fsname, file) == 0)
	    break;
    }

    endmntent(mf);

    return((mntent) ? mntent->mnt_dir : (char *) NULL);
}

/*
 * Get disk partition information
 */
static DISKPART *GetDiskPart(Name, DiskLabel)
    char		       *Name;
    struct disk_label	       *DiskLabel;
{
    register int		i;
    register DISKPART	       *Ptr;
    DISKPART		       *Base = NULL;
    DISKPART			DiskPart;
    static char			Part[2];
    register char	       *p;

    Part[1] = C_NULL;

    /*
     * Now handle each partition
     */
    for (i = 0; i < NPART; i++) {
	/* Ingore partitins that have no size */
	if (DiskLabel->dl_dt.d_partitions[i].p_size <= 0)
	    continue;

	Part[0] = 'a' + i;

	/* Make a clean slate */
	bzero((char *) &DiskPart, sizeof(DISKPART));

	/* Fill in the blanks */
	DiskPart.dp_name = strdup(Part);
	DiskPart.dp_stsect = DiskLabel->dl_dt.d_partitions[i].p_base;
	DiskPart.dp_nsect = DiskLabel->dl_dt.d_partitions[i].p_size;

	/* 
	 * Get the mount point name.
	 */
	if (p = GetMountInfo(Name, Part))
	    DiskPart.dp_mnt = strdup(p);

	/*
	 * Add this partition to the linked list.
	 */
	if (Base) {
	    for (Ptr = Base; Ptr && Ptr->dp_nxt; Ptr = Ptr->dp_nxt);
	    Ptr->dp_nxt = NewDiskPart(&DiskPart);
	} else {
	    Base = NewDiskPart(&DiskPart);
	}
    }

    return(Base);
}

/*
 * Convert disk info into a DEVICE entry.
 */
static DEVICE *diskToDiskDrive(Name, DevData, DevDataTab, DiskLabel, DriveInfo)
    char		       *Name;
    DEVDATA		       *DevData;
    DEVDATATAB		       *DevDataTab;
    struct disk_label	       *DiskLabel;
    struct drive_info	       *DriveInfo;
{
    DEVICE		       *Device;
    DISKDRIVE		       *DiskDrive;
    static char 		Buf[BUFSIZ];

    if ((Device = NewDevice(NULL)) == NULL) {
	Error("Cannot create new device entry.");
	return((DEVICE *) NULL);
    }

    if ((DiskDrive = NewDiskDrive(NULL)) == NULL) {
	Error("Cannot create new diskdrive entry.");
	return((DEVICE *) NULL);
    }

    Device->dv_name 		= strdup(Name);
    Device->dv_type 		= DT_DISKDRIVE;
    DiskDrive->dd_label 	= strdup(DriveInfo->di_name);
    Device->dv_model 		= DiskDrive->dd_label;
    DiskDrive->dd_unit 		= DevData->dd_devunit;
    DiskDrive->dd_slave 	= DevData->dd_slave;
    DiskDrive->dd_dcyl 		= DiskLabel->dl_ncyl;
    DiskDrive->dd_heads 	= DiskLabel->dl_ntrack;
    DiskDrive->dd_sect 		= DiskLabel->dl_nsect;
    DiskDrive->dd_apc 		= DiskLabel->dl_ngroups;
    DiskDrive->dd_rpm 		= DiskLabel->dl_rpm;
    DiskDrive->dd_secsize 	= DiskLabel->dl_secsize;
    /*
     * Only get partition info we we're going to print it later.
     */
    if (VL_ALL)
	DiskDrive->dd_part 	= GetDiskPart(Name, DiskLabel);

    /*
     * Determine size (capacity) of media
     */
    if (DiskDrive->dd_dcyl && DiskDrive->dd_sect && DiskDrive->dd_heads)
	DiskDrive->dd_size = nsect_to_bytes(DiskDrive->dd_dcyl * 
					    DiskDrive->dd_sect * 
					    DiskDrive->dd_heads, 
					    DiskDrive->dd_secsize);

    /*
     * Create the description
     */
    if (DiskDrive->dd_size > 0) {
	(void) sprintf(Buf, "%.2f MB capacity", 
		       (float) bytes_to_mbytes(DiskDrive->dd_size));
	Device->dv_desc = strdup(Buf);
    }

    Device->dv_devspec = (caddr_t *) DiskDrive;
    Device->dv_master = MkMasterFromDevData(DevData);

    return(Device);
}

/*
 * Query and learn about a disk.
 */
extern DEVICE *ProbeDiskDrive(Name, DevData, DevDataTab)
    /*ARGSUSED*/
    char 		       *Name;
    DEVDATA 		       *DevData;
    DEVDATATAB 	     	       *DevDataTab;
{
    static struct disk_label    DiskLabel;
    static struct drive_info 	DriveInfo;
    int				Desc;
    char		       *File;
    DEVICE		       *Device;

    File = GetRawFile(Name, "a");

    if ((Desc = open(File, O_RDONLY|O_NDELAY)) < 0) {
	if (Debug) Error("%s: Cannot open for read: %s.\n", File, SYSERR);
	/*
	 * If we know for sure this drive is present and we
	 * know something about it, then create a minimal device.
	 */
	if ((DevDataTab->ddt_model || DevDataTab->ddt_desc) &&
	    FLAGS_ON(DevData->dd_flags, DD_IS_ALIVE)) {
	    Device = NewDevice((DEVICE *) NULL);
	    Device->dv_name = strdup(Name);
	    Device->dv_unit = DevData->dd_devunit;
	    Device->dv_master = MkMasterFromDevData(DevData);
	    Device->dv_type = DT_DISKDRIVE;
	    Device->dv_model = DevDataTab->ddt_model;
	    Device->dv_desc = DevDataTab->ddt_desc;
	    return(Device);
	} else
	    return((DEVICE *) NULL);
    }

    /*
     * Read disk label
     */
    if (ioctl(Desc, DKIOCGLABEL, &DiskLabel) < 0) {
	if (Debug) Error("%s: DKIOCGLABEL: %s.", File, SYSERR);
	return((DEVICE *) NULL);
    }

    /*
     * Read drive info
     */
    if (ioctl(Desc, DKIOCINFO, &DriveInfo) < 0) {
	if (Debug) Error("%s: DKIOCINFO: %s.", File, SYSERR);
	return((DEVICE *) NULL);
    }

    close(Desc);

    if (!(Device = diskToDiskDrive(Name, DevData, DevDataTab, 
				   &DiskLabel, &DriveInfo))) {
	Error("%s: Cannot convert diskdrive info.", Name);
	return((DEVICE *) NULL);
    }

    return(Device);
}

/*
 * Get ROM Version
 */
extern char *GetRomVer()
{
    /* No support */
    return((char *) NULL);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.