Во время компиляции ядра вставляется соответствующая ветка дерева кода (х86, РРС, MIPS и т. д.). Здесь обсуждается РРС вариант исходного файла для обобщенного драйвера RTC не х86 систем.
/drivers/char/genrtc.с
276 static int gen_rtc_ioctl(struct inode *inode, struct file *file,
277 unsigned int cmd, unsigned long arg)
278 {
279 struct rtc_time wtime;
280 struct rtc_pll_info pll; 281
2 82 switch (cmd) {
283
284 case RTC_PLL_GET:
290 case RTC_PLL_SET:
298
302
305 306 307 308 309 310 311 312 313 314
353 354 355 356 357
case RTC_UIE_OFF: /* отключение прерываний от обновлений RTC. */
case RTC_UIE_ON: /* включение прерываний от обновлений RTC. */
case RTC_RD_TIME: /* Чтение времени/даты из RTC */
memset(&wtime, 0, sizeof(wtime)); get_rtc_time(&wtime);
return copy_to_user((void *)arg,&wtime,sizeof(wtime)) ? -EFAULT:0;
case RTC_SET_TIME: /* Set the RTC */
return -EINVAL;
}
static int gen_rtc_open(struct inode *inode, struct file *file) {
if (gen_rtc_status & RTC_IS_OPEN) return -EBUSY; gen_rtc_status |= RTC_IS_OPEN;
Этот код реализует тот же набор команд ioctl. Так как мы выполняем вызов ioctl ■з проверочной программы пользовательского пространства с флагом RTC_RD_TIME, управление передается на строку 305. Следующий вызов в строке 308 - это get_rtc_time(&wtime) из rtc.h (см. соответствующий код). Перед тем как оставить этот блок кода, обратите внимание на строку 353. Она позволяет получать доступ к драйверу только для одного пользователя зараз с помощью open (), устанавливающей состояние драйвера в RTC_IS_OPEN:
include/asm-ppc/rtc.h
45 static inline unsigned int get_rtc_time(struct rtc_time *time)
46 {
nowtime = (ppc_md.get_rtc_time)() to_tm(nowtime, time);
if (ppc_md.get_rtc_time) { unsigned long nowtime;
356
}
057 return RTC_24H;
058 }
Встроенная функция get_rtc_time () вызывает функцию, устанавливающую переменную-указатель в значение ppc_md. get_rtc_time на строке 50. Ранее при инициализации ядра эта переменная устанавливалась в chrp_setup. с:
arch/ppc/platforms/chrp_setup.с
447 chrp_init(unsigned long гЗ, unsigned long r4, unsigned long r5,
448 unsigned long r6, unsigned long r7)
449 {
477 ppc_md.time_init = chrp_time_init;
478 ppc_md.set_rtc_time = chrp_set_rtc_time;
479 ppc_md.get_rtc_time = chrp_get_rtc_time;
480 ppc_md.calibrate_decr = chrp_calibrate_decr;
Функция chrp_get_rtc_time () (в строке 479) определена в chrp_time. с в следующем блоке кода. Так как информация о времени в памяти CMOS обновляется на периодической основе, блокировка кода чтения включена в цикл for, который пересчитывает обновляемые в прогрессе блоки:
arch/ppc/platforms/chrp_time.с
122 unsigned long chrp chrp_get_rtc_time(void)
123 {
124 unsigned int year, mon, day, hour, min, sec;
125 int uip, i;
141 for ( i = 0; i<1000000; i++) {
142 uip = chrp_cmos_clock_read(RTC_FREQ_SELECT);
143 sec = chrp_cmos_clock_read(RTC_SECONDS);
144 min = chrp_cmos_clock_read(RTC_MINUTES);
145 hour = chrp_cmos_clock_read(RTC_HOURS);
146 day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH);
147 mon = chrp_cmos_clock_read(RTC_MONTH);
148 year = chrp_cmos_clock_read(RTC_YEAR);
149 uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT);
150 if ((uip & RTC_UIP)==0) break;
151 }
152 if (!(chrp_cmos_clock_read(RTC_CONTROL)
153 & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
154 {