
              Linux ѥꥢ륿९åɥ饤
              ====================================

Ƥ PC (Alpha ޥޤߤޤ) ˤϡꥢ륿९åȤ
ޤƤޤ̾ϥԥ塼ΥåץåȤȤ߹ޤ
ƤΤǤMotorola MC146818 (⤷ϤΥ) ܡɾ
ܤƤ⤢ޤΥåϡԥ塼Ÿ
Ƥ뤢⡢³Ƥޤ

ꥢ륿९åϡ2Hz Ȥ®Ū® 8192Hz ޤǤ
ϰϤˤȿ â2 ߾ͤμȿ ȯ륷ʥ
ΤˤȤȤǤޤΥʥϡֹ 8 
ޤ (ޤˤΤ IRQ 8 ȤƤΤǤ!) ꤵ줿
ˤʤäȤ IRQ 8 ȯ 24 ֥顼ȤƻȤȤ
Ǥޤץߥ󥰲ǽ 3 Ĥͤβ餫Ȥ߹碌 㤨С
ػٻʬٻá١ å뤿˥顼
Ѥ뤳ȤǤޤåΤӤ˳ߤȯ褦ˤ
С1Hz Υʥ뤳ȤǤޤ

ߤϡunsigned long ѿȤ /dev/rtc (᥸㡼ֹ 10, ޥ
ʡֹ 135, ɹѥ饯ǥХ) ͳΤޤ̤
1 ХȤǡȯߤμ (ֹԤ줿ס֥顼बĤäס
⤷ϡּ) 򼨤ĤʣХȤǡǸɹ߽ʹߤ
ȯ߲ϿƤޤ/proc ե륷ƥबͭʤС
ۥե /proc/driver/rtc 饹ơǤޤɥ
Фϡ٤˰ĤΥץ /dev/rtc 󥿡ե򥪡ץ
Ǥʤ褦ˤ뤿ᡢåǽƤޤ

桼ץϡ/dev/rtc  read(2) 뤫 select(2) 뤳Ȥˤäơ
ߤƻ뤹뤳ȤǤޤread  select ⡢γߤȯ
ޤǥ桼ץ֥åߤޤgettimeofday ʤɤǥݡ
򤷤 CPU ѥȤ̤褦ʤȤϤʤɤ⡢Ǥ
ʤ٤ǥǡ򤪤ʤȤ褦ʾˤϡ
ǽΩޤ

RTC ⤤ȿꤷƤ뤫⤷٤⤤֤ΤȤˤϡ
ߤѤȯƤޤäƤʤɤǧ뤿ᡢ
ǸɽФ򤪤ʤäγ߼å
ۤ褤Ǥ礦ͤޤǤ˸ޤȡ/dev/rtc ɤ߽Ф
롼פ¹ԤŵŪ 486/33Hz ƥǤϡ1024Hz ⤤
ξ硢ȤߤѤȯƤޤޤ (ĤޤꡢǸ
ɹ߽ 2 İʾ IRQ ٥ȤȯƤ) ǤΤǡ
ɤ߽Фͤξ̥ХȤϥå٤Ǥ礦äˡ̾Υ
ߤμȿ (100Hz) ⤤ȿξϡȤå
Ƥ

64Hz 礭߼ȿꤷͭˤꤹ뤳Ȥ
Τϡroot ΤߤǤϼ㴳ݼŪ᤮褦ʵ⤷ޤ
ʤ顢IRQ ȯѥեޥ󥹤˰ƶͿǽΤ
386SX/16Hz Τ褦®ޥǡIRQ ȯ褦Ȥ밭դ
桼ʤȤ¤ޤ󡣤ʤΤ褦ʥѥեޥ󥹤ؤ
ƶǾ뤿ᡢߥϥɥϤۤοԤΥɤΤߤǹ
Ƥޤ

ޤͥ郎ƱƤ硢ͥ 11 ʬȤ
CMOS ػ񤭹ߤޤν򤪤ʤäƤ뤢ϡRTC 
ߤϰŪ˥դˤƤޤRTC Ȥäƽפʽ򤪤ʤä
ϡΤȤαդƤƤ (NTP ʤ) 
ͥƱƤʤϡͥ RTC ˰ڴΤʤ
ΤǡץꥱѤΥǥХȤ RTC ¾Ū˻Ѥ뤳Ȥ
Ǥޤ

include/linux/rtc.h ˥ꥹȥåפƤ͡ ioctl(2) ƽФ
Ȥ顼߼ȿ RTC ˥ץߥ󥰤뤳ȤǤޤ
ioctl() ʤɤˤĤ 50 ڡ⵭Ҥ⡢λȤɥ
Фεǽ򼨤ʥƥȥץ󼨤ۤͭפȻפޤ
Υɥ饤ФȤץꥱ뤳Ȥ˶̣Τ͡ˤȤ
ƤϡɤΤۤäΩĤǤ礦

                                                Paul Gortmaker

ΡJF ץ < http://www.linux.or.jp/JF/ >
  ԡ ɧ < takahiko@hakubi.co.jp >
  ԡ  < hng@ps.ksky.ne.jp >



-------------------- 8< ---------------- 8< -----------------------------

/*
 *      Real Time Clock Driver Test/Example Program
 *
 *      Compile with:
 *              gcc -s -Wall -Wstrict-prototypes rtctest.c -o rtctest
 *
 *      Copyright (C) 1996, Paul Gortmaker.
 *
 *      Released under the GNU General Public License, version 2,
 *      included herein by reference.
 *
 */

#include <stdio.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

int main(void) {

int i, fd, retval, irqcount = 0;
unsigned long tmp, data;
struct rtc_time rtc_tm;

fd = open ("/dev/rtc", O_RDONLY);

if (fd ==  -1) {
        perror("/dev/rtc");
        exit(errno);
}

fprintf(stderr, "\n\t\t\tRTC Driver Test Example.\n\n");

/* Turn on update interrupts (one per second) */
retval = ioctl(fd, RTC_UIE_ON, 0);
if (retval == -1) {
        perror("ioctl");
        exit(errno);
}

fprintf(stderr, "Counting 5 update (1/sec) interrupts from reading /dev/rtc:");
fflush(stderr);
for (i=1; i<6; i++) {
        /* This read will block */
        retval = read(fd, &data, sizeof(unsigned long));
        if (retval == -1) {
                perror("read");
                exit(errno);
        }
        fprintf(stderr, " %d",i);
        fflush(stderr);
        irqcount++;
}

fprintf(stderr, "\nAgain, from using select(2) on /dev/rtc:");
fflush(stderr);
for (i=1; i<6; i++) {
        struct timeval tv = {5, 0};     /* 5 second timeout on select */
        fd_set readfds;

        FD_ZERO(&readfds);
        FD_SET(fd, &readfds);
        /* The select will wait until an RTC interrupt happens. */
        retval = select(fd+1, &readfds, NULL, NULL, &tv);
        if (retval == -1) {
                perror("select");
                exit(errno);
        }
        /* This read won't block unlike the select-less case above. */
        retval = read(fd, &data, sizeof(unsigned long));
        if (retval == -1) {
                perror("read");
                exit(errno);
        }
        fprintf(stderr, " %d",i);
        fflush(stderr);
        irqcount++;
}

/* Turn off update interrupts */
retval = ioctl(fd, RTC_UIE_OFF, 0);
if (retval == -1) {
        perror("ioctl");
        exit(errno);
}

/* Read the RTC time/date */
retval = ioctl(fd, RTC_RD_TIME, &rtc_tm);
if (retval == -1) {
        perror("ioctl");
        exit(errno);
}

fprintf(stderr, "\n\nCurrent RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n",
        rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900,
        rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);

/* Set the alarm to 5 sec in the future, and check for rollover */
rtc_tm.tm_sec += 5;
if (rtc_tm.tm_sec >= 60) {
        rtc_tm.tm_sec %= 60;
        rtc_tm.tm_min++;
}
if  (rtc_tm.tm_min == 60) {
        rtc_tm.tm_min = 0;
        rtc_tm.tm_hour++;
}
if  (rtc_tm.tm_hour == 24)
        rtc_tm.tm_hour = 0;

retval = ioctl(fd, RTC_ALM_SET, &rtc_tm);
if (retval == -1) {
        perror("ioctl");
        exit(errno);
}

/* Read the current alarm settings */
retval = ioctl(fd, RTC_ALM_READ, &rtc_tm);
if (retval == -1) {
        perror("ioctl");
        exit(errno);
}

fprintf(stderr, "Alarm time now set to %02d:%02d:%02d.\n",
        rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);

/* Enable alarm interrupts */
retval = ioctl(fd, RTC_AIE_ON, 0);
if (retval == -1) {
        perror("ioctl");
        exit(errno);
}

fprintf(stderr, "Waiting 5 seconds for alarm...");
fflush(stderr);
/* This blocks until the alarm ring causes an interrupt */
retval = read(fd, &data, sizeof(unsigned long));
if (retval == -1) {
        perror("read");
        exit(errno);
}
irqcount++;
fprintf(stderr, " okay. Alarm rang.\n");

/* Disable alarm interrupts */
retval = ioctl(fd, RTC_AIE_OFF, 0);
if (retval == -1) {
        perror("ioctl");
        exit(errno);
}

/* Read periodic IRQ rate */
retval = ioctl(fd, RTC_IRQP_READ, &tmp);
if (retval == -1) {
        perror("ioctl");
        exit(errno);
}
fprintf(stderr, "\nPeriodic IRQ rate was %ldHz.\n", tmp);

fprintf(stderr, "Counting 20 interrupts at:");
fflush(stderr);

/* The frequencies 128Hz, 256Hz, ... 8192Hz are only allowed for root. */
for (tmp=2; tmp<=64; tmp*=2) {

        retval = ioctl(fd, RTC_IRQP_SET, tmp);
        if (retval == -1) {
                perror("ioctl");
                exit(errno);
        }

        fprintf(stderr, "\n%ldHz:\t", tmp);
        fflush(stderr);

        /* Enable periodic interrupts */
        retval = ioctl(fd, RTC_PIE_ON, 0);
        if (retval == -1) {
                perror("ioctl");
                exit(errno);
        }

        for (i=1; i<21; i++) {
                /* This blocks */
                retval = read(fd, &data, sizeof(unsigned long));
                if (retval == -1) {
                        perror("read");
                        exit(errno);
                }
                fprintf(stderr, " %d",i);
                fflush(stderr);
                irqcount++;
        }

        /* Disable periodic interrupts */
        retval = ioctl(fd, RTC_PIE_OFF, 0);
        if (retval == -1) {
                perror("ioctl");
                exit(errno);
        }
}

fprintf(stderr, "\n\n\t\t\t *** Test complete ***\n");
fprintf(stderr, "\nTyping \"cat /proc/interrupts\" will show %d more events on IRQ 8.\n\n",
                                                                 irqcount);

close(fd);
return 0;

} /* end main */



-------- ꥢ륿९åɥ饤Сƥȥץܸ --------
/*
 *       ꥢ륿९åɥ饤
 *         ƥȥץܸ
 *
 *
 *    Copyright (C) 2002, Takahiko KAWASAKI.
 *
 *
 *   Paul Gortmaker 󤬽񤫤줿 'Real Time
 *   Clock Driver Test/Example Program' 
 *   ܸѤɤߤ䤹񤭤ΤǤ
 *
 *   ߡ顼ࡢߡϡ
 *   줾졢update_interrupt_test(),
 *   alarm_test(), periodic_interrupt_test()
 *   ˤޤ
 *
 *   GNU General Public License, version 2 
 *   饤󥹤ޤ
 */

/*
 *   [ 2.4.17  include/linux/rtc.h  ]
 *
 *      RTC_AIE_ON         顼ߤͭˤ
 *      RTC_AIE_OFF        顼ߤ̵ˤ
 *      RTC_UIE_ON         ߤͭˤ
 *      RTC_UIE_OFF        ߤ̵ˤ
 *      RTC_PIE_ON         ߤͭˤ
 *      RTC_PIE_OFF        ߤ̵ˤ
 *      RTC_WIE_ON         åɥåߤͭˤ
 *      RTC_WIE_OFF        åɥåߤͭˤ
 *
 *      RTC_ARM_SET        顼򥻥åȤ
 *      RTC_ARM_READ       顼ɤ߽Ф
 *      RTC_RD_TIME        RTC ɤ߽Ф
 *      RTC_SET_TIME       RTC 򥻥åȤ
 *      RTC_IRQP_READ      IRQ ȿɤ߽Ф
 *      RTC_IRQP_SET       IRQ ȿ򥻥åȤ
 *      RTC_EPOCH_READ     ݥåɤ߽Ф
 *      RTC_EPOCH_SET      ݥå򥻥åȤ
 *
 *      RTC_WKALM_SET      顼򥻥åȤ
 *      RTC_WKALM_RD       顼
 */



/****************************************
  إåե
****************************************/
#include <stdio.h>
#include <stdlib.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdarg.h>


/****************************************
  static ؿץȥ
****************************************/
static void    do_tests(void);
static void    perror_exit(const char *msg);
static void    print_msg(const char *fmt, ...);
/* ߥƥ */
static void    update_interrupt_test(void);
static void    count_by_reading(void);
static void    count_by_selecting(void);
/* 顼ƥ */
static void    alarm_test(void);
static void    set_alarm(int sec);
static void    read_current_rtc(struct rtc_time *rtc_tm);
static void    add_sec_to_rtc_time(struct rtc_time *rtc_tm, int sec);
/* ߥƥ */
static void    print_periodic_irq_rate(void);
static void    periodic_interrupt_test(void);
static void    count_periodic_interrupt(void);
static void    count_one_pirq(unsigned long pirq_rate);
/* åѡؿ */
static int     Open(const char *path, int flags);
static int     Ioctl(int fd, int request, void *arg);
static ssize_t Read(int fd, void *buf, size_t count);
static int     Select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tout);


/****************************************
  static ѿ
****************************************/
static unsigned long  m_irqcount;             /* ȯ */
static int            m_fd;                   /* /dev/rtc ե뵭һ */


/**************************************************
  main()
**************************************************/
int
main(void)
{
        /************************************************************
          ƥȳϥå
        ************************************************************/
        print_msg("\n\t\t\tRTC ɥ饤Хƥ\n\n");


        /************************************************************
          ƼƥȤ¹Ԥ롣
        ************************************************************/
        do_tests();


        /************************************************************
          ƥȽλå
        ************************************************************/
        print_msg("\n\n\t\t\t *** ƥȴλ ***\n\n");
        print_msg(
                "IRQ 8  %lu ʾΥ٥ȤɲäƤ뤳Ȥ\n"
                "'cat /proc/interrupts' ǳǧ뤳ȤǤޤ\n\n",
                m_irqcount
        );


        return EXIT_SUCCESS;
}


/**************************************************
  do_tests()
**************************************************/
static void
do_tests(void)
{
        /************************************************************
          RTC ΥǥХե '/dev/rtc' 򥪡ץ󤹤롣
        ************************************************************/
        m_fd = Open("/dev/rtc", O_RDONLY);


        /************************************************************
          ߥƥ
        ************************************************************/
        update_interrupt_test();


        /************************************************************
          顼ƥ
        ************************************************************/
        alarm_test();


        /************************************************************
          ߥƥ
        ************************************************************/
        periodic_interrupt_test();


        /************************************************************
          RTC ΥǥХե '/dev/rtc' 򥯥롣
        ************************************************************/
        close(m_fd);
}


/**************************************************
  perror_exit()
**************************************************/
static void
perror_exit(const char *msg)
{
        perror(msg);
        exit(errno);
}


/**************************************************
  print_msg()
**************************************************/
static void
print_msg(const char *fmt, ...)
{
        va_list args;


        va_start(args, fmt);

        vfprintf(stderr, fmt, args);

        /************************************************************
          stderr ϥץˤϥХåե󥰤ƤʤΤǡ
          虜虜 fflush(stderr) ϼ¹Ԥʤ
        ************************************************************/

        va_end(ap);
}


/*
 *
 *
 * ߥƥ
 *
 *
 */

/**************************************************
  update_interrupt_test()
**************************************************/
static void
update_interrupt_test(void)
{
        print_msg("ߥƥ\n");


        /************************************************************
          ô֤˰Υڡǹߤȯ褦ˤ롣
        ************************************************************/
        Ioctl(m_fd, RTC_UIE_ON, 0);


        /************************************************************
          /dev/rtc  read 뤳Ȥ RTC ͤɤ߽Ф
        ************************************************************/
        count_by_reading();


        /************************************************************
          /dev/rtc ɽФǽǤ뤳Ȥ select ǳǧƤ顢
          /dev/rtc  read RTC ͤɤ߽Ф
        ************************************************************/
        count_by_selecting();


        /************************************************************
          ߤȯ롣
        ************************************************************/
        Ioctl(m_fd, RTC_UIE_OFF, 0);
}


/**************************************************
  count_by_reading()
**************************************************/
static void
count_by_reading(void)
{
        int i;
        unsigned long data;


        print_msg(
                "\t*  ()  /dev/rtc  read 뤳Ȥˤ\n"
                "\t  5 ޤ:"
        );


        /************************************************************
          RTC  5 ɤ߽Ф
        ************************************************************/
        for ( i = 1; i < 6; i++ ) {
                /************************************************************
                  RTC ɤ߽Ф
                ************************************************************/
                Read(m_fd, &data, sizeof(unsigned long));
                print_msg(" %d", i);


                /* ߲򥫥Ȥ */
                m_irqcount++;
        }
}


/**************************************************
  count_by_selecting()
**************************************************/
static void
count_by_selecting(void)
{
        int i;
        unsigned long data;
        struct timeval tv;
        fd_set readfds;


        print_msg(
                "\n\n\t* ƱƥȤǤread ¹Ԥ /dev/rtc ɹ\n"
                "\t  ǽǤ뤫ɤ select(2) Ĵ٤ޤߤ\n"
                "\t  5 ޤ:"
        );


        /************************************************************
          RTC  5 ɤ߽Ф
        ************************************************************/
        for ( i = 1; i < 6; i++ ) {
                /************************************************************
                  select ΥॢȤ 5 äꤹ롣
                ************************************************************/
                tv.tv_sec = 5;
                tv.tv_usec = 0;


                /************************************************************
                  m_fd ɹ߲ǽˤʤäɤĴ٤뤿ν򤹤롣
                ************************************************************/
                FD_ZERO(&readfds);
                FD_SET(m_fd, &readfds);


                /************************************************************
                  select ϡߤȯޤԤ ( 5 ää
                  ߤȯʤХॢȤ) 
                ************************************************************/
                Select(m_fd+1, &readfds, NULL, NULL, &tv);


                /************************************************************
                  Ȥϰۤʤꡢ read ϥ֥åʤ
                ************************************************************/
                Read(m_fd, &data, sizeof(unsigned long));
                print_msg(" %d", i);


                /* ߲򥫥Ȥ */
                m_irqcount++;
        }
}


/*
 *
 *
 * 顼ƥ
 *
 *
 */

/**************************************************
  alarm_test()
**************************************************/
static void
alarm_test(void)
{
        unsigned long data;


        print_msg("\n\n顼ƥ\n");


        /************************************************************
          5 ø˥顼बȯ褦ꤹ롣
        ************************************************************/
        set_alarm(5);
        print_msg("\t* 顼बȯޤ 5 ôԤޤ...");


        /************************************************************
          RTC ͤɤ߽Ф
        ************************************************************/
        Read(m_fd, &data, sizeof(unsigned long));
        print_msg(" \n\t  顼बĤޤ\n");


        /* ߲򥫥Ȥ */
        m_irqcount++;


        /************************************************************
          顼ߤ̵ˤ롣
        ************************************************************/
        Ioctl(m_fd, RTC_AIE_OFF, 0);
}


/**************************************************
  set_alarm()
**************************************************/
static void
set_alarm(int sec)
{
        struct rtc_time rtc_tm;


        /************************************************************
          ߤ RTC ɤ߽Ф rtc_tm ˥åȤ롣
        ************************************************************/
        read_current_rtc(&rtc_tm);


        /************************************************************
          rtc_tm ͤ sec ÿʤ롣
        ************************************************************/
        add_sec_to_rtc_time(&rtc_tm, sec);


        /************************************************************
          sec ø˥顼बȯ褦ꤹ롣
        ************************************************************/
        Ioctl(m_fd, RTC_ALM_SET, &rtc_tm);


        /************************************************************
          äꤷ顼ͤɤ߽Ф
        ************************************************************/
        Ioctl(m_fd, RTC_ALM_READ, &rtc_tm);


        /************************************************************
          ꤵƤ륢顼ξɽ롣
        ************************************************************/
        print_msg("\t* 顼郎 '%02d  %02d ʬ %02d ' ꤵޤ\n",
                rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec
        );


        /************************************************************
          顼ߤͭˤ롣
        ************************************************************/
        Ioctl(m_fd, RTC_AIE_ON, 0);
}


/**************************************************
  read_current_rtc()
**************************************************/
static void
read_current_rtc(struct rtc_time *rtc_tm)
{
        /************************************************************
          ߤ RTC ɤ߽Ф rtc_tm ˥åȤ롣
        ************************************************************/
        Ioctl(m_fd, RTC_RD_TIME, rtc_tm);


        /************************************************************
          ߤ RTC ɽ롣
        ************************************************************/
        print_msg("\t* RTC ߻: %d ǯ %d  %d  %02d  %02d ʬ %02d \n",
                rtc_tm->tm_year + 1900, rtc_tm->tm_mon + 1, rtc_tm->tm_mday,
                rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec
        );
}


/**************************************************
  add_sec_to_rtc_time()
**************************************************/
static void
add_sec_to_rtc_time(struct rtc_time *rtc_tm, int sec)
{
        rtc_tm->tm_sec += sec;

        if ( rtc_tm->tm_sec >= 60 ) {
                rtc_tm->tm_sec %= 60;
                rtc_tm->tm_min++;
        }

        if ( rtc_tm->tm_min == 60 ) {
                rtc_tm->tm_min = 0;
                rtc_tm->tm_hour++;
        }

        if ( rtc_tm->tm_hour == 24 ) {
                rtc_tm->tm_hour = 0;
        }
}


/*
 *
 *
 * ߥƥ
 *
 *
 */

/**************************************************
  periodic_interrupt_test()
**************************************************/
static void
periodic_interrupt_test(void)
{
        print_msg("\nߥƥ\n");


        /************************************************************
           IRQ 졼Ȥɽ롣
        ************************************************************/
        print_periodic_irq_rate();


        /************************************************************
           IRQ 졼ȤѲʤ顢RTC ɹߥƥȤԤ
        ************************************************************/
        count_periodic_interrupt();
}


/**************************************************
  print_periodic_irq_rate()
**************************************************/
static void
print_periodic_irq_rate(void)
{
        unsigned long pirq_rate;


        /************************************************************
           IRQ 졼Ȥɤ߽Ф
        ************************************************************/
        Ioctl(m_fd, RTC_IRQP_READ, &pirq_rate);


        /************************************************************
           IRQ 졼Ȥɽ롣
        ************************************************************/
        print_msg("\t*  IRQ 졼Ȥ %luHz Ǥ\n", pirq_rate);
}


/**************************************************
  count_periodic_interrupt()
**************************************************/
static void
count_periodic_interrupt(void)
{
        unsigned long pirq_rate;
        unsigned long rate_max;


        print_msg("\t* ȿѲʤ RTC ɼƥȤ¹Ԥޤ\n");


        /************************************************************
          ƥȤȿκͤ롣Υץμ¸桼
          ID  root ξϡ8192Hz ޤǥƥȤ롣root ǤϤʤ
          ϡ64Hz ޤǤΥƥȤȤ롣
        ************************************************************/
        if ( geteuid() == 0 ) {
                rate_max = 8192;        /* 8192Hz */
        }
        else {
                rate_max = 64;                /* 64Hz */
        }


        /************************************************************
          ȿ 2Hz, 4Hz, 8Hz, 16Hz, 32Hz, 64Hz ˽缡Ѥ
          ƥȤ򤪤ʤ128Hz, 256Hz, ... 8192Hz ϡroot
          Τߤ˵Ƥ롣
        ************************************************************/
        for ( pirq_rate = 2; pirq_rate <= rate_max; pirq_rate *= 2 ) {
                count_one_pirq(pirq_rate);
        }
}


/**************************************************
  count_one_pirq()
**************************************************/
static void
count_one_pirq(unsigned long pirq_rate)
{
        int i;
        unsigned long data;


        /************************************************************
          RTC μȿꤹ롣
        ************************************************************/
        Ioctl(m_fd, RTC_IRQP_SET, (void *)pirq_rate);
        print_msg("\n\t%4luHz:\t", pirq_rate);


        /************************************************************
          ߤͭˤ롣
        ************************************************************/
        Ioctl(m_fd, RTC_PIE_ON, 0);


        /************************************************************
          20  RTC ɤ߽Ф
        ************************************************************/
        for ( i = 1; i < 21; i++ ) {
                /************************************************************
                  RTC ɤ߽Ф
                ************************************************************/
                Read(m_fd, &data, sizeof(unsigned long));
                print_msg(" %d", i);


                /* ߲򥫥Ȥ */
                m_irqcount++;
        }


        /************************************************************
          ߤ̵ˤ롣
        ************************************************************/
        Ioctl(m_fd, RTC_PIE_OFF, 0);
}


/*
 *
 *
 * åѡؿ
 *
 *
 */

/**************************************************
  Open()
**************************************************/
static int
Open(const char *path, int flags)
{
        int fd;


        fd = open(path, flags);
        if ( fd == -1 ) {
                perror_exit("open");
        }

        return fd;
}


/**************************************************
  Ioctl()
**************************************************/
static int
Ioctl(int fd, int request, void *arg)
{
        int ret;


        ret = ioctl(fd, request, arg);
        if ( ret == -1 ) {
                perror_exit("ioctl");
        }

        return ret;
}


/**************************************************
  Read()
**************************************************/
static ssize_t
Read(int fd, void *buf, size_t count)
{
        ssize_t n;


        n = read(fd, buf, count);
        if ( n == -1 ) {
                perror_exit("read");
        }

        return n;
}


/**************************************************
  Select()
**************************************************/
static int
Select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tout)
{
        int ret;


        ret = select(n, rfds, wfds, efds, tout);
        if ( ret == -1 ) {
                perror_exit("select");
        }

        return ret;
}
