Attached is a current (2.4.16) linux kernel rtc callback patch for alsa.
The latest I have seen is for 2.4.9, and it doesn't apply cleanly.
apply this by:
cd /usr/src/linux
patch -s -p1 < alsa_rtc_2.4.16.patch
This fixes the rtc.o line in the Makefile patch and realigns the
patches in rtc.c
--
Sam Chessman [EMAIL PROTECTED]
In theory, there is no difference between theory and practice.
diff -r -u linux/drivers/char/Makefile linux-2.4.16/drivers/char/Makefile
--- linux/drivers/char/Makefile Mon Nov 26 14:39:20 2001
+++ linux-2.4.16/drivers/char/Makefile Mon Nov 26 14:40:36 2001
@@ -23,7 +23,7 @@
export-objs := busmouse.o console.o keyboard.o sysrq.o \
misc.o pty.o random.o selection.o serial.o \
- sonypi.o tty_io.o tty_ioctl.o generic_serial.o
+ sonypi.o tty_io.o tty_ioctl.o generic_serial.o rtc.o
mod-subdirs := joystick ftape drm pcmcia
diff -r -u linux/drivers/char/rtc.c linux-2.4.16/drivers/char/rtc.c
--- linux/drivers/char/rtc.c Mon Nov 26 14:39:31 2001
+++ linux-2.4.16/drivers/char/rtc.c Mon Nov 26 14:40:09 2001
@@ -139,6 +139,11 @@
static unsigned long rtc_freq = 0; /* Current periodic IRQ rate */
static unsigned long rtc_irq_data = 0; /* our output to the world */
+#if RTC_IRQ
+static spinlock_t rtc_task_lock = SPIN_LOCK_UNLOCKED;
+static rtc_task_t *rtc_callback = NULL;
+#endif
+
/*
* If this driver ever becomes modularised, it will be really nice
* to make the epoch retain its value across module reload...
@@ -180,6 +185,10 @@
spin_unlock (&rtc_lock);
/* Now do the rest of the actions */
+ spin_lock(&rtc_task_lock);
+ if (rtc_callback)
+ rtc_callback->func(rtc_callback->private_data);
+ spin_unlock(&rtc_task_lock);
wake_up_interruptible(&rtc_wait);
kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
@@ -244,8 +253,7 @@
#endif
}
-static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
+static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
{
struct rtc_time wtime;
@@ -295,7 +303,7 @@
* We don't really want Joe User enabling more
* than 64Hz of interrupts on a multi-user machine.
*/
- if ((rtc_freq > 64) && (!capable(CAP_SYS_RESOURCE)))
+ if (!kernel && (rtc_freq > 64) && (!capable(CAP_SYS_RESOURCE)))
return -EACCES;
if (!(rtc_status & RTC_TIMER_ON)) {
@@ -493,7 +501,7 @@
* We don't really want Joe User generating more
* than 64Hz of interrupts on a multi-user machine.
*/
- if ((arg > 64) && (!capable(CAP_SYS_RESOURCE)))
+ if (!kernel && (arg > 64) && (!capable(CAP_SYS_RESOURCE)))
return -EACCES;
while (arg > (1<<tmp))
@@ -539,6 +547,12 @@
return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
}
+static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ return rtc_do_ioctl(cmd, arg, 0);
+}
+
/*
* We enforce only one user at a time here with the open/close.
* Also clear the previous interrupt data on an open, and clean
@@ -606,11 +620,8 @@
spin_lock_irq (&rtc_lock);
rtc_irq_data = 0;
- spin_unlock_irq (&rtc_lock);
-
- /* No need for locking -- nobody else can do anything until this rmw is
- * committed, and no timer is running. */
rtc_status &= ~RTC_IS_OPEN;
+ spin_unlock_irq (&rtc_lock);
return 0;
}
@@ -636,6 +647,88 @@
#endif
/*
+ * exported stuffs
+ */
+
+EXPORT_SYMBOL(rtc_register);
+EXPORT_SYMBOL(rtc_unregister);
+EXPORT_SYMBOL(rtc_control);
+
+int rtc_register(rtc_task_t *task)
+{
+#if !RTC_IRQ
+ return -EIO;
+#else
+ if (task == NULL || task->func == NULL)
+ return -EINVAL;
+ spin_lock_irq(&rtc_lock);
+ if (rtc_status & RTC_IS_OPEN) {
+ spin_unlock_irq(&rtc_lock);
+ return -EBUSY;
+ }
+ spin_lock(&rtc_task_lock);
+ if (rtc_callback) {
+ spin_unlock(&rtc_task_lock);
+ spin_unlock_irq(&rtc_lock);
+ return -EBUSY;
+ }
+ rtc_status |= RTC_IS_OPEN;
+ rtc_callback = task;
+ spin_unlock(&rtc_task_lock);
+ spin_unlock_irq(&rtc_lock);
+ return 0;
+#endif
+}
+
+int rtc_unregister(rtc_task_t *task)
+{
+#if !RTC_IRQ
+ return -EIO;
+#else
+ unsigned char tmp;
+
+ spin_lock_irq(&rtc_task_lock);
+ if (rtc_callback != task) {
+ spin_unlock_irq(&rtc_task_lock);
+ return -ENXIO;
+ }
+ rtc_callback = NULL;
+ spin_lock(&rtc_lock);
+ /* disable controls */
+ tmp = CMOS_READ(RTC_CONTROL);
+ tmp &= ~RTC_PIE;
+ tmp &= ~RTC_AIE;
+ tmp &= ~RTC_UIE;
+ CMOS_WRITE(tmp, RTC_CONTROL);
+ CMOS_READ(RTC_INTR_FLAGS);
+ if (rtc_status & RTC_TIMER_ON) {
+ rtc_status &= ~RTC_TIMER_ON;
+ del_timer(&rtc_irq_timer);
+ }
+ rtc_status &= ~RTC_IS_OPEN;
+ spin_unlock(&rtc_lock);
+ spin_unlock_irq(&rtc_task_lock);
+ return 0;
+#endif
+}
+
+int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg)
+{
+#if !RTC_IRQ
+ return -EIO;
+#else
+ spin_lock_irq(&rtc_task_lock);
+ if (rtc_callback != task) {
+ spin_unlock_irq(&rtc_task_lock);
+ return -ENXIO;
+ }
+ spin_unlock_irq(&rtc_task_lock);
+ return rtc_do_ioctl(cmd, arg, 1);
+#endif
+}
+
+
+/*
* The various file operations we support.
*/
@@ -818,7 +911,6 @@
module_init(rtc_init);
module_exit(rtc_exit);
-EXPORT_NO_SYMBOLS;
#if RTC_IRQ
/*
diff -r -u linux/include/linux/rtc.h linux-2.4.16/include/linux/rtc.h
--- linux/include/linux/rtc.h Mon Nov 26 14:39:50 2001
+++ linux-2.4.16/include/linux/rtc.h Mon Nov 26 14:40:09 2001
@@ -66,4 +66,17 @@
#define RTC_WKALM_SET _IOW('p', 0x0f, struct rtc_wkalrm)/* Set wakeup alarm*/
#define RTC_WKALM_RD _IOR('p', 0x10, struct rtc_wkalrm)/* Get wakeup alarm*/
+/* Exported functions to other kernel drivers */
+
+#ifdef __KERNEL__
+typedef struct rtc_task {
+ void (*func)(void *private_data);
+ void *private_data;
+} rtc_task_t;
+
+int rtc_register(rtc_task_t *task);
+int rtc_unregister(rtc_task_t *task);
+int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg);
+#endif
+
#endif /* _LINUX_RTC_H_ */