Subject: Re: root device
To: Simon Burge <simonb@wasabisystems.com>
From: Nathan J. Williams <nathanw@wasabisystems.com>
List: tech-kern
Date: 02/10/2003 17:24:46
--=rail-gun-EuroFed-Fortezza-bullion-threat-Project-Monarch-UNSCOM-Pine

Simon Burge <simonb@wasabisystems.com> writes:

> Emmanuel Dreyfus wrote:
> 
> > > i think that having a program that could dump out the device tree
> > > under netbsd would be *damn cool*!
> > 
> > Hey, look at what Darwin's ioreg outputs on my NetBSD/macppc machine:
> > 
> > +-o mainbus0@  <class unknownClass>
> >   +-o cpu0@  <class unknownClass>
> >
> > [ ... ]
> 
> It'd be nice to have a _native_ NetBSD program to show this too.  I'm
> sorta sure that's what Andrew meant :-)

Here's something I've had kicking around for a while. It's quite
simple; embellish as necessary to get actual tree-like
output. Locators only exist for devices configured explicitly; we
don't store "found" locators anywhere besides the message buffer.

% ./printdev

mainbus0 
cpu0 at mainbus0 
pci0 at mainbus0 
pchb0 at pci0 
agp0 at pchb0 
ppb0 at pci0 
pci1 at ppb0 
vga1 at pci1 
wsdisplay0 at vga1 kbdmux 0x1 
pcib0 at pci0 
pciide0 at pci0 
wd0 at pciide0 
atapibus0 at pciide0 
cd0 at atapibus0 
cd1 at atapibus0 
amdpm0 at pci0 
tlp0 at pci0 
acphy0 at tlp0 
ppb1 at pci0 
pci2 at ppb1 
cmpci0 at pci2 
audio0 at cmpci0 
opl0 at cmpci0 
midi0 at opl0 
mpu0 at cmpci0 
midi1 at mpu0 
ohci0 at pci2 
usb0 at ohci0 
uhub0 at usb0 
ohci1 at pci2 
usb1 at ohci1 
uhub1 at usb1 
ehci0 at pci2 
usb2 at ehci0 
uhub2 at usb2 
tlp1 at pci2 
bmtphy0 at tlp1 
isa0 at pcib0 
com0 at isa0 port 0x3f8 irq 0x4 
com1 at isa0 port 0x2f8 irq 0x3 
pckbc0 at isa0 
pckbd0 at pckbc0 
wskbd0 at pckbd0 mux 0x1 
pms0 at pckbc0 
wsmouse0 at pms0 
lpt0 at isa0 port 0x378 irq 0x7 
pcppi0 at isa0 
midi2 at pcppi0 
spkr0 at pcppi0 
sysbeep0 at pcppi0 
npx0 at isa0 port 0xf0 irq 0xd 
fdc0 at isa0 port 0x3f0 irq 0x6 drq 0x2 
fd0 at fdc0


        - Nathan


--=rail-gun-EuroFed-Fortezza-bullion-threat-Project-Monarch-UNSCOM-Pine
Content-Type: application/x-sh
Content-Disposition: attachment; filename=printdev.shar
Content-Description: printdev

# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	Makefile
#	printdev.c
#
echo x - Makefile
sed 's/^X//' >Makefile << 'END-of-Makefile'
XPROG=		printdev
XSRCS=		printdev.c
XDPADD=		${LIBKVM}
XLDADD=		-lkvm
XBINGRP=		kmem
XBINMODE=	2555
XWARNS= 2
XMAN=
X
X.include <bsd.prog.mk>
END-of-Makefile
echo x - printdev.c
sed 's/^X//' >printdev.c << 'END-of-printdev.c'
X
X#include <err.h>
X#include <fcntl.h>
X#include <kvm.h>
X#include <nlist.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include <limits.h>
X#include <unistd.h>
X
X#include <sys/device.h>
X
Xstatic void usage(void);
Xssize_t kvm_readstr(kvm_t *kd, u_long addr, char *buf, size_t maxlen);
Xssize_t kvm_eread(kvm_t *kd, u_long addr, void *buf, size_t maxlen);
X
X#define FORMAT(n) ((n) > -10 && (n) < 10 ? "%d" : "0x%x")
X
X
Xstruct nlist pcnl[] = {
X#define PCNL_ALLDEVS 0
X  { "_alldevs" },
X	{NULL}
X};
X
Xint main(int argc, char *argv[])
X{
X  extern char *optarg;
X  extern int optind;
X  int ch, ret;
X  char *nlistf, *memf, *swapf;
X  kvm_t* kd;
X  char errbuf[LINE_MAX], locname[LINE_MAX];
X  u_long devaddr;
X
X  struct devicelist alldevs;
X  struct device dev, dev2;
X  struct cfdata cfda;
X  char **lnsaddr, *lnaddr;
X  int *lsaddr, loc;
X
X  nlistf = NULL;
X  memf = NULL;
X  swapf = NULL;
X
X  while((ch = getopt(argc, argv, "N:M:W:")) != -1)
X    switch (ch) {
X    case 'M':
X      memf = optarg;
X      break;
X    case 'N':
X      nlistf = optarg;
X      break;
X    case 'W':
X      swapf = optarg;
X      break;
X    case '?':
X    default: 
X      usage();
X    }
X
X  argc += optind;
X  argv -= optind;
X
X  kd = kvm_openfiles(nlistf, memf, swapf, O_RDONLY, errbuf);
X  if (kd == 0) {
X    errx(1, "%s", errbuf);
X  }
X
X  ret = kvm_nlist(kd, pcnl);
X  if (ret < 0) {
X    errx(2, "%s", kvm_geterr(kd));
X  }
X
X  kvm_eread(kd, pcnl[PCNL_ALLDEVS].n_value, &alldevs, sizeof(alldevs));
X
X  devaddr = (u_long) TAILQ_FIRST(&alldevs);
X  while (devaddr) {
X	  kvm_eread(kd, devaddr, &dev, sizeof(dev));
X	  printf("%s ", dev.dv_xname);
X	  if (dev.dv_parent) {
X		  kvm_eread(kd, (u_long)dev.dv_parent, &dev2, sizeof(dev));
X		  printf("at %s ", dev2.dv_xname);
X	  }
X	  if (dev.dv_cfdata) {
X		  kvm_eread(kd, (u_long)dev.dv_cfdata, &cfda, sizeof(cfda));
X		  lnsaddr = (char **)cfda.cf_locnames;
X		  lsaddr = cfda.cf_loc;
X		  kvm_eread(kd, (u_long)lnsaddr, &lnaddr, sizeof(lnaddr));
X		  while (lnaddr) {
X			  kvm_readstr(kd, (u_long)lnaddr, locname,
X			      sizeof(locname));
X			  kvm_eread(kd, (u_long)lsaddr, &loc, sizeof(loc));
X			  if (loc != -1 && loc != 0)
X				  printf("%s %#x ", locname, loc);
X			  
X			  lnsaddr++;
X			  lsaddr++;
X			  kvm_eread(kd, (u_long)lnsaddr, &lnaddr,
X			      sizeof(lnaddr));
X		  }
X	  }
X	  printf("\n");
X	  devaddr = (u_long)TAILQ_NEXT(&dev, dv_list);
X  }
X
X  kvm_close(kd);
X
X  return 0;
X}
X
Xssize_t kvm_eread(kvm_t *kd, u_long addr, void *buf, size_t maxlen)
X{
X  ssize_t ret;
X  ret = kvm_read(kd, addr, buf, maxlen);
X  if (ret == -1) {
X    errx(3, "%s", kvm_geterr(kd));
X  }
X  return ret;
X}
X
Xssize_t kvm_readstr(kvm_t *kd, u_long addr, char *buf, size_t maxlen)
X{
X  int count, done;
X
X  count = 0;
X  done = 0;
X  
X  while (!done && count < maxlen) {
X    kvm_eread(kd, addr + count, &buf[count], 1);
X    if (buf[count] == '\0')
X      done = 1;
X    count++;
X  }
X
X  return count;
X}
X
Xstatic void usage(void)
X{
X	fprintf(stderr, "usage: printdev [-N kernel] [-M core] [-W swap]\n");
X	exit(1);
X}
END-of-printdev.c
exit


--=rail-gun-EuroFed-Fortezza-bullion-threat-Project-Monarch-UNSCOM-Pine--