/* Produces a beep on the Crusoe NetWinder */ #include #include #include #include #include #include #define stop_count() outb(inb(0x61) & ~0x01, 0x61) #define start_count() outb(inb(0x61) | 0x01, 0x61) #define set_freq(freq) \ do { \ unsigned count = 1191380 / freq; \ outb(0xb6, 0x43); \ outb(count & 0xff, 0x42); \ outb(count >> 8, 0x42); \ } while (0) #define sound_on() outb(inb(0x61) | 0x02, 0x61) #define sound_off() outb(inb(0x61) & ~0x02, 0x61) int alarm_handler_called = 0; void alarm_handler(int arg) { alarm_handler_called = 1; } int main(int argc, char *argv[]) { int retval; struct itimerval itime; /* Make sure two args (frequency in Hz, duration in ms) */ if (argc < 3) return 1; /* Allow I/O to timer */ retval = ioperm(0x40, 4, 0x44); if (retval) { perror("ioperm (0x40, 4, 0x44"); return 2; } /* Allow I/O to sound control */ retval = ioperm(0x61, 1, 0x62); if (retval) { perror("ioperm (0x61, 1, 0x61"); return 2; } sound_off(); stop_count(); set_freq(atoi(argv[1])); start_count(); signal(SIGALRM, &alarm_handler); /* Set the duration timer */ itime.it_interval.tv_sec = 0; itime.it_interval.tv_usec = 0; itime.it_value.tv_sec = atoi(argv[2]) / 1000; itime.it_value.tv_usec = atoi(argv[2]) % 1000 * 1000; retval = setitimer(ITIMER_REAL, &itime, NULL); if (retval) { perror("setitimer"); return 3; } /* Play the sound */ sound_on(); pause(); sound_off(); return (alarm_handler_called) ? 0: 4; }