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
|
#include <linux/module.h>
#include <rtl_fifo.h>
#include <asm/rt_irq.h>
#include <linux/rt_time.h>
#include <linux/mc146818rtc.h>
#include <linux/cons.h>
static int filter(int x)
{
static int oldx;
int ret;
if (x & 0x80) {
x = 382 - x;
}
ret = x > oldx;
oldx = x;
return ret;
}
void intr_handler(void) {
char data;
char temp;
(void) CMOS_READ(RTC_REG_C); /* clear IRQ */
if (rtf_get(0, &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);
}
}
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(0, 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);
request_RTirq(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);
(void) CMOS_READ(RTC_REG_C);
return 0;
}
void cleanup_module(void)
{
rtf_destroy(0);
outb_p(0xb6, 0x43); /* restore the original mode */
CMOS_WRITE(save_cmos_A, RTC_REG_A);
CMOS_WRITE(save_cmos_B, RTC_REG_B);
free_RTirq(8);
}
|