patch-2.3.99-pre6 linux/drivers/char/efirtc.c

Next file: linux/drivers/char/ip2/fip_firm.h
Previous file: linux/drivers/char/cpia.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.99-pre5/linux/drivers/char/efirtc.c linux/drivers/char/efirtc.c
@@ -39,7 +39,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
-#define EFI_RTC_VERSION		"0.1"
+#define EFI_RTC_VERSION		"0.2"
 
 #define EFI_ISDST (EFI_TIME_ADJUST_DAYLIGHT|EFI_TIME_IN_DAYLIGHT)
 /*
@@ -47,7 +47,7 @@
  */
 #define EFI_RTC_EPOCH		1998
 
-static spinlock_t efi_rtc_lock;
+static spinlock_t efi_rtc_lock = SPIN_LOCK_UNLOCKED;
 
 static int efi_rtc_ioctl(struct inode *inode, struct file *file,
 		     unsigned int cmd, unsigned long arg);
@@ -153,6 +153,8 @@
 	efi_time_t	eft;
 	efi_time_cap_t	cap;
 	struct rtc_time	wtime;
+	struct rtc_wkalrm *ewp;
+	unsigned char	enabled, pending;
 
 	switch (cmd) {
 		case RTC_UIE_ON:
@@ -203,6 +205,50 @@
 			spin_unlock_irqrestore(&efi_rtc_lock,flags);
 
 			return status == EFI_SUCCESS ? 0 : -EINVAL;
+
+		case RTC_WKALM_SET:
+
+			if (!capable(CAP_SYS_TIME)) return -EACCES;
+
+			ewp = (struct rtc_wkalrm *)arg;
+
+			if (  get_user(enabled, &ewp->enabled)
+			   || copy_from_user(&wtime, &ewp->time, sizeof(struct rtc_time)) )
+				return -EFAULT;
+
+			convert_to_efi_time(&wtime, &eft);
+			
+			spin_lock_irqsave(&efi_rtc_lock, flags);
+			/*
+			 * XXX Fixme:
+			 * As of EFI 0.92 with the firmware I have on my
+			 * machine this call does not seem to work quite 
+			 * right
+			 */
+			status = efi.set_wakeup_time((efi_bool_t)enabled, &eft);
+
+			spin_unlock_irqrestore(&efi_rtc_lock,flags);
+
+			return status == EFI_SUCCESS ? 0 : -EINVAL;
+
+		case RTC_WKALM_RD:
+
+			spin_lock_irqsave(&efi_rtc_lock, flags);
+
+			status = efi.get_wakeup_time((efi_bool_t *)&enabled, (efi_bool_t *)&pending, &eft);
+
+			spin_unlock_irqrestore(&efi_rtc_lock,flags);
+
+			if (status != EFI_SUCCESS) return -EINVAL;
+
+			ewp = (struct rtc_wkalrm *)arg;
+
+			if (  put_user(enabled, &ewp->enabled)
+			   || put_user(pending, &ewp->pending)) return -EFAULT;
+
+			convert_from_efi_time(&eft, &wtime);
+
+			return copy_to_user((void *)&ewp->time, &wtime, sizeof(struct rtc_time));
 	}
 	return -EINVAL;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)