home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume26
/
sysinfo-1.0
/
part01
/
os-ultrix.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-10
|
19KB
|
872 lines
/*
* 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-ultrix.c,v 1.14 1992/04/26 23:32:06 mcooper Exp $";
#endif
/*
* $Log: os-ultrix.c,v $
* Revision 1.14 1992/04/26 23:32:06 mcooper
* Add Copyright notice
*
* Revision 1.13 1992/04/17 23:27:51 mcooper
* Add support for ROM Version information (Sun only for now).
*
* Revision 1.12 1992/04/17 01:07:59 mcooper
* More de-linting
*
* Revision 1.11 1992/04/16 19:56:24 mcooper
* De-linting stuff.
*
* Revision 1.10 1992/04/15 02:04:16 mcooper
* Change GetMemoryStr() to GetMemory().
*
* Revision 1.9 1992/03/31 02:22:03 mcooper
* Fix failed return value from CheckNlist().
*
* Revision 1.8 1992/03/31 01:55:17 mcooper
* Use new CheckNlist to check nlist success.
*
* Revision 1.7 1992/03/31 00:15:09 mcooper
* Add error check for nlist.n_type.
*
* Revision 1.6 1992/03/22 00:20:10 mcooper
* Major cleanup and re-org.
*
* Revision 1.5 1992/03/09 01:07:50 mcooper
* Add support for determining system model type.
*
* Revision 1.4 1992/03/08 23:08:41 mcooper
* - Add new set_macinfo_packetfilter().
* - Remove unneeded get_bus().
*
* Revision 1.3 1992/03/08 04:57:09 mcooper
* Set DT_TAPEDRIVE in probe_tapedrive().
*
* Revision 1.2 1992/03/08 01:11:39 mcooper
* Add tape drive support.
*
* Revision 1.1 1992/03/06 18:35:40 mcooper
* Initial revision
*
*/
/*
* Ultrix specific functions
*/
#include <stdio.h>
#include "system.h"
#include "defs.h"
#include <fcntl.h>
#include <nlist.h>
#include <fstab.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/fs.h>
#include <sys/ioctl.h>
#include <sys/buf.h>
#include <sys/stat.h>
#include <machine/cpuconf.h>
#include <sys/devio.h>
#include <sys/mtio.h>
#include "info-ultrix.h"
#if defined(HAVE_UBA)
/*
* UBA (UniBus Adapter) specific code
*/
#include <io/uba/ubavar.h>
/*
* Probe specific structure
*/
struct _probespec {
struct uba_device *uba_device;
};
typedef struct _probespec PROBESPEC;
#define DV_SIZE (sizeof(struct uba_device))
#define CR_SIZE (sizeof(struct uba_ctlr))
/*
* Build a device tree by searching Unibus Adapters
*/
static int BuildUBA(TreePtr)
DEVICE **TreePtr;
{
extern struct nlist UniBusNL[];
static struct uba_device Device;
static struct uba_ctlr Ctlr;
static char CtlrName[BUFSIZ], DevName[BUFSIZ];
u_long Addr, DeviceAddr;
static DEVDATA DevData;
static PROBESPEC ProbeSpec;
DEVICE *dev;
kvm_t *kd;
int cnum;
/*
* Read table address from kernel
*/
if (!(kd = KVM_open(UniBusNL))) {
if (Debug) Error("Cannot read unibus device table from kernel.");
return(-1);
}
/*
* See if we got a valid entry
*/
if (CheckNlist(&UniBusNL[0]))
return(-1);
/*
* Read each device table entry. A NULL device.ui_driver
* indicates that we're at the end of the table.
*/
for (DeviceAddr = UniBusNL[0].n_value; DeviceAddr;
DeviceAddr += DV_SIZE) {
/*
* Read this device
*/
if (KVM_read(kd, DeviceAddr, (char *) &Device, DV_SIZE)) {
if (Debug)
Error("Cannot read unibus device from address 0x%x.",
DeviceAddr);
KVM_close(kd);
return(-1);
}
/*
* See if we're done.
*/
if (!Device.ui_driver)
break;
/*
* Get the device name
*/
DevName[0] = C_NULL;
if (Addr = (u_long) Device.ui_devname) {
if (KVM_read(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;
cnum = -1;
if (Addr = (u_long) Device.ui_mi) {
if (KVM_read(kd, Addr, (char *) &Ctlr, CR_SIZE)) {
if (Debug)
Error("Cannot read controller from address 0x%x.", Addr);
} else {
/*
* Get the controller name
*/
if (Addr = (u_long) Ctlr.um_ctlrname) {
if (KVM_read(kd, Addr, CtlrName, sizeof(CtlrName))) {
if (Debug)
Error(
"Cannot read controller name from driver address 0x%x.",
Addr);
continue;
}
}
cnum = Ctlr.um_ctlr;
}
}
if (Debug)
printf("build_unibus(): 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.ui_unit;
}
if (CtlrName[0]) {
DevData.dd_ctlrname = strdup(CtlrName);
DevData.dd_ctlrunit = cnum;
}
/*
* Unibus devices should always exist.
*/
if (Device.ui_alive)
DevData.dd_flags |= DD_IS_ALIVE;
ProbeSpec.uba_device = &Device;
/* Probe and add device */
if (dev = (DEVICE *) ProbeDevice(&DevData, TreePtr, &ProbeSpec))
AddDevice(dev, TreePtr);
}
KVM_close(kd);
return(0);
}
#endif /* HAVE_UBA */
/*
* Build list of Ultrix devices
*/
extern int BuildDevicesUltrix(TreePtr)
DEVICE **TreePtr;
{
int Found = 1;
#if defined(HAVE_UBA)
if (BuildUBA(TreePtr) == 0)
Found = 0;
#endif /* HAVE_UBA */
return(Found);
}
/*
* Get Device Info structure from device.
*/
static struct devget *GETdevget(File, FileD)
char *File;
int FileD;
{
static struct devget devget;
if (ioctl(FileD, DEVIOCGET, &devget) == SYSFAIL) {
if (Debug) Error("%s: ioctl DEVIOCGET failed: %s.", File, SYSERR);
return((struct devget *) NULL);
}
return(&devget);
}
/*
* Get Device Geometry structure from device.
*/
static DEVGEOMST *GETdevgeom(File, FileD)
char *File;
int FileD;
{
static DEVGEOMST devgeom;
if (ioctl(FileD, DEVGETGEOM, &devgeom) == SYSFAIL) {
if (Debug) Error("%s: ioctl DEVGETGEOM failed: %s.", File, SYSERR);
return((DEVGEOMST *) NULL);
}
return(&devgeom);
}
/*
* Lookup a category type.
*/
static char *GetCategory(val)
int val;
{
extern NAMETAB Categorys[];
register int i;
for (i = 0; Categorys[i].name; ++i)
if (val == Categorys[i].value)
return(Categorys[i].name);
return((char *) NULL);
}
/*
* Convert a 'devget' to a 'device'.
*/
static DEVICE *devgetToDEVICE(DevGet, DevData, ProbeSpec)
struct devget *DevGet;
DEVDATA *DevData;
PROBESPEC *ProbeSpec;
{
DEVICE *Device;
if (!(Device = NewDevice(NULL)))
return(Device);
Device->dv_name = strdup(MkDevName(DevData->dd_devname,
DevData->dd_devunit));
Device->dv_model = strdup(DevGet->device);
Device->dv_desc = GetCategory(DevGet->category);
Device->dv_unit = DevGet->unit_num;
/*
* Set master/controller info
*/
if (Device->dv_master = MkMasterFromDevData(DevData))
Device->dv_master->dv_model = strdup(DevGet->interface);
return(Device);
}
/*
* Check a device by trying to perform a devget on it.
*/
static struct devget *CheckDevice(File)
char *File;
{
struct devget *DevGet;
int d;
if ((d = open(File, O_RDONLY|O_NDELAY)) < 0) {
if (Debug) Error("%s: Cannot open: %s.", File, SYSERR);
return((struct devget *) NULL);
}
/*
* Get generic device info
*/
if (!(DevGet = GETdevget(File, d))) {
if (Debug) Error("%s: GETdevget failed.", File);
close(d);
return((struct devget *) NULL);
}
close(d);
return(DevGet);
}
/*
* Retrieve disk partition information from a device file.
*/
static struct pt *ExtractDiskPart(File)
char *File;
{
static struct pt pt;
int d;
if ((d = open(File, O_RDONLY|O_NDELAY)) < 0) {
if (Debug) Error("%s: open failed: %s.", File, SYSERR);
return((struct pt *) NULL);
}
if (ioctl(d, DIOCGETPT, &pt) < 0) {
if (Debug) Error("%s: ioctl DIOCGETPT failed: %s.", File, SYSERR);
close(d);
return((struct pt *) NULL);
}
close(d);
return(&pt);
}
/*
* Get the mount point for a filesystem.
*/
static char *GetMountInfo(Name, Part)
char *Name;
char *Part;
{
char *File;
struct fstab *fstab;
File = GetCharFile(Name, Part);
if (fstab = getfsspec(File)) {
if (strcmp(fstab->fs_type, FSTAB_SW) == 0)
return("swap");
return(fstab->fs_file);
}
return((char *) NULL);
}
/*
* Get the partition information for a disk device.
*/
static DISKPART *GetPartInfo(Name, Device)
char *Name;
DEVICE *Device;
{
static DISKPART diskpart;
static char Buf[BUFSIZ], part[2];
register DISKPART *pdp, *dp;
register char *p;
DISKPART *base = NULL;
struct pt *pt;
register int i;
/*
* First get the partition info.
*/
(void) sprintf(Buf, "/dev/r%sa", Name);
if (!(pt = ExtractDiskPart(Buf)))
return((DISKPART *) NULL);
part[1] = C_NULL;
/*
* Now deal with each partition.
*/
for (i = 0; i < MAX_DISK_PARTS; ++i) {
/* Ignore partitions that have no size */
if (!pt->pt_part[i].pi_nblocks)
continue;
part[0] = 'a' + i;
/* Make a clean slate */
bzero((char *) &diskpart, sizeof(DISKPART));
/* Fill in what we know */
diskpart.dp_name = strdup(part);
diskpart.dp_stsect = pt->pt_part[i].pi_blkoff;
diskpart.dp_nsect = pt->pt_part[i].pi_nblocks;
/*
* Get the mount point name.
* If this is the "b" partition on the
* root device, then assume it's swap
*/
if (p = GetMountInfo(Name, part))
diskpart.dp_mnt = strdup(p);
else if (Device->dv_unit == 0 && strcmp(part, "b") == 0)
diskpart.dp_mnt = "swap";
/*
* Add this partition to the linked list.
*/
if (base) {
for (pdp = base; pdp && pdp->dp_nxt; pdp = pdp->dp_nxt);
pdp->dp_nxt = NewDiskPart(&diskpart);
} else {
base = NewDiskPart(&diskpart);
}
}
return(base);
}
/*
* Probe a disk drive
*/
extern DEVICE *ProbeDiskDrive(Name, DevData, DevDataTab, ProbeSpec)
char *Name;
DEVDATA *DevData;
DEVDATATAB *DevDataTab;
PROBESPEC *ProbeSpec;
{
DEVICE *Device;
DISKDRIVE *DiskDrive;
DEVGEOMST *DevGeom;
struct devget *DevGet;
char *File;
int Desc;
if (!Name)
return((DEVICE *) NULL);
File = GetRawFile(Name, "c");
if ((Desc = open(File, O_RDONLY|O_NDELAY)) < 0) {
if (Debug) Error("%s: open failed: %s.", 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);
}
/*
* Get generic device info
*/
if (!(DevGet = GETdevget(File, Desc))) {
if (Debug) Error("%s: GETdevget failed.", File);
close(Desc);
return((DEVICE *) NULL);
}
/*
* Get geometry of device
*/
if (!(DevGeom = GETdevgeom(File, Desc))) {
if (Debug) Error("%s: get_geomst failed.", File);
}
close(Desc);
/*
* Convert devget info to a device struct
*/
if (!(Device = devgetToDEVICE(DevGet, DevData, ProbeSpec))) {
if (Debug) Error("%s: Cannot convert devget to device.");
return((DEVICE *) NULL);
}
/*
* Disks should be on disk controllers.
*/
if (Device->dv_master)
Device->dv_master->dv_type = DT_DISKCTLR;
/*
* Set the disk drive specific info
*/
if ((DiskDrive = NewDiskDrive(NULL)) == NULL) {
Error("Cannot create new diskdrive entry.");
return((DEVICE *) NULL);
}
Device->dv_type = DT_DISKDRIVE;
if (DevGet->device)
DiskDrive->dd_label = strdup(DevGet->device);
/*
* Convert Geometry
*/
if (DevGeom) {
/*
* If this is a removable device, indicate so.
*/
if (FLAGS_ON(DevGeom->geom_info.attributes, DEVGEOM_REMOVE)) {
if (Device->dv_desc) {
char Buf[BUFSIZ];
(void) sprintf(Buf, "Removable %s", Device->dv_desc);
(void) free(Device->dv_desc);
Device->dv_desc = strdup(Buf);
} else {
Device->dv_desc = "Removable disk drive";
}
}
DiskDrive->dd_unit = DevGet->unit_num;
DiskDrive->dd_slave = DevGet->slave_num;
DiskDrive->dd_part = GetPartInfo(Name, Device);
DiskDrive->dd_dcyl = DevGeom->geom_info.ncylinders;
DiskDrive->dd_heads = DevGeom->geom_info.ntracks;
DiskDrive->dd_sect = DevGeom->geom_info.nsectors;
DiskDrive->dd_secsize = SECSIZE;
if (DiskDrive->dd_dcyl && DiskDrive->dd_sect && DiskDrive->dd_heads) {
static char Buf[BUFSIZ];
DiskDrive->dd_size = nsect_to_bytes(DiskDrive->dd_dcyl *
DiskDrive->dd_sect *
DiskDrive->dd_heads,
DiskDrive->dd_secsize);
(void) sprintf(Buf, "%.2f MB capacity",
(float) bytes_to_mbytes(DiskDrive->dd_size));
Device->dv_desc = strdup(Buf);
}
}
Device->dv_devspec = (caddr_t *) DiskDrive;
return(Device);
}
/*
* Lookup info about a tape drive.
*/
static char *GetTapeInfo(Flag)
int Flag;
{
extern NAMETAB TapeInfo[];
static char Buf[BUFSIZ];
register int i;
if (!Flag)
return((char *) NULL);
Buf[0] = C_NULL;
/*
* Values are flag bits and are appended together.
*/
for (i = 0; TapeInfo[i].name; i++) {
if (Flag & TapeInfo[i].value) {
if (Buf[0]) {
(void) strcat(Buf, ", ");
(void) strcat(Buf, TapeInfo[i].name);
} else
(void) strcpy(Buf, TapeInfo[i].name);
}
}
return(Buf);
}
/*
* Probe a tape drive
*/
extern DEVICE *ProbeTapeDrive(Name, DevData, DevDataTab, ProbeSpec)
char *Name;
DEVDATA *DevData;
DEVDATATAB *DevDataTab;
PROBESPEC *ProbeSpec;
{
struct devget *DevGet;
DEVICE *Device;
char *File;
char *p;
char Buf[BUFSIZ];
register int i;
/*
* XXX Kludge Alert! ! !
*
* Ultrix tape device files are numbered independently of actual
* unit number. Additionally, not all tape devices support the same
* set of minor devices types, so we can't look at the minor device
* number.
*
* The code below will open(), ioctl(), close() all tape
* devices between 0 and MAXTAPES until a matching unit number is found.
* This means that on systems with lots of tape drives, this can be
* very slow.
*/
for (i = 0; i < MAXTAPES; ++i) {
(void) sprintf(Buf, "/dev/nrmt%dh", i);
if ((DevGet = CheckDevice(Buf)) &&
(DevGet->unit_num == DevData->dd_devunit))
break;
}
if (!DevGet) {
if (Debug) Error("%s: Cannot find device file.", Name);
return((DEVICE *) NULL);
}
/*
* Convert devget info to a device struct
*/
if (!(Device = devgetToDEVICE(DevGet, DevData, ProbeSpec))) {
if (Debug) Error("%s: Cannot convert devget to device.");
return((DEVICE *) NULL);
}
/*
* Set our device type
*/
Device->dv_type = DT_TAPEDRIVE;
/*
* Get and add Tape Info
*/
if (p = GetTapeInfo(DevGet->category_stat)) {
if (Device->dv_desc) {
(void) sprintf(Buf, "%s %s", p, Device->dv_desc);
free(Device->dv_desc);
Device->dv_desc = strdup(Buf);
} else {
Device->dv_desc = p;
}
}
/*
* Tapes should be on tape controllers.
*/
if (Device->dv_master)
Device->dv_master->dv_type = DT_TAPECTLR;
return(Device);
}
/*
* Get network type information
*/
static char *GetNetType(type)
int type;
{
extern NAMETAB NetTypes[];
register int i;
for (i = 0; NetTypes[i].name; i++)
if (NetTypes[i].value == type)
return(NetTypes[i].name);
return((char *) NULL);
}
#if defined(HAVE_PACKETFILTER)
#include <sys/time.h>
#include <net/pfilt.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
/*
* Find and set the MAC info using the Packet Filter
*/
extern void SetMacInfoPacketFilter(DevName, Netif, Device)
char *DevName;
NETIF *Netif;
DEVICE *Device;
{
struct endevp endevp;
struct ether_addr ether_addr;
char *ether_ntoa(), HostBuf[MAXHOSTNAMLEN+1];
char *p;
int Desc;
if (!DevName || !Netif)
return;
/*
* Open this device using the packet filter
*/
if ((Desc = pfopen(DevName, O_RDONLY)) < 0) {
if (Debug) Error("pfopen %s failed: %s.", DevName, SYSERR);
return;
}
/*
* Retrieve info
*/
if (ioctl(Desc, EIOCDEVP, &endevp) < 0) {
if (Debug) Error("ioctl EIOCDEVP of %s failed: %s.", DevName, SYSERR);
return;
}
close(Desc);
/*
* Convert address into ethers(5) format
*/
bcopy((char *) endevp.end_addr,
(char *) ether_addr.ether_addr_octet,
endevp.end_addr_len);
/*
* Set what we now know.
*/
if (p = ether_ntoa(ðer_addr))
Netif->ni_macaddr = strdup(p);
if (ether_ntohost(HostBuf, ðer_addr) == 0)
Netif->ni_macname = strdup(HostBuf);
if (Device && (p = GetNetType(endevp.end_dev_type)))
Device->dv_desc = p;
}
#endif /* HAVE_PACKETFILTER */
/*
* Get the system model name. Ultrix keeps the system type
* in a kernel structure called cpusw as cpusw.system_type.
* The system types are defined in <machine/cpuconf.h>.
*/
extern char *GetModelName()
{
extern NAMETAB ModelTab[];
extern struct nlist CpuSwNL[];
static struct cpusw CpuSw;
register int i;
kvm_t *kd;
if (!(kd = KVM_open(CpuSwNL))) {
if (Debug) Error("Cannot find cpusw symbol in kernel.");
return((char *) NULL);
}
/*
* See if we got a valid entry
*/
if (CheckNlist(&CpuSwNL[0]))
return((char *) NULL);
if (KVM_read(kd, (u_long) CpuSwNL[0].n_value, (char *) &CpuSw,
sizeof(struct cpusw))) {
if (Debug) Error("Cannot read cpusw from kernel.");
return((char *) NULL);
}
KVM_close(kd);
for (i = 0; ModelTab[i].name; ++i)
if (ModelTab[i].value == CpuSw.system_type)
return(ModelTab[i].name);
if (Debug)
printf("system model/type %d is unknown.\n", CpuSw.system_type);
return((char *) NULL);
}
/*
* Get kernel version string from kernel symbol "version".
*/
extern char *GetKernelVersionStr()
{
return(GetKernelVersionFromVersion());
}
/*
* Get amount of physical memory using kernel symbol "physmem".
*/
extern char *GetMemory()
{
return(GetMemoryFromPhysmem());
}
/*
* Get system serial number
*/
extern char *GetSerialNoStr()
{
/* No support */
return((char *) NULL);
}
/*
* Get name of OS
*/
extern char *GetOSNameStr()
{
return(GetOSNameFromUname());
}
/*
* Get version of OS
*/
extern char *GetOSVersionStr()
{
return(GetOSVersionFromUname());
}
/*
* Get ROM Version
*/
extern char *GetRomVer()
{
/* No support */
return((char *) NULL);
}