This source file includes following definitions.
- rtc_interrupt
- rtc_lseek
- rtc_read
- rtc_ioctl
- rtc_open
- rtc_release
- rtc_select
- rtc_init
- get_rtc_status
- rtc_is_updating
- get_rtc_time
- get_rtc_alm_time
- mask_rtc_irq_bit
- set_rtc_irq_bit
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 #define RTC_VERSION "1.04"
34
35 #define RTC_IRQ 8
36 #define RTC_IO_BASE 0x70
37 #define RTC_IO_EXTENT 0x10
38
39
40
41
42
43
44
45
46
47 #include <linux/types.h>
48 #include <linux/errno.h>
49 #include <linux/miscdevice.h>
50 #include <linux/malloc.h>
51 #include <linux/ioport.h>
52 #include <linux/fcntl.h>
53 #include <linux/mc146818rtc.h>
54
55 #include <asm/io.h>
56 #include <asm/segment.h>
57 #include <asm/system.h>
58
59 #include <time.h>
60
61
62
63
64
65
66 #define RTC_MINOR 135
67
68 static struct wait_queue *rtc_wait;
69
70 static int rtc_lseek(struct inode *inode, struct file *file, off_t offset,
71 int origin);
72
73 static int rtc_read(struct inode *inode, struct file *file,
74 char *buf, int count);
75
76 static int rtc_ioctl(struct inode *inode, struct file *file,
77 unsigned int cmd, unsigned long arg);
78
79 static int rtc_select(struct inode *inode, struct file *file,
80 int sel_type, select_table *wait);
81
82 void get_rtc_time (struct tm *rtc_tm);
83 void get_rtc_alm_time (struct tm *alm_tm);
84
85 inline void set_rtc_irq_bit(unsigned char bit);
86 inline void mask_rtc_irq_bit(unsigned char bit);
87
88 unsigned char rtc_is_updating(void);
89
90
91
92
93
94 #define RTC_IS_OPEN 0x01
95
96 unsigned char rtc_status = 0;
97 unsigned long rtc_irq_data = 0;
98
99 unsigned char days_in_mo[] =
100 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
101
102
103
104
105
106
107
108
109 static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
110 {
111
112
113
114
115
116
117
118 rtc_irq_data += 0x100;
119 rtc_irq_data &= ~0xff;
120 rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);
121 wake_up_interruptible(&rtc_wait);
122 }
123
124
125
126
127
128 static int rtc_lseek(struct inode *inode, struct file *file, off_t offset,
129 int origin)
130 {
131 return -ESPIPE;
132 }
133
134 static int rtc_read(struct inode *inode, struct file *file, char *buf, int count)
135 {
136 struct wait_queue wait = { current, NULL };
137 int retval;
138
139 if (count < sizeof(unsigned long))
140 return -EINVAL;
141
142 retval = verify_area(VERIFY_WRITE, buf, sizeof(unsigned long));
143 if (retval)
144 return retval;
145
146 add_wait_queue(&rtc_wait, &wait);
147
148 current->state = TASK_INTERRUPTIBLE;
149
150 while (rtc_irq_data == 0) {
151 if (file->f_flags & O_NONBLOCK) {
152 retval = -EAGAIN;
153 break;
154 }
155 if (current->signal & ~current->blocked) {
156 retval = -ERESTARTSYS;
157 break;
158 }
159 schedule();
160 continue;
161 }
162
163 if (retval == 0) {
164 memcpy_tofs(buf, &rtc_irq_data, sizeof(unsigned long));
165 rtc_irq_data = 0;
166 retval = sizeof(unsigned long);
167 }
168
169 current->state = TASK_RUNNING;
170 remove_wait_queue(&rtc_wait, &wait);
171
172 return retval;
173 }
174
175 static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
176 unsigned long arg)
177 {
178
179 unsigned long flags;
180
181 switch (cmd) {
182 case RTC_AIE_OFF:
183 {
184 mask_rtc_irq_bit(RTC_AIE);
185 return 0;
186 }
187 case RTC_AIE_ON:
188 {
189 set_rtc_irq_bit(RTC_AIE);
190 return 0;
191 }
192 case RTC_PIE_OFF:
193 {
194 mask_rtc_irq_bit(RTC_PIE);
195 return 0;
196 }
197 case RTC_PIE_ON:
198 {
199 unsigned int hz;
200 unsigned char tmp;
201
202 save_flags(flags);
203 cli();
204 tmp = CMOS_READ(RTC_FREQ_SELECT) & 0x0f;
205 restore_flags(flags);
206
207 hz = (tmp ? (65536/(1<<tmp)) : 0);
208
209
210
211
212
213 if ((hz > 64) && (!suser()))
214 return -EPERM;
215
216 set_rtc_irq_bit(RTC_PIE);
217 return 0;
218 }
219 case RTC_UIE_OFF:
220 {
221 mask_rtc_irq_bit(RTC_UIE);
222 return 0;
223 }
224 case RTC_UIE_ON:
225 {
226 set_rtc_irq_bit(RTC_UIE);
227 return 0;
228 }
229 case RTC_ALM_READ:
230 {
231
232
233
234
235
236 int retval;
237 struct tm alm_tm;
238
239 retval = verify_area(VERIFY_WRITE, (struct tm*)arg, sizeof(struct tm));
240 if (retval != 0 )
241 return retval;
242
243 get_rtc_alm_time(&alm_tm);
244
245 memcpy_tofs((struct tm*)arg, &alm_tm, sizeof(struct tm));
246
247 return 0;
248 }
249 case RTC_ALM_SET:
250 {
251
252
253
254
255
256 int retval;
257 unsigned char hrs, min, sec;
258 struct tm alm_tm;
259
260 retval = verify_area(VERIFY_READ, (struct tm*)arg, sizeof(struct tm));
261 if (retval != 0 )
262 return retval;
263
264 memcpy_fromfs(&alm_tm, (struct tm*)arg, sizeof(struct tm));
265
266 hrs = alm_tm.tm_hour;
267 min = alm_tm.tm_min;
268 sec = alm_tm.tm_sec;
269
270 if (hrs >= 24)
271 hrs = 0xff;
272
273 if (min >= 60)
274 min = 0xff;
275
276 if (sec >= 60)
277 sec = 0xff;
278
279 save_flags(flags);
280 cli();
281 if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) ||
282 RTC_ALWAYS_BCD)
283 {
284 BIN_TO_BCD(sec);
285 BIN_TO_BCD(min);
286 BIN_TO_BCD(hrs);
287 }
288 CMOS_WRITE(hrs, RTC_HOURS_ALARM);
289 CMOS_WRITE(min, RTC_MINUTES_ALARM);
290 CMOS_WRITE(sec, RTC_SECONDS_ALARM);
291 restore_flags(flags);
292
293 return 0;
294 }
295 case RTC_RD_TIME:
296 {
297 int retval;
298 struct tm rtc_tm;
299
300 retval = verify_area(VERIFY_WRITE, (struct tm*)arg, sizeof(struct tm));
301 if (retval !=0 )
302 return retval;
303
304 get_rtc_time(&rtc_tm);
305 memcpy_tofs((struct tm*)arg, &rtc_tm, sizeof(struct tm));
306 return 0;
307 }
308 case RTC_SET_TIME:
309 {
310 int retval;
311 struct tm rtc_tm;
312 unsigned char mon, day, hrs, min, sec, leap_yr;
313 unsigned char save_control, save_freq_select;
314 unsigned int yrs;
315 unsigned long flags;
316
317 if (!suser())
318 return -EPERM;
319
320 retval = verify_area(VERIFY_READ, (struct tm*)arg, sizeof(struct tm));
321 if (retval !=0 )
322 return retval;
323
324 memcpy_fromfs(&rtc_tm, (struct tm*)arg, sizeof(struct tm));
325
326 yrs = rtc_tm.tm_year + 1900;
327 mon = rtc_tm.tm_mon + 1;
328 day = rtc_tm.tm_mday;
329 hrs = rtc_tm.tm_hour;
330 min = rtc_tm.tm_min;
331 sec = rtc_tm.tm_sec;
332
333 if ((yrs < 1970) || (yrs > 2069))
334 return -EINVAL;
335
336 leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
337
338 if ((mon > 12) || (day == 0))
339 return -EINVAL;
340
341 if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
342 return -EINVAL;
343
344 if ((hrs >= 24) || (min >= 60) || (sec >= 60))
345 return -EINVAL;
346
347 if (yrs >= 2000)
348 yrs -= 2000;
349 else
350 yrs -= 1900;
351
352 save_flags(flags);
353 cli();
354 if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) ||
355 RTC_ALWAYS_BCD)
356 {
357 BIN_TO_BCD(sec);
358 BIN_TO_BCD(min);
359 BIN_TO_BCD(hrs);
360 BIN_TO_BCD(day);
361 BIN_TO_BCD(mon);
362 BIN_TO_BCD(yrs);
363 }
364
365 save_control = CMOS_READ(RTC_CONTROL);
366 CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
367 save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
368 CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
369
370 CMOS_WRITE(yrs, RTC_YEAR);
371 CMOS_WRITE(mon, RTC_MONTH);
372 CMOS_WRITE(day, RTC_DAY_OF_MONTH);
373 CMOS_WRITE(hrs, RTC_HOURS);
374 CMOS_WRITE(min, RTC_MINUTES);
375 CMOS_WRITE(sec, RTC_SECONDS);
376
377 CMOS_WRITE(save_control, RTC_CONTROL);
378 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
379
380 restore_flags(flags);
381 return 0;
382 }
383 case RTC_IRQP_READ:
384 {
385 unsigned long hz;
386 int retval;
387
388 retval = verify_area(VERIFY_WRITE, (unsigned long*)arg, sizeof(unsigned long));
389 if (retval != 0)
390 return retval;
391
392 save_flags(flags);
393 cli();
394 retval = CMOS_READ(RTC_FREQ_SELECT) & 0x0f;
395 restore_flags(flags);
396 hz = (retval ? (65536/(1<<retval)) : 0);
397 memcpy_tofs((unsigned long*)arg, &hz, sizeof(unsigned long));
398 return 0;
399 }
400 case RTC_IRQP_SET:
401 {
402 int tmp = 0;
403 unsigned char val;
404
405
406
407
408 if (arg > 8192)
409 return -EINVAL;
410
411
412
413
414 if ((arg > 64) && (!suser()))
415 return -EPERM;
416
417 while (arg > (1<<tmp))
418 tmp++;
419
420
421
422
423 if ((arg != 0) && (arg != (1<<tmp)))
424 return -EINVAL;
425
426 save_flags(flags);
427 cli();
428 val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
429
430 if (arg == 0) {
431 CMOS_WRITE(val, RTC_FREQ_SELECT);
432 restore_flags(flags);
433 return 0;
434 }
435
436 val |= (16 - tmp);
437 CMOS_WRITE(val, RTC_FREQ_SELECT);
438 restore_flags(flags);
439 return 0;
440 }
441 default:
442 return -EINVAL;
443 }
444 }
445
446
447
448
449
450
451
452 static int rtc_open(struct inode *inode, struct file *file)
453 {
454
455 if(rtc_status & RTC_IS_OPEN)
456 return -EBUSY;
457
458 rtc_status |= RTC_IS_OPEN;
459 rtc_irq_data = 0;
460 return 0;
461 }
462
463 static void rtc_release(struct inode *inode, struct file *file)
464 {
465
466
467
468
469
470
471 unsigned char tmp;
472 unsigned long flags;
473
474 save_flags(flags);
475 cli();
476 tmp = CMOS_READ(RTC_CONTROL);
477 tmp &= ~RTC_PIE;
478 tmp &= ~RTC_AIE;
479 tmp &= ~RTC_UIE;
480 CMOS_WRITE(tmp, RTC_CONTROL);
481 CMOS_READ(RTC_INTR_FLAGS);
482 restore_flags(flags);
483 rtc_irq_data = 0;
484 rtc_status &= ~RTC_IS_OPEN;
485 }
486
487 static int rtc_select(struct inode *inode, struct file *file,
488 int sel_type, select_table *wait)
489 {
490 if (sel_type == SEL_IN) {
491 if (rtc_irq_data != 0)
492 return 1;
493 select_wait(&rtc_wait, wait);
494 }
495 return 0;
496 }
497
498
499
500
501
502 static struct file_operations rtc_fops = {
503 rtc_lseek,
504 rtc_read,
505 NULL,
506 NULL,
507 rtc_select,
508 rtc_ioctl,
509 NULL,
510 rtc_open,
511 rtc_release
512 };
513
514 static struct miscdevice rtc_dev=
515 {
516 RTC_MINOR,
517 "rtc",
518 &rtc_fops
519 };
520
521 int rtc_init(void)
522 {
523 printk("Real Time Clock Driver v%s\n", RTC_VERSION);
524 if(request_irq(RTC_IRQ, rtc_interrupt, SA_INTERRUPT, "rtc", NULL))
525 {
526
527 printk("rtc: IRQ %d is not free.\n", RTC_IRQ);
528 return -EIO;
529 }
530 misc_register(&rtc_dev);
531
532 request_region(RTC_IO_BASE, RTC_IO_EXTENT, "rtc");
533 rtc_wait = NULL;
534 return 0;
535 }
536
537
538
539
540
541 int get_rtc_status(char *buf)
542 {
543 char *p;
544 struct tm tm;
545 unsigned char freq, batt, ctrl;
546 unsigned long flags;
547
548 save_flags(flags);
549 freq = CMOS_READ(RTC_FREQ_SELECT) & 0x0F;
550 batt = CMOS_READ(RTC_VALID) & RTC_VRT;
551 ctrl = CMOS_READ(RTC_CONTROL);
552 restore_flags(flags);
553
554 p = buf;
555 p += sprintf(p, "Real Time Clock Status:\n");
556
557 get_rtc_time(&tm);
558
559
560
561
562
563 p += sprintf(p, "\tRTC reports %02d:%02d:%02d of %d-%d-%d.\n",
564 tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_mday,
565 tm.tm_mon + 1, tm.tm_year + 1900);
566
567 get_rtc_alm_time(&tm);
568
569
570
571
572
573
574 p += sprintf(p, "\tAlarm set to match: ");
575 if (tm.tm_hour <= 24)
576 p += sprintf(p, "hour=%d, ", tm.tm_hour);
577 else
578 p += sprintf(p, "hour=any, ");
579 if (tm.tm_min <= 59)
580 p += sprintf(p, "min=%d, ", tm.tm_min);
581 else
582 p += sprintf(p, "min=any, ");
583 if (tm.tm_sec <= 59)
584 p += sprintf(p, "sec=%d.\n", tm.tm_sec);
585 else
586 p += sprintf(p, "sec=any.\n");
587
588 p += sprintf(p, "\tMisc. settings: daylight=%s; BCD=%s; 24hr=%s; Sq-Wave=%s.\n",
589 ((ctrl & RTC_DST_EN) ? "yes" : "no" ),
590 ((ctrl & RTC_DM_BINARY) ? "no" : "yes" ),
591 ((ctrl & RTC_24H) ? "yes" : "no" ),
592 ((ctrl & RTC_SQWE) ? "yes" : "no" ));
593
594 p += sprintf(p, "\tInterrupt for: alarm=%s; update=%s; periodic=%s.\n",
595 ((ctrl & RTC_AIE) ? "yes" : "no" ),
596 ((ctrl & RTC_UIE) ? "yes" : "no" ),
597 ((ctrl & RTC_PIE) ? "yes" : "no" ));
598
599 p += sprintf(p, "\tPeriodic interrupt rate set to %dHz.\n",
600 (freq ? (65536/(1<<freq)) : 0));
601
602 p += sprintf(p, "\tRTC reports that CMOS battery is %s.\n",
603 (batt ? "okay" : "dead"));
604
605 return p - buf;
606 }
607
608
609
610
611 inline unsigned char rtc_is_updating(void)
612 {
613 unsigned long flags;
614 unsigned char uip;
615
616 save_flags(flags);
617 uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
618 restore_flags(flags);
619 return uip;
620 }
621
622 void get_rtc_time(struct tm *rtc_tm)
623 {
624
625 unsigned long flags, uip_watchdog = jiffies;
626 unsigned char ctrl;
627
628
629
630
631
632
633
634
635
636
637
638 if (rtc_is_updating() != 0)
639 while (jiffies - uip_watchdog < 2*HZ/100)
640 barrier();
641
642
643
644
645
646
647
648 save_flags(flags);
649 cli();
650 rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
651 rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
652 rtc_tm->tm_hour = CMOS_READ(RTC_HOURS);
653 rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
654 rtc_tm->tm_mon = CMOS_READ(RTC_MONTH);
655 rtc_tm->tm_year = CMOS_READ(RTC_YEAR);
656 ctrl = CMOS_READ(RTC_CONTROL);
657 restore_flags(flags);
658
659 if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
660 {
661 BCD_TO_BIN(rtc_tm->tm_sec);
662 BCD_TO_BIN(rtc_tm->tm_min);
663 BCD_TO_BIN(rtc_tm->tm_hour);
664 BCD_TO_BIN(rtc_tm->tm_mday);
665 BCD_TO_BIN(rtc_tm->tm_mon);
666 BCD_TO_BIN(rtc_tm->tm_year);
667 }
668
669
670
671
672
673 if (rtc_tm->tm_year <= 69)
674 rtc_tm->tm_year += 100;
675
676 rtc_tm->tm_mon--;
677 }
678
679 void get_rtc_alm_time(struct tm *alm_tm)
680 {
681 unsigned long flags;
682 unsigned char ctrl;
683
684
685
686
687
688 save_flags(flags);
689 cli();
690 alm_tm->tm_sec = CMOS_READ(RTC_SECONDS_ALARM);
691 alm_tm->tm_min = CMOS_READ(RTC_MINUTES_ALARM);
692 alm_tm->tm_hour = CMOS_READ(RTC_HOURS_ALARM);
693 ctrl = CMOS_READ(RTC_CONTROL);
694 restore_flags(flags);
695
696 if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
697 {
698 BCD_TO_BIN(alm_tm->tm_sec);
699 BCD_TO_BIN(alm_tm->tm_min);
700 BCD_TO_BIN(alm_tm->tm_hour);
701 }
702 }
703
704
705
706
707
708
709
710
711
712
713 inline void mask_rtc_irq_bit(unsigned char bit)
714 {
715 unsigned char val;
716 unsigned long flags;
717
718 save_flags(flags);
719 cli();
720 val = CMOS_READ(RTC_CONTROL);
721 val &= ~bit;
722 CMOS_WRITE(val, RTC_CONTROL);
723 CMOS_READ(RTC_INTR_FLAGS);
724 restore_flags(flags);
725 rtc_irq_data = 0;
726 }
727
728 inline void set_rtc_irq_bit(unsigned char bit)
729 {
730 unsigned char val;
731 unsigned long flags;
732
733 save_flags(flags);
734 cli();
735 val = CMOS_READ(RTC_CONTROL);
736 val |= bit;
737 CMOS_WRITE(val, RTC_CONTROL);
738 CMOS_READ(RTC_INTR_FLAGS);
739 restore_flags(flags);
740 rtc_irq_data = 0;
741 }
742