Subject: Re: IRQ tables
To: Mark White <mark.white@st-edmund-hall.oxford.ac.uk>
From: Nathan J. Williams <nathanw@MIT.EDU>
List: port-i386
Date: 01/08/2001 09:10:01
<mark.white@st-edmund-hall.oxford.ac.uk> (Mark White) writes:
> Is there a way of getting a table of currently bound IRQs,
> I/O ports, & DMA channels, on a running system? (Other than
> trawling through demsg output)
>
> I'm thinking of /proc/ioports and friends on linux.
Not generally, no. The information is in the kernel but isn't
currently exported in a useful form.
But attached find a little program I whipped up to read the information out
of the kernel, using the kvm interface.
Output will look something like:
56 road-runner:nathanw>./getintr
irq intrmask level type (handler irq level count)...
0 f000ffe7 2 PULSE : (c025e6f0 0 1 13533800)
1 f000ffc6 8 EDGE : (c010b658 1 3 15363)
2 10000004 0 NONE :
3 f000ffff 1 EDGE : (c010a034 3 0 0)
4 f000ffff 1 EDGE : (c010a034 4 0 1)
5 f000ffe6 4 EDGE : (c025b2f8 5 2 0)
6 d000ed44 40 EDGE : (c026a12c 6 6 1)
7 f000ffc6 8 EDGE : (c0259a48 7 3 0)
8 10000100 0 NONE :
9 d000ef44 20 EDGE : (c010419c 9 5 16958)
10 10000400 0 NONE :
11 10000800 0 NONE :
12 f000ffc6 8 EDGE : (c010b658 12 3 4246)
13 10002000 0 NONE :
14 d000ed44 40 EDGE : (c024f8b8 14 6 32068)
15 10008000 0 NONE :
I was too lazy to code up the handler-address-to-function-name
translation. You can do it manually with nm and grep, as so:
58 road-runner:nathanw>nm /netbsd | grep c010419c
c010419c T epintr
Enjoy. The program is pretty kludgy; it's totally i386-specific and
tied to the current IRQ implementation, and doesn't even support
working on dead kernels (though it could, if I just copied the
relevant -N -M getopt code from ps(1) or something).
- Nathan
# 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
# getintr.c
#
echo x - Makefile
sed 's/^X//' >Makefile << 'END-of-Makefile'
X
XPROG= getintr
XSRCS= getintr.c
XDPADD= ${LIBKVM}
XLDADD= -lkvm
X
XBINGRP= kmem
XBINMODE=2555
X
XMAN=
X
X.include <bsd.prog.mk>
END-of-Makefile
echo x - getintr.c
sed 's/^X//' >getintr.c << 'END-of-getintr.c'
X#include <kvm.h>
X#include <stdio.h>
X#include <fcntl.h>
X#include <limits.h>
X#include <nlist.h>
X#include <sys/param.h>
X#include <sys/proc.h>
X#include "/sys/arch/i386/include/isa_machdep.h"
X
Xstruct nlist ginl[] = {
X { "_intrhand" },
X#define X_INTRHAND 0
X { "_intrlevel" },
X#define X_INTRLEVEL 1
X { "_intrmask" },
X#define X_INTRMASK 2
X { "_intrtype" },
X#define X_INTRTYPE 3
X { NULL }
X};
X
Xchar *isa_intrtypes[] = {"NONE", "PULSE", "EDGE", "LEVEL"};
X#define kread(x, v) \
X kvm_read(k, ginl[x].n_value, (char *)&v, sizeof v) != sizeof(v)
X
Xint main(void)
X{
X int err, i;
X char errstr[_POSIX2_LINE_MAX];
X kvm_t *k;
X void *addr;
X#define ICU_LEN 16
X int intrtype[ICU_LEN], intrmask[ICU_LEN], intrlevel[ICU_LEN];
X struct intrhand *intrhand[ICU_LEN];
X struct intrhand ih;
X k = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errstr);
X if (k == NULL) {
X fprintf(stderr,"kvm_openfiles: %s\n", errstr);
X exit(1);
X }
X
X err = kvm_nlist(k, ginl);
X if (err) {
X fprintf(stderr,"kvm_nlist: %s\n", kvm_geterr(k));
X exit(1);
X }
X if (kread(X_INTRLEVEL, intrlevel)) {
X warnx("intrlevel: %s", kvm_geterr(k));
X }
X if (kread(X_INTRMASK, intrmask)) {
X warnx("intrmask: %s", kvm_geterr(k));
X }
X if (kread(X_INTRTYPE, intrtype)) {
X warnx("intrtype: %s", kvm_geterr(k));
X }
X if (kread(X_INTRHAND, intrhand)) {
X warnx("intrhand: %s", kvm_geterr(k));
X }
X
X printf(" irq intrmask level type (handler irq level count)...\n");
X
X for (i = 0; i < ICU_LEN; i++) {
X printf("%3d %9x %4x %5s : ", i, intrmask[i], intrlevel[i],
X isa_intrtypes[intrtype[i]]);
X addr = intrhand[i];
X while (addr != NULL) {
X err = (kvm_read(k, (u_long) addr, &ih, sizeof(ih)) != sizeof(ih));
X if (err) {
X warnx("intrhand[%d]: %s", i, kvm_geterr(k));
X }
X printf("(%x %d %d %d) ", ih.ih_fun, ih.ih_irq, ih.ih_level, ih.ih_count);
X addr = ih.ih_next;
X }
X printf("\n");
X }
X
X err = kvm_close(k);
X if (err) {
X fprintf(stderr,"kvm_close: %s ", kvm_geterr(k));
X exit(1);
X }
X
X return 0;
X
X}
END-of-getintr.c
exit