This is os-ultrix.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-ultrix.c,v 1.17 1992/12/12 23:48:04 mcooper Exp mcooper $"; #endif /* * $Log: os-ultrix.c,v $ * Revision 1.17 1992/12/12 23:48:04 mcooper * Call MkDevName() with correct number of parameters. * * Revision 1.16 1992/11/24 04:05:57 mcooper * New/cleaner KVM/nlist interface. * * Revision 1.15 1992/07/09 23:21:59 mcooper * Defining NEED_ETHER_ADDR will make things work under Ultrix 4.[01]. * * 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 char UniBusSYM[]; static struct nlist nlistbuf; struct nlist *nlptr; 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 = KVMopen())) return(-1); if ((nlptr = KVMnlist(kd, UniBusSYM, &nlistbuf)) == NULL) return(-1); if (CheckNlist(nlptr)) return(-1); /* * Read each device table entry. A NULL device.ui_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 unibus device from address 0x%x.", DeviceAddr); KVMclose(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 (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; cnum = -1; if (Addr = (u_long) Device.ui_mi) { if (KVMread(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 (KVMread(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); } KVMclose(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, 0, 0)); 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> #if defined(NEED_ETHER_ADDR) /* * This didn't appear in <netinet/if_ether.h> until Ultrix 4.2 (4.1?) */ struct ether_addr { u_char ether_addr_octet[6]; }; #endif /* NEED_ETHER_ADDR */ /* * 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[]; struct nlist *nlptr; extern char CpuSwSYM[]; static struct cpusw CpuSw; register int i; kvm_t *kd; if (!(kd = KVMopen())) return((char *) NULL); if ((nlptr = KVMnlist(kd, CpuSwSYM, (struct nlist *)NULL)) == NULL) return((char *) NULL); if (CheckNlist(nlptr)) return((char *) NULL); if (KVMread(kd, (u_long) nlptr->n_value, (char *) &CpuSw, sizeof(struct cpusw))) { if (Debug) Error("Cannot read cpusw from kernel."); return((char *) NULL); } KVMclose(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); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.