static int gameport_measure_speed(struct gameport *gameport) { #if defined(__i386__) || defined(__x86_64__) #define GET_TIME(x) do { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } while (0) #define DELTA(x,y) ((y)-(x)+((y)<(x)?1193180L/HZ:0)) unsigned int i, t, t1, t2, t3, tx; unsigned long flags; if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW)) return 0; tx = 1 << 30; for(i = 0; i < 50; i++) { save_flags(flags); /* Yes, all CPUs */ cli(); GET_TIME(t1); for(t = 0; t < 50; t++) gameport_read(gameport); GET_TIME(t2); GET_TIME(t3); restore_flags(flags); udelay(i * 10); if ((t = DELTA(t2,t1) - DELTA(t3,t2)) < tx) tx = t; } return 59659 / (tx < 1 ? 1 : tx); #else unsigned int j, t = 0; j = jiffies; while (j == jiffies); j = jiffies; while (j == jiffies) { t++; gameport_read(gameport); } return t * HZ / 1000; #endif gameport_close(gameport); }
static int gameport_measure_speed(struct gameport *gameport) { #if defined(__i386__) unsigned int i, t, t1, t2, t3, tx; unsigned long flags; if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW)) return 0; tx = 1 << 30; for(i = 0; i < 50; i++) { local_irq_save(flags); GET_TIME(t1); for (t = 0; t < 50; t++) gameport_read(gameport); GET_TIME(t2); GET_TIME(t3); local_irq_restore(flags); udelay(i * 10); if ((t = DELTA(t2,t1) - DELTA(t3,t2)) < tx) tx = t; } gameport_close(gameport); return 59659 / (tx < 1 ? 1 : tx); #elif defined (__x86_64__) unsigned int i, t; unsigned long tx, t1, t2, flags; if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW)) return 0; tx = 1 << 30; for(i = 0; i < 50; i++) { local_irq_save(flags); rdtscl(t1); for (t = 0; t < 50; t++) gameport_read(gameport); rdtscl(t2); local_irq_restore(flags); udelay(i * 10); if (t2 - t1 < tx) tx = t2 - t1; } gameport_close(gameport); return (this_cpu_read(cpu_info.loops_per_jiffy) * (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx); #else unsigned int j, t = 0; if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW)) return 0; j = jiffies; while (j == jiffies); j = jiffies; while (j == jiffies) { t++; gameport_read(gameport); } gameport_close(gameport); return t * HZ / 1000; #endif }