This new autotest module implements a simple test for the driver of realtime clock. It do the testing of interrupt, date reading, alarm and frequency. Please refer the Documentation/rtc.txt for details. Signed-off-by: Jason Wang <jasowang@xxxxxxxxxx> --- client/tests/rtc/src/Makefile | 19 +++ client/tests/rtc/src/rtctest.c | 261 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 280 insertions(+), 0 deletions(-) create mode 100644 client/tests/rtc/src/Makefile create mode 100644 client/tests/rtc/src/rtctest.c diff --git a/client/tests/rtc/control b/client/tests/rtc/control new file mode 100644 index 0000000..f0f64c9 --- /dev/null +++ b/client/tests/rtc/control @@ -0,0 +1,15 @@ +TIME="SHORT" +AUTHOR = "Jason Wang <jasowag@xxxxxxxxxx>" +DOC = """ +rtc is a simple test of realtime clock driver which was grabbed from +Documentation/rtc.txt. It does the functional test of interrupt, alarm and +requeseted frequency. + +Please refer the kernel documentation for details. +""" +NAME = 'rtc' +TEST_CLASS = 'kernel' +TEST_CATEGORY = 'Functional' +TEST_TYPE = 'client' + +job.run_test('rtc') diff --git a/client/tests/rtc/rtc.py b/client/tests/rtc/rtc.py new file mode 100644 index 0000000..d4a1500 --- /dev/null +++ b/client/tests/rtc/rtc.py @@ -0,0 +1,23 @@ +import os +from autotest_lib.client.bin import test, utils +from autotest_lib.client.common_lib import error + +class rtc(test.test): + version = 1 + + preserve_srcdir = True + + def setup(self): + os.chdir(self.srcdir) + utils.system('make') + + + def initialize(self): + self.job.require_gcc() + + + def run_once(self, def_rtc="/dev/rtc0", maxfreq=64): + if not os.path.exists(def_rtc): + raise error.TestNAError("%s doest not existed." % def_rtc) + result = utils.system(self.srcdir + '/rtctest %s %s' % (def_rtc, + maxfreq)) diff --git a/client/tests/rtc/src/Makefile b/client/tests/rtc/src/Makefile new file mode 100644 index 0000000..f99dc60 --- /dev/null +++ b/client/tests/rtc/src/Makefile @@ -0,0 +1,19 @@ +CC= cc +CFLAGS= -O -Wall -Wstrict-prototypes + +PROGS= rtctest + +SRCS= rtctest.c +OBJS= ${SRCS:.c=.o} + + +all: $(PROGS) + +rtctest: $(OBJS) + $(CC) $(LDFLAGS) -o rtctest $(OBJS) + +clean: + -rm -f $(OBJS) + +clobber: clean + -rm -f $(PROGS) diff --git a/client/tests/rtc/src/rtctest.c b/client/tests/rtc/src/rtctest.c new file mode 100644 index 0000000..25b74af --- /dev/null +++ b/client/tests/rtc/src/rtctest.c @@ -0,0 +1,261 @@ +/* + * Real Time Clock Driver Test/Example Program + * + * Compile with: + * gcc -s -Wall -Wstrict-prototypes rtctest.c -o rtctest + * + * Copyright (C) 1996, Paul Gortmaker. + * Copyright (C) 2010, Jason Wang <jasowang@xxxxxxxxxx> + * + * 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 <stdlib.h> +#include <errno.h> + + +/* + * This expects the new RTC class driver framework, working with + * clocks that will often not be clones of what the PC-AT had. + * Use the command line to specify another RTC if you need one. + */ +static const char default_rtc[] = "/dev/rtc0"; +static int maxfreq = 64; + +int main(int argc, char **argv) +{ + int i, fd, retval, irqcount = 0; + unsigned long tmp, data; + struct rtc_time rtc_tm; + const char *rtc = default_rtc; + + switch (argc) { + case 3: + maxfreq = atoi(argv[2]); + case 2: + rtc = argv[1]; + /* FALLTHROUGH */ + case 1: + break; + default: + fprintf(stderr, "usage: rtctest [rtcdev] [maxfreq]\n"); + return 1; + } + + fd = open(rtc, O_RDONLY); + + if (fd == -1) { + perror(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) { + if (errno == ENOTTY) { + fprintf(stderr, + "\n...Update IRQs not supported.\n"); + goto test_READ; + } + perror("RTC_UIE_ON ioctl"); + exit(errno); + } + + fprintf(stderr, "Counting 5 update (1/sec) interrupts from reading %s:", + 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("RTC_UIE_OFF ioctl"); + exit(errno); + } + +test_READ: + /* Read the RTC time/date */ + retval = ioctl(fd, RTC_RD_TIME, &rtc_tm); + if (retval == -1) { + perror("RTC_RD_TIME 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) { + if (errno == ENOTTY) { + fprintf(stderr, + "\n...Alarm IRQs not supported.\n"); + goto test_PIE; + } + perror("RTC_ALM_SET ioctl"); + exit(errno); + } + + /* Read the current alarm settings */ + retval = ioctl(fd, RTC_ALM_READ, &rtc_tm); + if (retval == -1) { + perror("RTC_ALM_READ 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("RTC_AIE_ON 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("RTC_AIE_OFF ioctl"); + exit(errno); + } + +test_PIE: + /* Read periodic IRQ rate */ + retval = ioctl(fd, RTC_IRQP_READ, &tmp); + if (retval == -1) { + /* not all RTCs support periodic IRQs */ + if (errno == ENOTTY) { + fprintf(stderr, "\nNo periodic IRQ support\n"); + goto done; + } + perror("RTC_IRQP_READ ioctl"); + exit(errno); + } + fprintf(stderr, "\nPeriodic IRQ rate is %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<=maxfreq; tmp*=2) { + + retval = ioctl(fd, RTC_IRQP_SET, tmp); + if (retval == -1) { + /* not all RTCs can change their periodic IRQ rate */ + if (errno == ENOTTY) { + fprintf(stderr, + "\n...Periodic IRQ rate is fixed\n"); + goto done; + } + perror("RTC_IRQP_SET 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("RTC_PIE_ON 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("RTC_PIE_OFF ioctl"); + exit(errno); + } + } + +done: + fprintf(stderr, "\n\n\t\t\t *** Test complete ***\n"); + + close(fd); + + return 0; +} -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html