#include #include #include #include #include #include #include /* After starting the driver, make the * device send us interrupt by writing 1 to 0x40: * # sudo setpci -s 00:04.0 0x40.W=0x1 * Spurious irqs are ok if the irq is shared. * Missed irqs mean there's a bug. * */ int main() { int uiofd; int configfd; int err; int i; unsigned exp, act; int spurious = 0; unsigned char interrupt = 0x0; unsigned char command_high; uiofd = open("/dev/uio0", O_RDONLY); if (uiofd < 0) { perror("uio open:"); return errno; } configfd = open("/sys/class/uio/uio0/device/config", O_RDWR); if (uiofd < 0) { perror("config open:"); return errno; } /* Read and cache command value */ err = pread(configfd, &command_high, 1, 5); if (err != 1) { perror("command config read:"); return errno; } command_high &= ~0x4; for(i = 0;; ++i) { if (i == 0) fprintf(stderr, "Started uio test driver.\n"); else fprintf(stderr, "Interrupts: %d\n", act); /* Clear interrupt on the device */ err = pwrite(configfd, &interrupt, 1, 0x40); if (err != 1) { perror("command config read:"); return errno; } err = pread(configfd, &exp, 4, 0x44); if (err != 4) { perror("config read:"); break; } /* Re-enable interrupts. */ err = pwrite(configfd, &command_high, 1, 5); if (err != 1) { perror("config write:"); break; } /* Wait for next interrupt. */ err = read(uiofd, &act, 4); if (err != 4) { perror("uio read:"); break; } if (i == 0) { /* First time, ignore the counter so far. */ spurious = act - exp; } else if (act < exp + spurious) { fprintf(stderr, "Missed irq: actual %d, expected %d\n", act, exp + spurious); } else if (act > exp + spurious) { fprintf(stderr, "Spurious irq: actual %d, expected %d\n", act, exp + spurious); spurious = act - exp; } } return errno; }