This is os-sunos.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-sunos.c,v 1.34 1992/11/24 04:05:57 mcooper Exp mcooper $";
#endif
/*
* $Log: os-sunos.c,v $
* Revision 1.34 1992/11/24 04:05:57 mcooper
* New/cleaner KVM/nlist interface.
*
* Revision 1.33 1992/11/12 19:12:43 mcooper
* Add declaration of OpenPROMTraverse().
*
* Revision 1.32 1992/08/11 01:33:14 mcooper
* Adjust format of Error() message.
*
* Revision 1.31 1992/07/07 22:25:06 mcooper
* Add Auspex support from Guy Harris (guy@auspex.com) as well
* as some cleanup of code format and phrasing of device information:
* Added an entry for the SPARCengine 1E (6U Eurocard based on the
* SPARCstation 1; there are also SS2-based and, coming up, SS10-based
* SPARCengines, although they're not VME cards).
*
* Changed the description of the FPA from "Wietek FPA" to "Sun-3 FPA" (it
* uses Weitek - not "Wietek" chips, but it's a Sun product), and expanded
* the extra description to note that it's Weitek-based.
*
* Added support for various devices on Auspex systems (which required
* adding a hack to get around a botch in the "mb_device" table in our
* current drivers for some of those devices).
*
* Separated disks from CD-ROMS, giving each its own probe routine; the
* disk probe routine will, if a CD-ROM in the drive happens to have a
* label (as some Sun CD-ROMs do, and as the Auspex system software
* distribution CD-ROM does), act as if the label is something it should
* report (it shouldn't; for example, it should report the disk as a
* CD-ROM, not whatever glop appears in the label).
*
* Fixed "ProbeTapeDrive()" to use the no-rewind device, so that it doesn't
* run the risk of rewinding the tape out from under somebody.
*
* Put comments at the front of the probe routines for tapes and CD-ROMs to
* indicate that they may fail even if the device exists - i.e., if there's
* no medium in the drive, or if somebody's using the tape drive;
* unfortunately, I don't know of a good fix for that problem.
*
* Revision 1.30 1992/04/26 23:51:53 mcooper
* Add some comments.
*
* Revision 1.28 1992/04/19 23:17:46 mcooper
* Suppress CodeCenter warning about "romp".
*
* Revision 1.27 1992/04/19 23:07:23 mcooper
* Update GetRomVer() to be more portable.
*
* Revision 1.26 1992/04/18 20:48:18 mcooper
* Add #ifdef HAVE_SUNROMVEC around GetRomVer.
*
* Revision 1.25 1992/04/17 23:27:51 mcooper
* Add support for ROM Version information (Sun only for now).
*
* Revision 1.24 1992/04/17 01:07:59 mcooper
* More de-linting
*
* Revision 1.23 1992/04/16 02:25:39 mcooper
* Bug fixes, de-linting, and other changes found with CodeCenter.
*
* Revision 1.22 1992/04/15 02:46:34 mcooper
* - Add better MainBus() and OPENPROM() build debug messages.
* - Make GetKernArchName() use "cpu" kernel symbol like GetModelName().
*
* Revision 1.21 1992/04/15 02:02:17 mcooper
* Change GetMemoryStr() to GetMemory().
*
* Revision 1.20 1992/04/12 22:03:56 mcooper
* - Change GetModelName() to use kernel symbol "cpu" instead
* of gethostid() to be more portable to other SPARC clones.
* - Update GetKernArchName() to support Solbourne CPU_TYPE.
* - Add HAVE_IPI kludge for "id" disks.
* - Various other cleanup bits.
*
* Revision 1.19 1992/03/31 01:55:17 mcooper
* Use new CheckNlist to check nlist success.
*
* Revision 1.18 1992/03/31 00:45:27 mcooper
* Fixed GetKernArchName() to use CPU_ARCH mask.
*
* Revision 1.17 1992/03/31 00:15:09 mcooper
* Add error check for nlist.n_type.
*
* Revision 1.16 1992/03/25 03:28:32 mcooper
* Skip partitions that have 0 size.
*
* Revision 1.15 1992/03/25 03:20:14 mcooper
* Only read partition info we we're going to print it later.
*
* Revision 1.14 1992/03/22 00:20:10 mcooper
* Major cleanup and re-org.
*
* Revision 1.13 1992/03/09 01:23:42 mcooper
* Add need include files for NIT stuff.
*
* Revision 1.12 1992/03/08 04:58:30 mcooper
* Move probe_generic() to devices.c.
*
* Revision 1.11 1992/03/06 18:37:26 mcooper
* Move some general functions to devices.c.
*
* Revision 1.10 1992/03/05 22:36:35 mcooper
* Cleanup format.
*
* Revision 1.9 1992/03/05 05:12:10 mcooper
* Cleanup build_mainbus().
*
* Revision 1.8 1992/03/01 23:30:15 mcooper
* More more SunOS specific code from sysinfo.c to here.
*
* Revision 1.7 1992/02/27 22:01:22 mcooper
* Add support for getting CPU info for sun4m.
*
* Revision 1.6 1992/02/27 20:36:52 mcooper
* Remove \n from error() messages.
*
* Revision 1.5 1992/02/26 19:07:21 mcooper
* Add a debug statement.
*
* Revision 1.4 1992/02/25 00:59:35 mcooper
* Move tape info to local MTINFO.
*
* Revision 1.3 1992/02/25 00:17:45 mcooper
* Lots of fixes and changes.
*
* Revision 1.2 1992/02/22 02:30:29 mcooper
* Fix fbtab stuff.
*
* Revision 1.1 1992/02/22 02:20:19 mcooper
* Initial revision
*
* Revision 1.5 1992/02/19 22:30:44 mcooper
* Fix calling problem.
*
* Revision 1.4 1992/02/17 01:00:23 mcooper
* - More portability and support for solbourne.
*
* Revision 1.3 1992/02/17 00:24:22 mcooper
* Update frame buffers.
*
* Revision 1.2 1992/02/16 22:55:44 mcooper
* Add netif support.
*
* Revision 1.1 1991/11/30 23:28:53 mcooper
* Initial revision
*
*/
#include <stdio.h>
#include "system.h"
#include "defs.h"
#include <mntent.h>
#include <nlist.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/buf.h>
#include <sys/stat.h>
#include <sys/mtio.h>
#include <sun/dkio.h>
#include <sun/dklabel.h>
#include <sun/fbio.h>
/*
* Name of frame buffer "indirect" device.
*/
#define FBDEVICE "fb"
/*
* Name of generic magnetic tape device.
*/
#define MTNAME "mt"
/*
* Generally used variables
*/
static kvm_t *kd = NULL;
static struct stat StatBuf;
static DEVICE *Device;
static char Buf[BUFSIZ];
extern char CpuSYM[];
extern char RomVecSYM[];
static int OpenPROMTraverse();
#if defined(HAVE_MAINBUS)
/*
* Build a device tree by searching the MainBus
*/
#include <sundev/mbvar.h>
#define DV_SIZE (sizeof(struct mb_device))
#define DR_SIZE (sizeof(struct mb_driver))
extern char MainBusSYM[];
/*
* Build device tree by looking at mainbus (mb) devices
*/
static int BuildMainBus(TreePtr)
DEVICE **TreePtr;
{
static struct nlist nlistbuf;
struct nlist *nlptr;
static struct mb_device Device;
static struct mb_driver Driver;
static char CtlrName[BUFSIZ], DevName[BUFSIZ];
static DEVDATA DevData;
u_long Addr, DeviceAddr;
DEVICE *Dev;
/*
* Read table address from kernel
*/
if (!(kd = KVMopen()))
return(-1);
if ((nlptr = KVMnlist(kd, MainBusSYM, &nlistbuf)) == NULL)
return(-1);
if (CheckNlist(nlptr))
return(-1);
/*
* Read each device table entry. A NULL device.mb_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 mainbus device from address 0x%x.",
DeviceAddr);
KVMclose(kd);
return(-1);
}
/*
* See if we're done.
*/
if (!Device.md_driver)
break;
/*
* Read the driver structure
*/
Addr = (u_long) Device.md_driver;
if (KVMread(kd, Addr, (char *) &Driver, DR_SIZE)) {
if (Debug)
Error("Cannot read driver for mainbus address 0x%x.", Addr);
continue;
}
/*
* Get the device name
*/
if (Addr = (u_long) Driver.mdr_dname) {
if (KVMread(kd, Addr, (char *) DevName, sizeof(DevName))) {
if (Debug)
Error("Cannot read device name from address 0x%x.", Addr);
continue;
}
} else
DevName[0] = C_NULL;
/*
* Get the controller name
* XXX - not if "Device.md_ctlr" is -1; work around botch
* in current Auspex releases, where some boards (File Processor,
* Primary Memory, etc.) have both a device and a controller name,
* despite the fact that there's not both a controller and a
* set of 1 or more devices.
*/
if ((Addr = (u_long) Driver.mdr_cname) && Device.md_ctlr != -1) {
if (KVMread(kd, Addr, (char *) CtlrName, sizeof(CtlrName))) {
if (Debug)
Error("Cannot read controller name from address 0x%x.",
Addr);
continue;
}
} else
CtlrName[0] = C_NULL;
/* 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.md_unit;
}
if (CtlrName[0]) {
DevData.dd_ctlrname = strdup(CtlrName);
DevData.dd_ctlrunit = Device.md_ctlr;
}
/*
* Mainbus devices such, as SCSI targets, may not exist
* but the controller reports them as present
*/
if (Device.md_alive)
DevData.dd_flags |= DD_MAYBE_ALIVE;
if (Debug)
printf("MainBus: Found \"%s\" (Unit %d) on \"%s\" (Unit %d) %s\n",
DevData.dd_devname, DevData.dd_devunit,
DevData.dd_ctlrname, DevData.dd_ctlrunit,
(DevData.dd_flags & DD_MAYBE_ALIVE) ? "[MAYBE-ALIVE]" : "");
/* Probe and add device */
if (Dev = ProbeDevice(&DevData, TreePtr))
AddDevice(Dev, TreePtr);
}
KVMclose(kd);
return(0);
}
#endif /* HAVE_MAINBUS */
#if defined(HAVE_OPENPROM)
/*
* OpenPROM stuff
*/
#include <sun/openprom.h>
extern char OpenPROMSYM[];
/*
* Build device tree by looking at OpenPROM (op)
*/
static int BuildOpenPROM(TreePtr)
DEVICE **TreePtr;
{
static struct nlist nlistbuf;
struct nlist *nlptr;
static struct dev_info Root, *PtrRoot;
u_long Addr;
if (!(kd = KVMopen()))
return(-1);
if ((nlptr = KVMnlist(kd, OpenPROMSYM, &nlistbuf)) == NULL)
return(-1);
if (CheckNlist(nlptr))
return(-1);
/*
* Read pointer to "top_devinfo" from kernel
*/
Addr = nlptr->n_value;
if (KVMread(kd, Addr, (char *) &PtrRoot, sizeof(struct dev_info *))) {
if (Debug) Error("Cannot read openprom devinfo pointer from kernel");
return(-1);
}
if (KVMread(kd, (u_long)PtrRoot, (char *)&Root,
sizeof(struct dev_info))) {
if (Debug) Error("Cannot read openprom devinfo root from kernel");
return(-1);
}
return(OpenPROMTraverse(&Root, NULL, TreePtr));
}
/*
* Check an OpenPROM device.
*/
static int CheckOpenPROMDevice(DevInfo, Parent, TreePtr)
struct dev_info *DevInfo;
struct dev_info *Parent;
DEVICE **TreePtr;
{
static DEVDATA DevData;
DEVICE *Device;
/* Make sure devdata is clean */
bzero(&DevData, sizeof(DEVDATA));
/* Set what we know */
if (DevInfo && DevInfo->devi_name) {
DevData.dd_devname = DevInfo->devi_name;
DevData.dd_devunit = DevInfo->devi_unit;
}
if (Parent && Parent->devi_name) {
DevData.dd_ctlrname = Parent->devi_name;
DevData.dd_ctlrunit = Parent->devi_unit;
}
/*
* OpenPROM nodes that have a driver ALWAYS exist.
* Some nodes may exist, without a driver, however.
*/
if (DevInfo->devi_driver)
DevData.dd_flags |= DD_IS_ALIVE;
if (Debug)
printf("OPENPROM: Found \"%s\" (Unit %d) on \"%s\" (Unit %d) %s\n",
DevData.dd_devname, DevData.dd_devunit,
DevData.dd_ctlrname, DevData.dd_ctlrunit,
(DevData.dd_flags & DD_IS_ALIVE) ? "[ALIVE]" : "");
/* Probe and add device */
if (Device = (DEVICE *) ProbeDevice(&DevData, TreePtr))
AddDevice(Device, TreePtr);
}
/*
* Recursively traverse and descend the OpenPROM devinfo tree.
*/
static int OpenPROMTraverse(DevPtr, Parent, TreePtr)
struct dev_info *DevPtr;
struct dev_info *Parent;
DEVICE **TreePtr;
{
static char Name[BUFSIZ];
struct dev_info *Ptr;
/*
* If node name is a valid pointer, read the name from kernel space
* and call openprom_probe to handle checking the device.
*/
if (DevPtr->devi_name) {
if (KVMread(kd, (u_long) DevPtr->devi_name, (char *) Name,
sizeof(Name))) {
Error("Cannot read openprom device name.");
Name[0] = C_NULL;
} else {
DevPtr->devi_name = (char *) strdup(Name);
CheckOpenPROMDevice(DevPtr, Parent, TreePtr);
}
}
/*
* If this node has slaves, read the slave data from kernel space
* and descend.
*/
if (DevPtr->devi_slaves) {
Ptr = (struct dev_info *) xcalloc(1, sizeof(struct dev_info));
if (KVMread(kd, (u_long) DevPtr->devi_slaves, (char *) Ptr,
sizeof(struct dev_info))) {
Error("Cannot read openprom slave data for %s.", Name);
} else {
DevPtr->devi_slaves = (struct dev_info *) Ptr;
OpenPROMTraverse(DevPtr->devi_slaves, DevPtr, TreePtr);
}
}
/*
* If this node has a next pointer, read the next data from kernel space
* and traverse.
*/
if (DevPtr->devi_next) {
Ptr = (struct dev_info *) xcalloc(1, sizeof(struct dev_info));
if (KVMread(kd, (u_long) DevPtr->devi_next, (char *) Ptr,
sizeof(struct dev_info))) {
Error("Cannot read openprom next data for %s.", Name);
} else {
DevPtr->devi_next = (struct dev_info *) Ptr;
OpenPROMTraverse(DevPtr->devi_next, Parent, TreePtr);
}
}
return(0);
}
#endif /* HAVE_OPENPROM */
/*
* Build device tree using TreePtr.
* Calls bus and method specific functions to
* search for devices.
*/
extern int BuildDevicesSunOS(TreePtr)
DEVICE **TreePtr;
{
int Found = 1;
#if defined(HAVE_OPENPROM)
if (BuildOpenPROM(TreePtr) == 0)
Found = 0;
#endif /* HAVE_OPENPROM */
#if defined(HAVE_MAINBUS)
if (BuildMainBus(TreePtr) == 0)
Found = 0;
#endif /* HAVE_MAINBUS */
return(Found);
}
/*
* Scan the Disk Controller table looking for
* a specific type.
*/
static DKCTLRTAB *GetDkCtlrTab(DkCtrlType)
int DkCtrlType;
{
extern DKCTLRTAB DkCtlrTab[];
register int i;
for (i = 0; DkCtlrTab[i].ct_model; ++i) {
if (DkCtrlType == DkCtlrTab[i].ct_ctype)
return(&DkCtlrTab[i]);
}
return((DKCTLRTAB *) NULL);
}
/*
* Scan the Frame Buffer table looking for
* a specific fb type.
*/
static NAMETAB *GetFBTab(FBType)
int FBType;
{
extern NAMETAB FBTab[];
register int i;
for (i = 0; FBTab[i].name; ++i) {
if (FBType == FBTab[i].value)
return(&FBTab[i]);
}
return((NAMETAB *) NULL);
}
/*
* Get disk info structure.
*/
static struct dk_info *GETdk_info(d, file)
int d;
char *file;
{
static struct dk_info dk_info;
if (ioctl(d, DKIOCINFO, &dk_info) < 0) {
if (Debug) Error("%s: DKIOCINFO: %s.", file, SYSERR);
return(NULL);
}
return(&dk_info);
}
/*
* Get disk configuration structure.
*/
static struct dk_conf *GETdk_conf(d, file)
int d;
char *file;
{
static struct dk_conf dk_conf;
if (ioctl(d, DKIOCGCONF, &dk_conf) < 0) {
if (Debug) Error("%s: DKIOCGCONF: %s.", file, SYSERR);
return(NULL);
}
return(&dk_conf);
}
/*
* Get disk geometry structure.
*/
static struct dk_geom *GETdk_geom(d, file)
int d;
char *file;
{
static struct dk_geom dk_geom;
if (ioctl(d, DKIOCGGEOM, &dk_geom) < 0) {
if (Debug) Error("%s: DKIOCGGEOM: %s.", file, SYSERR);
return(NULL);
}
return(&dk_geom);
}
/*
* Get disk type structure.
*/
static struct dk_type *GETdk_type(d, file)
int d;
char *file;
{
static struct dk_type dk_type;
if (ioctl(d, DKIOCGTYPE, &dk_type) < 0) {
if (errno != ENOTTY)
if (Debug) Error("%s: DKIOCGTYPE: %s.", file, SYSERR);
return(NULL);
}
return(&dk_type);
}
/*
* Check the checksum of a disklabel.
*/
static int DkLblCheckSum(DkLabel)
struct dk_label *DkLabel;
{
register short *Ptr, Sum = 0;
register short Count;
Count = (sizeof (struct dk_label)) / (sizeof (short));
Ptr = (short *)DkLabel;
/*
* Take the xor of all the half-words in the label.
*/
while (Count--)
Sum ^= *Ptr++;
/*
* The total should be zero for a correct checksum
*/
return(Sum);
}
/*
* Get label information from label on disk.
* The label is stored in the first sector of the disk.
* We use the driver specific "read" flag with the DKIOCSCMD
* ioctl to read the first sector. There should be a special
* ioctl to just read the label.
*/
static struct dk_label *GETdk_label(d, file, dk_info)
int d;
char *file;
struct dk_info *dk_info;
{
static struct dk_label dk_label;
struct dk_cmd dk_cmd;
struct dkctlrtab *pct;
if (!file || !dk_info)
return((struct dk_label *) NULL);
if (!(pct = GetDkCtlrTab((int) dk_info->dki_ctype))) {
Error("Controller type %d is unknown.",
dk_info->dki_ctype);
return((struct dk_label *) NULL);
}
if (pct->ct_rdcmd < 0) {
if (Debug)
Error("Read block on controller type \"%s\" is unsupported.",
pct->ct_model);
return((struct dk_label *) NULL);
}
bzero((char *) &dk_cmd, sizeof(dk_cmd));
dk_cmd.dkc_cmd = pct->ct_rdcmd;
dk_cmd.dkc_flags = DK_SILENT | DK_ISOLATE;
dk_cmd.dkc_blkno = (daddr_t)0;
dk_cmd.dkc_secnt = 1;
dk_cmd.dkc_bufaddr = (char *) &dk_label;
dk_cmd.dkc_buflen = SECSIZE;
if (ioctl(d, DKIOCSCMD, &dk_cmd) < 0) {
if (Debug) Error("%s: DKIOCSCMD: %s.", file, SYSERR);
return((struct dk_label *) NULL);
}
if (dk_label.dkl_magic != DKL_MAGIC) {
Error("%s: Disk not labeled.", file);
return((struct dk_label *) NULL);
}
if (DkLblCheckSum(&dk_label)) {
Error("%s: Bad label checksum.", file);
return((struct dk_label *) NULL);
}
return(&dk_label);
}
/*
* Get the name of a disk (i.e. sd0).
*/
static char *GetDiskName(name, dk_conf, dk_info)
char *name;
struct dk_conf *dk_conf;
struct dk_info *dk_info;
{
if (!dk_conf || !dk_info) {
if (name)
return(name);
return((char *) NULL);
}
#if defined(DKI_HEXUNIT)
if (FLAGS_ON(dk_info->dki_flags, DKI_HEXUNIT))
(void) sprintf(Buf, "%s%3.3x", dk_conf->dkc_dname, dk_conf->dkc_unit);
else
#endif /* DKI_HEXUNIT */
(void) sprintf(Buf, "%s%d", dk_conf->dkc_dname, dk_conf->dkc_unit);
return(strdup(Buf));
}
/*
* Get the name of the controller for a disk.
*/
static char *GetDkCtlrName(dk_conf)
struct dk_conf *dk_conf;
{
if (!dk_conf)
return((char *) NULL);
(void) sprintf(Buf, "%s%d", dk_conf->dkc_cname, dk_conf->dkc_cnum);
return(strdup(Buf));
}
/*
* Get the disk controller model name from a disk.
*/
static char *GetDkCtlrModel(dk_info)
struct dk_info *dk_info;
{
struct dkctlrtab *pct;
if (!dk_info)
return((char *) NULL);
if (!(pct = GetDkCtlrTab(dk_info->dki_ctype)))
return(NULL);
return(pct->ct_model);
}
/*
* Get a disk controller device from disk info.
*/
static DEVICE *GetDkCtlrDevice(DevData, dk_info, dk_conf)
DEVDATA *DevData;
struct dk_info *dk_info;
struct dk_conf *dk_conf;
{
DEVICE *MkMasterFromDevData();
DEVICE *dkctlr;
if ((dkctlr = NewDevice(NULL)) == NULL)
return((DEVICE *) NULL);
bzero((char *) dkctlr, sizeof(*dkctlr));
dkctlr->dv_type = DT_DISKCTLR;
/*
* Get name of controller from devdata if available
*/
if (DevData && DevData->dd_ctlrname) {
dkctlr = MkMasterFromDevData(DevData);
}
if (dk_conf) {
if (!dkctlr->dv_name) {
dkctlr->dv_name = GetDkCtlrName(dk_conf);
dkctlr->dv_unit = dk_conf->dkc_cnum;
}
dkctlr->dv_addr = dk_conf->dkc_addr;
dkctlr->dv_prio = dk_conf->dkc_prio;
dkctlr->dv_vec = dk_conf->dkc_vec;
}
if (dk_info) {
dkctlr->dv_model = GetDkCtlrModel(dk_info);
}
return(dkctlr);
}
/*
* Get disk label info from the extracted dk_label info.
*/
static char *GetDiskLabel(dk_label)
struct dk_label *dk_label;
{
register char *p;
if (!dk_label)
return((char *) NULL);
(void) strcpy(Buf, dk_label->dkl_asciilabel);
/*
* The label normally has geometry information in it we don't want
* to see, so we trim out anything starting with " cyl".
*/
for (p = Buf; p && *p; ++p) {
if (*p == ' ' && strncasecmp(p, " cyl", 4) == 0)
*p = C_NULL;
}
return(strdup(Buf));
}
/*
* 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);
}
/*
* Extract the disk partition info from a disk.
*/
static DISKPART *ExtractDiskPart(name, part, dk_conf, dk_geom)
char *name;
char *part;
struct dk_conf *dk_conf;
struct dk_geom *dk_geom;
{
static DISKPART diskpart;
struct dk_map dk_map;
char *file;
char *p;
int d;
if (!name || !dk_conf || !dk_geom)
return((DISKPART *) NULL);
file = GetRawFile(name, part);
if (stat(file, &StatBuf) != 0) {
if (Debug) Error("%s: No such partition.", file);
return((DISKPART *) NULL);
}
if ((d = open(file, O_RDONLY)) < 0) {
if (Debug)
Error("%s: Cannot open for read: %s.", file, SYSERR);
return((DISKPART *) NULL);
}
if (ioctl(d, DKIOCGPART, &dk_map) != 0) {
Error("%s: Cannot extract partition info: %s.",
file, SYSERR);
return((DISKPART *) NULL);
}
(void) close(d);
/*
* Skip empty partitions
*/
if (!dk_map.dkl_nblk) {
if (Debug) Error("%s: partition has no size.", file);
return((DISKPART *) NULL);
}
bzero((char *) &diskpart, sizeof(DISKPART));
diskpart.dp_name = strdup(part);
if (p = GetMountInfo(name, part))
diskpart.dp_mnt = strdup(p);
/*
* If this is the "b" partition on the root device,
* then assume it's swap
*/
else if (dk_conf->dkc_unit == 0 && strcmp(part, "b") == 0)
diskpart.dp_mnt = "swap";
diskpart.dp_stsect = dk_map.dkl_cylno *
(dk_geom->dkg_nhead * dk_geom->dkg_nsect);
diskpart.dp_nsect = dk_map.dkl_nblk;
return(&diskpart);
}
/*
* Translate disk partition information from basic
* extracted disk info.
*/
static DISKPART *GetDiskPart(name, dk_conf, dk_geom)
char *name;
struct dk_conf *dk_conf;
struct dk_geom *dk_geom;
{
extern char PartChars[];
register DISKPART *pdp, *dp;
register int i;
static char pname[2];
DISKPART *base = NULL;
if (!name || !dk_conf || !dk_geom)
return((DISKPART *) NULL);
pname[1] = C_NULL;
for (i = 0; PartChars[i]; ++i) {
pname[0] = PartChars[i];
if (dp = ExtractDiskPart(name, pname, dk_conf, dk_geom)) {
if (base) {
for (pdp = base; pdp && pdp->dp_nxt; pdp = pdp->dp_nxt);
pdp->dp_nxt = NewDiskPart(dp);
} else {
base = NewDiskPart(dp);
}
}
}
return(base);
}
/*
* Convert all we've learned about a disk to a DEVICE.
*/
static DEVICE *dkToDiskDevice(name, DevData,
dk_info, dk_label, dk_conf, dk_geom, dk_type)
char *name;
DEVDATA *DevData;
struct dk_info *dk_info;
struct dk_label *dk_label;
struct dk_conf *dk_conf;
struct dk_geom *dk_geom;
struct dk_type *dk_type;
{
DEVICE *Device, *dkctlr;
DISKDRIVE *diskdrive;
if ((Device = NewDevice(NULL)) == NULL) {
Error("Cannot create new device entry.");
return((DEVICE *) NULL);
}
if ((dkctlr = NewDevice(NULL)) == NULL) {
Error("Cannot create new dkctlr device entry.");
return((DEVICE *) NULL);
}
if ((diskdrive = NewDiskDrive(NULL)) == NULL) {
Error("Cannot create new diskdrive entry.");
return((DEVICE *) NULL);
}
Device->dv_name = GetDiskName(name, dk_conf, dk_info);
Device->dv_type = DT_DISKDRIVE;
/*
* Only read partition info we we're going to print it later.
*/
if (VL_ALL)
diskdrive->dd_part = GetDiskPart(name, dk_conf, dk_geom);
diskdrive->dd_label = GetDiskLabel(dk_label);
Device->dv_model = diskdrive->dd_label;
if (dk_conf) {
diskdrive->dd_unit = dk_conf->dkc_unit;
diskdrive->dd_slave = dk_conf->dkc_slave;;
}
if (dk_geom) {
diskdrive->dd_dcyl = dk_geom->dkg_ncyl;
diskdrive->dd_pcyl = dk_geom->dkg_pcyl;
diskdrive->dd_acyl = dk_geom->dkg_acyl;
diskdrive->dd_heads = dk_geom->dkg_nhead;
diskdrive->dd_sect = dk_geom->dkg_nsect;
diskdrive->dd_apc = dk_geom->dkg_apc;
diskdrive->dd_rpm = dk_geom->dkg_rpm;
diskdrive->dd_intrlv = dk_geom->dkg_intrlv;
}
if (dk_type) {
diskdrive->dd_psect = dk_type->dkt_hsect;
diskdrive->dd_promrev = dk_type->dkt_promrev;
}
if (dk_info) {
#if defined(DKI_HEXUNIT)
if (FLAGS_ON(dk_info->dki_flags, DKI_HEXUNIT))
diskdrive->dd_flags |= DF_HEXUNIT;
#endif /* DKI_HEXUNIT */
}
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);
}
dkctlr = GetDkCtlrDevice(DevData, dk_info, dk_conf);
Device->dv_devspec = (caddr_t *) diskdrive;
Device->dv_master = dkctlr;
return(Device);
}
/*
* Convert all we've learned about a CD-ROM drive to a DEVICE.
*/
static DEVICE *dkToCDROMDevice(name, DevData,
dk_info, dk_conf, dk_geom, dk_type)
char *name;
DEVDATA *DevData;
struct dk_info *dk_info;
struct dk_conf *dk_conf;
struct dk_geom *dk_geom;
struct dk_type *dk_type;
{
DEVICE *Device, *dkctlr;
DISKDRIVE *diskdrive;
if ((Device = NewDevice(NULL)) == NULL) {
Error("Cannot create new device entry.");
return((DEVICE *) NULL);
}
if ((dkctlr = NewDevice(NULL)) == NULL) {
Error("Cannot create new dkctlr device entry.");
return((DEVICE *) NULL);
}
if ((diskdrive = NewDiskDrive(NULL)) == NULL) {
Error("Cannot create new diskdrive entry.");
return((DEVICE *) NULL);
}
Device->dv_name = GetDiskName(name, dk_conf, dk_info);
Device->dv_type = DT_DISKDRIVE;
/*
* Only read partition info we we're going to print it later.
*/
if (VL_ALL)
diskdrive->dd_part = GetDiskPart(name, dk_conf, dk_geom);
diskdrive->dd_label = NULL;
Device->dv_model = "CD-ROM";
if (dk_conf) {
diskdrive->dd_unit = dk_conf->dkc_unit;
diskdrive->dd_slave = dk_conf->dkc_slave;;
}
if (dk_geom) {
diskdrive->dd_dcyl = dk_geom->dkg_ncyl;
diskdrive->dd_pcyl = dk_geom->dkg_pcyl;
diskdrive->dd_acyl = dk_geom->dkg_acyl;
diskdrive->dd_heads = dk_geom->dkg_nhead;
diskdrive->dd_sect = dk_geom->dkg_nsect;
diskdrive->dd_apc = dk_geom->dkg_apc;
diskdrive->dd_rpm = dk_geom->dkg_rpm;
diskdrive->dd_intrlv = dk_geom->dkg_intrlv;
}
if (dk_type) {
diskdrive->dd_psect = dk_type->dkt_hsect;
diskdrive->dd_promrev = dk_type->dkt_promrev;
}
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);
}
dkctlr = GetDkCtlrDevice(DevData, dk_info, dk_conf);
Device->dv_devspec = (caddr_t *) diskdrive;
Device->dv_master = dkctlr;
return(Device);
}
/*
* Query and learn about a disk.
*/
extern DEVICE *ProbeDiskDrive(name, DevData, DevDataTab)
/*ARGSUSED*/
char *name;
DEVDATA *DevData;
DEVDATATAB *DevDataTab;
{
DEVICE *diskdevice;
struct dk_info *dk_info = NULL;
struct dk_conf *dk_conf = NULL;
struct dk_type *dk_type = NULL;
struct dk_label *dk_label = NULL;
struct dk_geom *dk_geom = NULL;
char *rfile;
int d;
if (!name)
return((DEVICE *) NULL);
#if defined(HAVE_IPI)
/*
* XXX - Kludge for IPI "id" disks.
*/
if (EQ(DevData->dd_devname, "id")) {
static char Buf[BUFSIZ];
(void) sprintf(Buf, "%s%3.3x",
DevData->dd_devname, DevData->dd_devunit);
name = Buf;
}
#endif /* HAVE_IPI */
if (stat(rfile = GetRawFile(name, NULL), &StatBuf) != 0) {
/*
* Get the name of the whole disk raw device.
*/
rfile = GetRawFile(name, "c");
}
if ((d = open(rfile, O_RDONLY)) < 0) {
if (Debug) Error("%s: Cannot open for reading: %s.", rfile, 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);
}
if ((dk_conf = GETdk_conf(d, rfile)) == NULL) {
if (Debug) Error("%s: get dk_conf failed.", rfile);
}
if ((dk_info = GETdk_info(d, rfile)) == NULL) {
if (Debug) Error("%s: get dk_info failed.", rfile);
}
if ((dk_geom = GETdk_geom(d, rfile)) == NULL) {
if (Debug) Error("%s: get dk_geom failed.", rfile);
}
if ((dk_label = GETdk_label(d, rfile, dk_info)) == NULL) {
if (Debug) Error("%s: get dk_label failed.", rfile);
}
/*
* Not all controllers support dk_type
*/
dk_type = GETdk_type(d, rfile);
close(d);
if (!(diskdevice = dkToDiskDevice(name, DevData,
dk_info, dk_label,
dk_conf, dk_geom, dk_type))) {
Error("%s: Cannot convert diskdrive information.", name);
return((DEVICE *) NULL);
}
return(diskdevice);
}
/*
* Probe a tape device
* XXX - this loses if somebody's using the tape, as tapes are exclusive-open
* devices, and our open will therefore fail.
* This also loses if there's no tape in the drive, as the open will fail.
* The above probably applies to most other flavors of UNIX.
*/
extern DEVICE *ProbeTapeDrive(name, DevData, DevDataTab)
/*ARGSUSED*/
char *name;
DEVDATA *DevData;
DEVDATATAB *DevDataTab;
{
extern NAMETAB MtInfo[];
DEVICE *Device;
char *file;
char *model = NULL;
char rfile[BUFSIZ];
static char Buf[BUFSIZ];
struct mtget mtget;
register int i;
int d;
/*
* Don't use GetRawFile; that'll just stick an "r" in front of the
* device name, meaning it'll return the rewind-on-close device.
* Somebody may have left the tape positioned somewhere other than
* at the BOT to, for example, write a dump there later in the
* evening; it'd be rather rude to reposition it out from under them.
*
* The above probably applies to most other flavors of UNIX.
*/
if (!name)
file = NULL;
else {
(void) sprintf(rfile, "/dev/nr%s", name);
file = rfile;
}
if ((d = open(file, O_RDONLY)) < 0) {
if (Debug)
Error("%s Cannot open for read: %s.", file, SYSERR);
/*
* --RECURSE--
* If we haven't tried the "mt" name yet, try it now
*/
if (strncmp(name, MTNAME, strlen(MTNAME)) != 0) {
(void) sprintf(Buf, "%s%d", MTNAME, DevData->dd_devunit);
Device = ProbeTapeDrive(Buf, DevData, DevDataTab);
if (Device)
return(Device);
}
/*
* 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);
/*
* Recreate name from devdata since we might have had to
* call ourself with name "rmt?"
*/
(void) sprintf(Buf, "%s%d", DevData->dd_devname,
DevData->dd_devunit);
Device->dv_name = strdup(Buf);
Device->dv_unit = DevData->dd_devunit;
Device->dv_master = MkMasterFromDevData(DevData);
Device->dv_type = DT_TAPEDRIVE;
Device->dv_model = DevDataTab->ddt_model;
Device->dv_desc = DevDataTab->ddt_desc;
return(Device);
} else
return((DEVICE *) NULL);
}
if (ioctl(d, MTIOCGET, &mtget) != 0) {
Error("%s: Cannot extract tape status: %s.", file, SYSERR);
return((DEVICE *) NULL);
}
(void) close(d);
model = "unknown";
for (i = 0; MtInfo[i].name; ++i) {
if ((MtInfo[i].value == mtget.mt_type)) {
model = MtInfo[i].name;
break;
}
}
/*
* Create and set device info
*/
Device = NewDevice(NULL);
Device->dv_name = strdup(name);
Device->dv_type = DT_TAPEDRIVE;
if (model)
Device->dv_model = model;
else
Device->dv_model = DevDataTab->ddt_model;
Device->dv_desc = DevDataTab->ddt_desc;
Device->dv_unit = DevData->dd_devunit;
Device->dv_master = MkMasterFromDevData(DevData);
return(Device);
}
/*
* Query and learn about a CD-ROM drive.
* We don't just use ProbeDisk Drive so that we don't get confused if
* the CD-ROM in the drive has a label.
* XXX - this loses if there's no caddy in the drive, as the open will fail.
*/
extern DEVICE *ProbeCDROMDrive(name, DevData, DevDataTab)
/*ARGSUSED*/
char *name;
DEVDATA *DevData;
DEVDATATAB *DevDataTab;
{
DEVICE *diskdevice;
struct dk_info *dk_info = NULL;
struct dk_conf *dk_conf = NULL;
struct dk_type *dk_type = NULL;
struct dk_geom *dk_geom = NULL;
char *rfile;
int d;
if (!name)
return((DEVICE *) NULL);
rfile = GetRawFile(name, NULL);
if ((d = open(rfile, O_RDONLY)) < 0) {
if (Debug) Error("%s: Cannot open for reading: %s.", rfile, 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);
}
if ((dk_conf = GETdk_conf(d, rfile)) == NULL) {
if (Debug) Error("%s: get dk_conf failed.", rfile);
}
if ((dk_info = GETdk_info(d, rfile)) == NULL) {
if (Debug) Error("%s: get dk_info failed.", rfile);
}
if ((dk_geom = GETdk_geom(d, rfile)) == NULL) {
if (Debug) Error("%s: get dk_geom failed.", rfile);
}
/*
* Not all controllers support dk_type
*/
dk_type = GETdk_type(d, rfile);
close(d);
if (!(diskdevice = dkToCDROMDevice(name, DevData,
dk_info, dk_conf, dk_geom,
dk_type))) {
Error("%s: Cannot convert CD-ROM drive information.", name);
return((DEVICE *) NULL);
}
return(diskdevice);
}
/*
* Query and learn about a device attached to an Auspex Storage Processor.
* They'll show up as "ad" in the Mainbus info structure, but that
* merely reflects the way the slots are set up in the config file.
* We need to find out what type of device it is at this particular
* instant (it's subject to change - perhaps even while we're running,
* but there's not a heck of a lot we can do about that).
*
* We do that by trying it as a CD-ROM first, then as a disk, then as
* a tape; that loses if it's a tape and somebody's using it, but
* tapes on most if not all UNIX systems can't be probed by us if
* somebody's using it.
* The reason why we try it first as a CD-ROM is that if the CD has a
* partition table, the Auspex driver lets you open the partitions as
* if it were a disk.
*/
extern DEVICE *ProbeSPDrive(name, DevData, DevDataTab)
/*ARGSUSED*/
char *name;
DEVDATA *DevData;
DEVDATATAB *DevDataTab;
{
DEVICE *thedevice;
char devname[BUFSIZ];
/*
* Try it first as a CD-ROM.
*/
(void) sprintf(devname, "acd%d", DevData->dd_devunit);
DevData->dd_devname = "acd";
DevDataTab->ddt_model = "CD-ROM";
if (thedevice = ProbeCDROMDrive(devname, DevData, DevDataTab))
return(thedevice);
/*
* Not a CD-ROM. Try a disk.
*/
(void) sprintf(devname, "ad%d", DevData->dd_devunit);
DevData->dd_devname = "ad";
DevDataTab->ddt_model = NULL;
if (thedevice = ProbeDiskDrive(devname, DevData, DevDataTab))
return(thedevice);
/*
* Not a disk. Try a tape.
*/
(void) sprintf(devname, "ast%d", DevData->dd_devunit);
DevData->dd_devname = "ast";
if (thedevice = ProbeTapeDrive(devname, DevData, DevDataTab))
return(thedevice);
/*
* None of the above. Who knows?
*/
return((DEVICE *) NULL);
}
/*
* Probe a CPU.
*
* This function really "fakes" up an entry.
*
* XXX Currently the info only comes from the OpenPROM. This should
* be converted to use the kernel mach_info and mod_info structures.
*/
extern DEVICE *ProbeCPU(name, DevData, DevDataTab)
/*ARGSUSED*/
char *name;
DEVDATA *DevData;
DEVDATATAB *DevDataTab;
{
static int num_cpus = 0;
Device = NewDevice(NULL);
(void) sprintf(Buf, "cpu%d", num_cpus++);
Device->dv_name = strdup(Buf);
Device->dv_type = DT_CPU;
Device->dv_model = strdup(name);
Device->dv_desc = DevDataTab->ddt_desc;
Device->dv_master = MkMasterFromDevData(DevData);
return(Device);
}
/*
* Probe a FrameBuffer.
*/
extern DEVICE *ProbeFrameBuffer(name, DevData, DevDataTab)
char *name;
DEVDATA *DevData;
DEVDATATAB *DevDataTab;
{
DEVICE *fbdevice;
FRAMEBUFFER *fb;
NAMETAB *fbtab;
struct fbgattr fbattr;
#ifdef FBIOGXINFO
struct cg6_info cg6_info;
#endif
char *file, Buf[BUFSIZ];
int d;
if (!name)
return((DEVICE *) NULL);
/*
* Check the device file. If the stat fails because
* the device doesn't exist, trying the default framebuffer
* device /dev/fb.
*/
file = GetCharFile(name, NULL);
if (stat(file, &StatBuf) != 0) {
if (errno == ENOENT && !EQ(name, FBDEVICE)) {
if (Debug)
Error("Framebuffer device %s does not exist. Trying `fb'.",
name);
return(ProbeFrameBuffer(FBDEVICE, DevData, DevDataTab));
}
}
if ((d = open(file, O_RDONLY)) < 0) {
if (Debug) Error("%s: Cannot open for reading: %s.", file, SYSERR);
return((DEVICE *) NULL);
}
if (ioctl(d, FBIOGATTR, &fbattr) != 0) {
if (ioctl(d, FBIOGTYPE, &fbattr.fbtype) != 0) {
if (Debug) Error("%s: FBIOGATTR/FBIOGTYPE: %s.",
file, SYSERR);
return((DEVICE *) NULL);
}
}
Buf[0] = C_NULL;
#if defined(FBIOGXINFO)
if (ioctl(d, FBIOGXINFO, &cg6_info) == 0) {
sprintf(Buf, "SBus Slot %d, Revision %d",
cg6_info.slot, cg6_info.boardrev);
if (cg6_info.hdb_capable)
(void) strcat(Buf, ", double buffered");
else
(void) strcat(Buf, ", single buffered");
} else {
bzero((char *) &cg6_info, sizeof(struct cg6_info));
if (Debug) Error("%s: FBIOGXINFO: %s.", file, SYSERR);
}
#endif /* FBIOGXINFO */
close(d);
if (!(fb = NewFrameBuffer(NULL))) {
Error("Cannot create new frame buffer.");
return((DEVICE *) NULL);
}
if (!(fbdevice = NewDevice(NULL))) {
Error("Cannot create new frame buffer device entry.");
return((DEVICE *) NULL);
}
if (!(fbtab = GetFBTab(fbattr.fbtype.fb_type))) {
Error("Device %s is an unknown type (%d) of frame buffer.",
name, fbattr.fbtype.fb_type);
}
fbdevice->dv_name = name;
fbdevice->dv_type = DT_FRAMEBUFFER;
fbdevice->dv_devspec = (caddr_t *) fb;
if (Buf[0])
fbdevice->dv_desc = strdup(Buf);
if (fbtab) {
fbdevice->dv_model = fbtab->name;
} else {
fbdevice->dv_model = "UNKNOWN";
}
fb->fb_height = fbattr.fbtype.fb_height;
fb->fb_width = fbattr.fbtype.fb_width;
fb->fb_depth = fbattr.fbtype.fb_depth;
fb->fb_size = fbattr.fbtype.fb_size;
fb->fb_cmsize = fbattr.fbtype.fb_cmsize;
#if defined(FBIOGXINFO)
if (cg6_info.vmsize)
fb->fb_vmsize = mbytes_to_bytes(cg6_info.vmsize);
#endif /* FBIOGXINFO */
fbdevice->dv_master = MkMasterFromDevData(DevData);
return(fbdevice);
}
/*
* Determine our cpu model name.
*
* We lookup the kernel symbol "cpu" instead of using gethostid()
* because some SPARC vendors do not encode cpu/model info in gethostid().
*/
extern char *GetModelName()
{
extern NAMETAB ModelTab[];
struct nlist *nlptr;
register int i;
int Cpu;
kvm_t *kd;
if (!(kd = KVMopen()))
return((char *) NULL);
if ((nlptr = KVMnlist(kd, CpuSYM, (struct nlist *)NULL)) == NULL)
return((char *) NULL);
if (CheckNlist(nlptr))
return((char *) NULL);
if (KVMread(kd, (u_long) nlptr->n_value, (char *) &Cpu, sizeof(Cpu))) {
if (Debug) Error("Cannot read cpu from kernel.");
return((char *) NULL);
}
KVMclose(kd);
for (i = 0; ModelTab[i].name; ++i)
if (Cpu == ModelTab[i].value)
return(ModelTab[i].name);
if (Debug)
Error("No model found; CPU = 0x%x.", Cpu);
return((char *) NULL);
}
#if defined(CPU_ARCH) /* Sun */
#define ARCH_MASK CPU_ARCH
#endif /* CPU_ARCH */
#if defined(CPU_TYPE) /* Solbourne */
#define ARCH_MASK CPU_TYPE
#endif /* CPU_TYPE */
/*
* Determine our kernel architecture name from our hostid.
*/
extern char *GetKernArchName()
{
#if defined(ARCH_MASK)
extern NAMETAB KernArchTab[];
struct nlist *nlptr;
kvm_t *kd;
int Cpu;
register int i;
if (!(kd = KVMopen()))
return((char *) NULL);
if ((nlptr = KVMnlist(kd, CpuSYM, (struct nlist *)NULL)) == NULL)
return((char *) NULL);
if (CheckNlist(nlptr))
return((char *) NULL);
if (KVMread(kd, (u_long) nlptr->n_value, (char *) &Cpu, sizeof(Cpu))) {
if (Debug) Error("Cannot read cpu from kernel.");
return((char *) NULL);
}
KVMclose(kd);
for (i = 0; KernArchTab[i].name; ++i)
if ((Cpu & ARCH_MASK) == KernArchTab[i].value)
return(KernArchTab[i].name);
if (Debug)
Error("Kernel Arch 0x%x not defined; Cpu = 0x%x Mask = 0x%x",
Cpu & ARCH_MASK, Cpu, ARCH_MASK);
#endif /* ARCH_MASK */
return((char *) NULL);
}
#if defined(HAVE_NIT)
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/nit_if.h>
/*
* Find and set the MAC info using the Network Interface Tap (NIT)
*/
extern void SetMacInfoNIT(DevName, NetIf)
char *DevName;
NETIF *NetIf;
{
register struct sockaddr *SockAddr;
struct ifreq ifreq;
char *ether_ntoa(), Buf[MAXHOSTNAMLEN+1];
int Desc;
if (!NetIf)
return;
if ((Desc = open("/dev/nit", O_RDONLY)) == SYSFAIL) {
if (Debug) Error("open /dev/nit failed");
return;
}
/*
* Bind to NIT for DevName
*/
strncpy(ifreq.ifr_name, DevName, sizeof ifreq.ifr_name);
if (ioctl(Desc, NIOCBIND, (caddr_t) &ifreq) < 0) {
if (Debug) Error("ioctl: NIOCBIND");
return;
}
/*
* Get address
*/
if (ioctl(Desc, SIOCGIFADDR, (caddr_t)&ifreq) < 0) {
if (Debug) Error("ioctl (SIOCGIFADDR)");
return;
}
(void) close(Desc);
SockAddr = (struct sockaddr *)&ifreq.ifr_addr;
NetIf->ni_macaddr = strdup(ether_ntoa((struct ether_addr *)
SockAddr->sa_data));
if (ether_ntohost(Buf, (struct ether_addr *) SockAddr->sa_data) == 0)
NetIf->ni_macname = strdup(Buf);
}
#endif /* HAVE_NIT */
/*
* 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());
}
#if defined(HAVE_SUNROMVEC)
/*
* Be backwards compatible with pre-4.1.2 code
*/
#include <mon/sunromvec.h>
#if defined(OPENPROMS) && !(defined(ROMVEC_VERSION) && \
(ROMVEC_VERSION == 0 || ROMVEC_VERSION == 1))
#define v_mon_id op_mon_id
#endif
#endif /* HAVE_SUNROMVEC */
/*
* Get ROM Version number
*
* If "romp" is "defined" (in <mon/sunromvec.h>), then take that
* as the address of the kernel pointer to "rom" (struct sunromvec).
* Otherwise, nlist "romp" from the kernel.
*/
extern char *GetRomVer()
{
static char RomRev[16];
struct nlist *nlptr;
#if defined(HAVE_SUNROMVEC)
static struct sunromvec Rom;
register char *p;
register char *Addr;
kvm_t *kd;
#if !defined(romp)
struct sunromvec *romp;
if (!(kd = KVMopen()))
return((char *) NULL);
if ((nlptr = KVMnlist(kd, RomVecSYM, (struct nlist *)NULL)) == NULL)
return((char *) NULL);
if (CheckNlist(nlptr))
return((char *) NULL);
/*
* Read the kernel pointer to the sunromvec structure.
*/
if (KVMread(kd, (u_long) nlptr->n_value, (char *) &romp,
sizeof(romp))) {
if (Debug) Error("Cannot read sunromvec pointer from kernel.");
return((char *) NULL);
}
#else /* romp */
if (!(kd = KVMopen()))
return((char *) NULL);
#endif /* romp */
/*
* Read the sunromvec structure from the kernel
*/
/*SUPPRESS 25*/
if (KVMread(kd, (u_long) romp, (char *) &Rom, sizeof(struct sunromvec))) {
if (Debug) Error("Cannot read sunromvec from kernel.");
return((char *) NULL);
}
#if !defined(romp)
/*
* XXX Hardcoded values
*/
(void) sprintf(RomRev, "%d.%d", Rom.v_mon_id >> 16, Rom.v_mon_id & 0xFFFF);
#else /* romp */
/*
* Read the version string from the address indicated by Rom.v_mon_id.
* Read 1 byte at a time until '\0' is encountered.
*/
p = RomRev;
Addr = Rom.v_mon_id;
do {
if (KVMread(kd, (u_long) Addr++, p, 1))
break;
} while (p < &RomRev[sizeof(RomRev)-1] && *p++);
*p = C_NULL;
#endif /* romp */
KVMclose(kd);
#endif /* HAVE_SUNROMVEC */
return((RomRev[0]) ? RomRev : (char *) NULL);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.