1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
|
/*
* Interrupt handling in Real-Time. Play sounds with PC speaker.
*
* (C) Michael Barabanov, 1997
* (C) FSMLabs 1999. baraban@fsmlabs.com
* Released under the GNU GENERAL PUBLIC LICENSE Version 2, June 1991
* Any use of this code must include this notice.
*
*/
#include <linux/mc146818rtc.h>
#include <rtl_fifo.h>
#include <rtl_core.h>
#include <rtl_time.h>
#include <rtl.h>
#define FIFO_NO 3
static int filter(int x)
{
static int oldx;
int ret;
if (x & 0x80) {
x = 382 - x;
}
ret = x > oldx;
oldx = x;
return ret;
}
unsigned int intr_handler(unsigned int irq, struct pt_regs *regs) {
char data;
char temp;
(void) CMOS_READ(RTC_REG_C); /* clear IRQ */
if (rtf_get(FIFO_NO, &data, 1) > 0) {
data = filter(data);
/* if (data) conpr("1"); else conpr("0"); */
temp = inb(0x61);
temp &= 0xfc;
if (data) {
temp |= 3;
}
outb(temp,0x61);
}
rtl_hard_enable_irq (8);
return 0;
}
char save_cmos_A;
char save_cmos_B;
int init_module(void)
{
char ctemp;
if (!I8253_channel2_free()) {
conpr("RTL sound: can't use channel 2; bailing out\n");
return -1;
}
rtf_create(FIFO_NO, 4000);
/* this is just to ensure that the output of the counter is 1 */
outb_p(0xb0, 0x43); /* binary, mode 0, LSB/MSB, ch 2 */
outb_p(0x1, 0x42);
outb_p(0x0, 0x42);
rtl_request_irq (8, intr_handler);
/* program the RTC to interrupt at 8192 Hz */
save_cmos_A = CMOS_READ(RTC_REG_A);
save_cmos_B = CMOS_READ(RTC_REG_B);
CMOS_WRITE(0x23, RTC_REG_A); /* 32kHz Time Base, 8192 Hz interrupt frequency */
ctemp = CMOS_READ(RTC_REG_B);
ctemp &= 0x8f; /* Clear */
ctemp |= 0x40; /* Periodic interrupt enable */
CMOS_WRITE(ctemp, RTC_REG_B);
rtl_hard_enable_irq (8);
(void) CMOS_READ(RTC_REG_C);
return 0;
}
void cleanup_module(void)
{
rtf_destroy(FIFO_NO);
outb_p(0xb6, 0x43); /* restore the original mode */
CMOS_WRITE(save_cmos_A, RTC_REG_A);
CMOS_WRITE(save_cmos_B, RTC_REG_B);
rtl_free_irq(8);
}
|