patch-2.4.15 linux/drivers/char/rtc.c
Next file: linux/drivers/char/serial.c
Previous file: linux/drivers/char/random.c
Back to the patch index
Back to the overall index
- Lines: 176
- Date:
Tue Nov 13 09:16:05 2001
- Orig file:
v2.4.14/linux/drivers/char/rtc.c
- Orig date:
Sun Sep 23 11:40:57 2001
diff -u --recursive --new-file v2.4.14/linux/drivers/char/rtc.c linux/drivers/char/rtc.c
@@ -79,9 +79,11 @@
#endif
static unsigned long rtc_port;
-static int rtc_irq;
+static int rtc_irq = PCI_IRQ_NONE;
#endif
+static int rtc_has_irq = 1;
+
/*
* We sponge a minor off of the misc major. No need slurping
* up another valuable major dev number for this. If you add
@@ -198,6 +200,9 @@
unsigned long data;
ssize_t retval;
+ if (rtc_has_irq == 0)
+ return -EIO;
+
if (count < sizeof(unsigned long))
return -EINVAL;
@@ -244,6 +249,22 @@
{
struct rtc_time wtime;
+#if RTC_IRQ
+ if (rtc_has_irq == 0) {
+ switch (cmd) {
+ case RTC_AIE_OFF:
+ case RTC_AIE_ON:
+ case RTC_PIE_OFF:
+ case RTC_PIE_ON:
+ case RTC_UIE_OFF:
+ case RTC_UIE_ON:
+ case RTC_IRQP_READ:
+ case RTC_IRQP_SET:
+ return -EINVAL;
+ };
+ }
+#endif
+
switch (cmd) {
#if RTC_IRQ
case RTC_AIE_OFF: /* Mask alarm int. enab. bit */
@@ -412,15 +433,18 @@
yrs = 73;
}
#endif
+ /* These limits and adjustments are independant of
+ * whether the chip is in binary mode or not.
+ */
+ if (yrs > 169) {
+ spin_unlock_irq(&rtc_lock);
+ return -EINVAL;
+ }
+ if (yrs >= 100)
+ yrs -= 100;
+
if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
|| RTC_ALWAYS_BCD) {
- if (yrs > 169) {
- spin_unlock_irq(&rtc_lock);
- return -EINVAL;
- }
- if (yrs >= 100)
- yrs -= 100;
-
BIN_TO_BCD(sec);
BIN_TO_BCD(min);
BIN_TO_BCD(hrs);
@@ -550,13 +574,16 @@
static int rtc_release(struct inode *inode, struct file *file)
{
#if RTC_IRQ
+ unsigned char tmp;
+
+ if (rtc_has_irq == 0)
+ goto no_irq;
+
/*
* Turn off all interrupts once the device is no longer
* in use, and clear the data.
*/
- unsigned char tmp;
-
spin_lock_irq(&rtc_lock);
tmp = CMOS_READ(RTC_CONTROL);
tmp &= ~RTC_PIE;
@@ -574,6 +601,7 @@
if (file->f_flags & FASYNC) {
rtc_fasync (-1, file, 0);
}
+no_irq:
#endif
spin_lock_irq (&rtc_lock);
@@ -592,6 +620,9 @@
{
unsigned long l;
+ if (rtc_has_irq == 0)
+ return 0;
+
poll_wait(file, &rtc_wait, wait);
spin_lock_irq (&rtc_lock);
@@ -669,12 +700,17 @@
return -EIO;
found:
+ if (rtc_irq == PCI_IRQ_NONE) {
+ rtc_has_irq = 0;
+ goto no_irq;
+ }
+
/*
* XXX Interrupt pin #7 in Espresso is shared between RTC and
* PCI Slot 2 INTA# (and some INTx# in Slot 1). SA_INTERRUPT here
* is asking for trouble with add-on boards. Change to SA_SHIRQ.
*/
- if(request_irq(rtc_irq, rtc_interrupt, SA_INTERRUPT, "rtc", (void *)&rtc_port)) {
+ if (request_irq(rtc_irq, rtc_interrupt, SA_INTERRUPT, "rtc", (void *)&rtc_port)) {
/*
* Standard way for sparc to print irq's is to use
* __irq_itoa(). I think for EBus it's ok to use %d.
@@ -682,6 +718,7 @@
printk(KERN_ERR "rtc: cannot register IRQ %d\n", rtc_irq);
return -EIO;
}
+no_irq:
#else
if (check_region (RTC_PORT (0), RTC_IO_EXTENT))
{
@@ -712,8 +749,10 @@
uip_watchdog = jiffies;
if (rtc_is_updating() != 0)
- while (jiffies - uip_watchdog < 2*HZ/100)
+ while (jiffies - uip_watchdog < 2*HZ/100) {
barrier();
+ cpu_relax();
+ }
spin_lock_irq(&rtc_lock);
year = CMOS_READ(RTC_YEAR);
@@ -766,11 +805,13 @@
misc_deregister(&rtc_dev);
#ifdef __sparc__
- free_irq (rtc_irq, &rtc_port);
+ if (rtc_has_irq)
+ free_irq (rtc_irq, &rtc_port);
#else
release_region (RTC_PORT (0), RTC_IO_EXTENT);
#if RTC_IRQ
- free_irq (RTC_IRQ, NULL);
+ if (rtc_has_irq)
+ free_irq (RTC_IRQ, NULL);
#endif
#endif /* __sparc__ */
}
@@ -946,8 +987,10 @@
*/
if (rtc_is_updating() != 0)
- while (jiffies - uip_watchdog < 2*HZ/100)
+ while (jiffies - uip_watchdog < 2*HZ/100) {
barrier();
+ cpu_relax();
+ }
/*
* Only the values that we read from the RTC are set. We leave
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)