lsdev(8), a user-land utility to query the device configuration database

managed by kern_devconf.c.  A useful feature is that the following
script generates almost well-formed config-file lines for all ISA devices
in the system:

lsdev -t isa | awk '{ print "device $0" }'
lsdev -t disk | awk '{ print "disk $0" }'
This commit is contained in:
Garrett Wollman 1994-10-17 23:26:10 +00:00
parent e33700d2b0
commit 0ed1ac8d35
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/ours/; revision=3673
5 changed files with 423 additions and 0 deletions

8
usr.sbin/lsdev/Makefile Normal file
View File

@ -0,0 +1,8 @@
# $Id$
PROG= lsdev
MAN8= lsdev.8
SRCS= lsdev.c ${MACHINE}.c
CFLAGS+= -I${.CURDIR}/../../sys
.include <bsd.prog.mk>

183
usr.sbin/lsdev/i386.c Normal file
View File

@ -0,0 +1,183 @@
#include "lsdev.h"
#include <stdio.h>
#include <string.h>
static void print_isa(struct devconf *);
static void print_eisa(struct devconf *);
static void print_pci(struct devconf *);
static void print_scsi(struct devconf *);
static void print_disk(struct devconf *);
void
print(struct devconf *dc)
{
if(vflag)
printf("%d: ", dc->dc_number);
switch(dc->dc_devtype) {
case MDDT_CPU:
printf("CPU on %s", dc->dc_parent);
break;
case MDDT_ISA:
if(dc->dc_datalen >= ISA_EXTERNALLEN) {
print_isa(dc);
} else {
printit:
printf("%s%d on %s",
dc->dc_name, dc->dc_unit, dc->dc_parent);
}
break;
case MDDT_EISA:
if(dc->dc_datalen >= EISA_EXTERNALLEN) {
print_eisa(dc);
} else {
goto printit;
}
break;
case MDDT_PCI:
if(dc->dc_datalen >= PCI_EXTERNALLEN) {
print_pci(dc);
} else {
goto printit;
}
break;
case MDDT_SCSI:
if(dc->dc_datalen >= SCSI_EXTERNALLEN) {
print_scsi(dc);
} else {
goto printit;
}
break;
case MDDT_DISK:
if(dc->dc_datalen >= DISK_EXTERNALLEN) {
print_disk(dc);
} else {
goto printit;
}
break;
default:
if(dc->dc_devtype >= NDEVTYPES) {
printf("%s%d (#%d) on %s",
dc->dc_name, dc->dc_unit, dc->dc_devtype,
dc->dc_parent);
} else {
printf("%s%d (%s) on %s",
dc->dc_name, dc->dc_unit,
devtypes[dc->dc_devtype], dc->dc_parent);
}
break;
}
fputc('\n', stdout);
}
static void
print_isa(struct devconf *dc)
{
struct isa_device *id = (struct isa_device *)dc->dc_data;
printf("%s%d on %s", dc->dc_name, dc->dc_unit, dc->dc_parent);
if(vflag) {
printf(" (id %d)", id->id_id);
}
if(id->id_iobase) {
if(id->id_iobase < 0) {
printf(" port ?");
} else {
printf(" port 0x%x", id->id_iobase);
}
}
if(id->id_irq) {
int bit = ffs(id->id_irq) - 1;
if(id->id_irq & ~(1 << bit)) {
printf(" irq ?");
} else {
printf(" irq %d", bit);
}
}
if(id->id_drq) {
if(id->id_drq < 0) {
printf(" drq ?");
} else {
printf(" drq %d", id->id_drq);
}
}
if(id->id_maddr) {
if((unsigned long)id->id_maddr == ~0UL) {
printf(" iomem ?");
} else {
printf(" iomem 0x%lx", (unsigned long)id->id_maddr);
}
}
if(id->id_msize) {
if(id->id_msize < 0) {
printf(" iosiz ?", id->id_msize);
} else {
printf(" iosiz %d", id->id_msize);
}
}
if(id->id_flags) {
printf(" flags 0x%x", id->id_flags);
}
}
static void
print_eisa(struct devconf *dc)
{
int *slotp = (int *)&dc->dc_data[ISA_EXTERNALLEN];
print_isa(dc);
if(vflag) {
printf(" (slot %d)", *slotp);
}
}
static void
print_pci(struct devconf *dc)
{
struct pci_device *pd = (struct pci_device *)dc->dc_data;
/*
* Unfortunately, the `pci_device' struct is completely
* useless. We will have to develop a unique structure
* for this task eventually, unless the existing one can
* be made to serve.
*/
printf("%s%d on %s", dc->dc_name, dc->dc_unit, dc->dc_parent);
}
static void
print_scsi(struct devconf *dc)
{
struct scsi_link *sl = (struct scsi_link *)dc->dc_data;
printf("%s%d on SCSI bus %d:%d:%d",
dc->dc_name, dc->dc_unit, sl->scsibus, sl->target,
sl->lun);
if(vflag) {
if(sl->flags & SDEV_MEDIA_LOADED)
printf(" (ready)");
if(sl->flags & SDEV_OPEN)
printf(" (open)");
if(sl->flags & SDEV_BOUNCE)
printf(" (bounce)");
}
}
static void
print_disk(struct devconf *dc)
{
int *slavep = (int *)dc->dc_data;
printf("%s%d on %s drive %d",
dc->dc_name, dc->dc_unit, dc->dc_parent, *slavep);
}

61
usr.sbin/lsdev/lsdev.8 Normal file
View File

@ -0,0 +1,61 @@
.\" $Id: lsvfs.1,v 1.1 1994/09/22 01:25:56 wollman Exp $
.\" Garrett A. Wollman, October 1994
.\" This file is in the public domain.
.\"
.Dd October 17, 1994
.Dt LSDEV 1
.Os
.Sh NAME
.Nm lsdev
.Nd list configured devices
.Sh SYNOPSIS
.Nm lsdev
.Op Fl t Ar type
.Op Fl v
.Op Ar class Ns Op unit
.Sh DESCRIPTION
The
.Nm lsdev
utility lists devices configured in the current system, in a
machine-dependent manner. The
.Fl t
flag can be used to restrict the listing to a specific
.Ar type
of device;
the types available vary from machine to machine. (Specifying an
invalid type will cause a list of valid types to be printed.) The
.Fl v
flag requests more verbose output. The optional
.Ar class
argument requests information on a particular class of devices (e.g.,
.Dq Li wdc
or
.No Do Li ie Dc Ns ).
If no
.Ar unit
is specified, all units of the specified class will be listed.
.Pp
The
.Xr sysctl 3
mechanism is used to retrieve information from the kernel about which
devices are configured.
.Sh FILES
.Bl -tag -width <machine/devconf.h>
.It Aq sys/devconf.h
defines the structure examined by
.Nm
.It Aq machine/devconf.h
defines the machine-dependent parts of the structure, including the
supported device type names
.El
.Sh SEE ALSO
.\" .Xr chdev 8
.Xr sysctl 3
.Sh BUGS
Not all devices have the proper support implmented yet.
.Sh HISTORY
An
.Nm
comand appeared in
.Tn FreeBSD
2.0.

155
usr.sbin/lsdev/lsdev.c Normal file
View File

@ -0,0 +1,155 @@
#include "lsdev.h"
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <ctype.h>
#include <string.h>
const char *const devtypes[] = DEVTYPENAMES;
int vflag = 0;
const char *whoami;
static void usage(void);
static void badtype(const char *);
static void badname(const char *);
int
main(int argc, char **argv)
{
struct devconf *dc = 0;
size_t size, osize;
int ndevs, i;
int mib[8];
int c;
int showonlytype = -1;
int showonlydev = 0;
char showonlydevclass[MAXDEVNAME];
int showonlydevunit = -1;
whoami = argv[0];
while((c = getopt(argc, argv, "t:v")) != EOF) {
switch(c) {
case 't':
showonlytype = findtype(optarg);
if(showonlytype < 0)
badtype(optarg);
break;
case 'v':
vflag++;
break;
default:
usage();
break;
}
}
if(argc - optind > 1) {
usage();
}
if(argv[optind]) {
char *s = &argv[optind][strlen(argv[optind])];
if(s - argv[optind] > MAXDEVNAME)
badname(argv[optind]);
s--; /* step over null */
while(s > argv[optind] && isdigit(*s))
s--;
s++;
if(*s) {
showonlydevunit = atoi(s);
*s = '\0';
} else {
showonlydevunit = -1;
}
strcpy(showonlydevclass, argv[optind]);
showonlydev = 1;
}
mib[0] = CTL_HW;
mib[1] = HW_DEVCONF;
mib[2] = DEVCONF_NUMBER;
size = sizeof ndevs;
if(sysctl(mib, 3, &ndevs, &size, 0, 0) < 0) {
err(1, "sysctl(hw.devconf.number)");
}
osize = 0;
for(i = 1; i <= ndevs; i++) {
mib[2] = i;
if(sysctl(mib, 3, 0, &size, 0, 0) < 0) {
/*
* Probably a deleted device; just go on to the next
* one.
*/
continue;
}
if(size > osize) {
dc = realloc(dc, size);
if(!dc) {
err(2, "realloc(%lu)", (unsigned long)size);
}
}
if(sysctl(mib, 3, dc, &size, 0, 0) < 0) {
err(1, "sysctl(hw.devconf.%d)", i);
}
if(!showonlydev && showonlytype < 0) {
print(dc);
} else if(showonlydev) {
if(!strcmp(showonlydevclass, dc->dc_name)
&& (showonlydevunit < 0 ||
showonlydevunit == dc->dc_unit))
print(dc);
} else if(showonlytype == dc->dc_devtype) {
print(dc);
}
osize = size;
}
return 0;
}
static void
usage(void)
{
fprintf(stderr,
"usage:\n"
"\t%s [-t type] [-v] [name]\n",
whoami);
exit(-1);
}
int
findtype(const char *name)
{
int i;
for(i = 0; devtypes[i]; i++) {
if(!strcmp(name, devtypes[i]))
return i;
}
return -1;
}
static void
badtype(const char *name)
{
int i;
fprintf(stderr,
"%s: invalid device type `%s'\n", whoami, name);
fprintf(stderr,
"%s: valid types are: ", whoami);
for(i = 0; devtypes[i]; i++) {
fprintf(stderr, "%s`%s'", i ? ", " : "", devtypes[i]);
}
fputs(".\n", stderr);
exit(-1);
}
static void
badname(const char *name)
{
errx(3, "invalid device name `%s'", name);
}

16
usr.sbin/lsdev/lsdev.h Normal file
View File

@ -0,0 +1,16 @@
/*
* Declarations for lsdev(8).
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/proc.h>
#include <vm/vm.h>
#include <sys/sysctl.h>
#include <sys/devconf.h>
extern const char *const devtypes[]; /* device type array */
extern void print(struct devconf *); /* machine-specific print routine */
extern int vflag;
extern int findtype(const char *); /* get device type by name */