NetBSD/sys/arch/x68k/usr.bin/rtcalarm/rtcalarm.c

315 lines
7.2 KiB
C

/* $NetBSD: rtcalarm.c,v 1.3 1998/08/04 16:10:45 minoura Exp $ */
/*
* Copyright (c) 1995 MINOURA Makoto.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Minoura Makoto.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* rtcalarm: X68k RTC alarm test program */
#ifndef __GNUC__
#define __volatile
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <machine/powioctl.h>
char *prog;
static __volatile void usage __P((void));
static __volatile void myperror __P((const char *, int));
static void showinfo __P((void));
static char *numstr __P((unsigned int));
static void showontime __P((unsigned int));
static void disablealarm __P((void));
static void setinfo __P((int, char **));
static int strnum __P((const char *, int));
int
main(argc, argv)
int argc;
char *argv[];
{
prog = argv[0];
if (argc == 1)
showinfo();
else if (argc == 2 && strcmp(argv[1], "off") == 0)
disablealarm();
else
setinfo(argc, argv);
return 0;
}
static __volatile void
usage(void)
{
fprintf(stderr, "Usage: %s [[-w day-of-the-week] [-d day-of-the-month]\n", prog);
fprintf(stderr, " [-m minites] [-s seconds] [-c channel] HH:MM]\n");
exit(1);
}
static __volatile void
myperror(str, fd)
const char *str;
int fd;
{
fprintf(stderr, "%s: %s: %s\n", prog, str, strerror(errno));
if (fd >= 0)
close(fd);
exit(1);
}
static void
showinfo(void)
{
struct x68k_alarminfo alarminfo;
int fd;
fd = open("/dev/pow1", O_RDONLY);
if (fd < 0)
myperror("Opening /dev/pow1", -1);
if (ioctl(fd, POWIOCGALARMINFO, &alarminfo) < 0)
myperror("powiocgalarminfo", fd);
close(fd);
if (alarminfo.al_enable) {
showontime(alarminfo.al_ontime);
if (alarminfo.al_dowhat == 0 || alarminfo.al_dowhat == -1)
printf("Computer mode.\n");
else if (alarminfo.al_dowhat >= 0x30 && alarminfo.al_dowhat <= 0x3b)
printf("TV channel %d.\n", alarminfo.al_dowhat - 0x30 + 1);
else if (alarminfo.al_dowhat < 0x40)
printf("TV mode.\n");
else
printf("Computer mode. ADDR=%8.8x\n", alarminfo.al_dowhat);
if (alarminfo.al_offtime == 0)
printf("Never shut down automatically.\n");
else
printf("Shut down in %d seconds (%d minutes).\n",
alarminfo.al_offtime,
alarminfo.al_offtime / 60);
} else {
printf("RTC alarm is disabled.\n");
}
}
static char *
numstr(num)
unsigned int num;
{
static char buffer[4];
if ((num & 0xf0) == 0xf0)
buffer[0] = 'x';
else
buffer[0] = ((num & 0xf0) >> 4) + '0';
if ((num & 0x0f) == 0x0f)
buffer[1] = 'x';
else
buffer[1] = (num & 0x0f) + '0';
buffer[2] = 0;
return buffer;
}
const char *weekname[] =
{
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
};
static void
showontime(ontime)
unsigned int ontime;
{
printf("At %s:", numstr((ontime & 0x0000ff00) >> 8));
printf("%s ", numstr(ontime & 0x000000ff));
if ((ontime & 0x0fff0000) != 0x0fff0000) {
if ((ontime & 0x0f000000) != 0x0f000000) {
if ((ontime & 0x00ff0000) != 0x00ff0000)
printf("on %s, %sth in every month, \n",
weekname[(ontime & 0x0f000000) >> 24],
numstr((ontime & 0x00ff0000) >> 16));
else
printf("on every %s, \n",
weekname[(ontime & 0x0f000000) >> 24]);
} else
printf("on %sth in every month, \n",
numstr((ontime & 0x00ff0000) >> 16));
} else
printf("everyday.\n");
}
static void
disablealarm(void)
{
int fd;
struct x68k_alarminfo alarminfo;
alarminfo.al_enable = 0;
fd = open("/dev/pow1", O_WRONLY);
if (fd < 0)
myperror("Opening /dev/pow1", -1);
if (ioctl(fd, POWIOCSALARMINFO, &alarminfo) < 0)
myperror("powiocsalarminfo", fd);
close(fd);
}
static void
setinfo(argc, argv)
int argc;
char **argv;
{
int ch;
int week = 0x0f;
int hour = 0xffff;
int day = 0xff;
int offtime = 0;
int dowhat = 0;
extern char *optarg;
extern int optind;
int fd;
struct x68k_alarminfo alarminfo;
while ((ch = getopt(argc, argv, "w:d:m:s:c:")) != -1)
switch (ch) {
case 'w': /* day of the week */
if ((week = strnum(optarg, 1)) < 0)
usage();
break;
case 'd': /* day of the month */
if ((day = strnum(optarg, 2)) < 0)
usage();
break;
case 'm': /* for X minits */
offtime = atoi(optarg);
break;
case 's': /* for X seconds */
offtime = atoi(optarg) / 60;
break;
case 'c': /* channel */
dowhat = atoi(optarg) + 0x30 - 1;
if (dowhat < 0x30 || dowhat > 0x3b)
usage();
break;
}
if (optind != argc - 1)
usage();
#ifdef DEBUG
printf("week: %x, day:%x, for:%d, hour:%x\n",
week, day, offtime, strnum(argv[optind], 5));
#endif
hour = strnum(argv[optind], 5);
if (hour < 0)
usage();
alarminfo.al_enable = 1;
alarminfo.al_ontime = (week << 24) | (day << 16) | hour;
alarminfo.al_dowhat = dowhat;
alarminfo.al_offtime = offtime * 60;
fd = open("/dev/pow1", O_WRONLY);
if (fd < 0)
myperror("Opening /dev/pow1", -1);
if (ioctl(fd, POWIOCSALARMINFO, &alarminfo) < 0)
myperror("powiocsalarminfo", fd);
close(fd);
}
static int
strnum(str, wid)
const char *str;
int wid;
{
int r;
if (strlen(str) != wid)
return -1;
if (str[0] >= '0' && str[0] <= '9')
r = str[0] - '0';
else
r = 0xf;
if (wid == 1)
return r;
r <<= 4;
if (str[1] >= '0' && str[1] <= '9')
r += str[1] - '0';
else
r += 0xf;
if (wid == 2)
return r;
if (str[2] != ':')
return -1;
r <<= 4;
if (str[3] >= '0' && str[3] <= '9')
r += str[3] - '0';
else
r += 0xf;
r <<= 4;
if (str[4] >= '0' && str[4] <= '9')
r += str[4] - '0';
else
r += 0xf;
return r;
}