/*

  Set the MC146818 CMOS clock to local time from the current software clock.

  I'm *sure* something like this exists already but I can't find it.

  Build with:
  gcc -O -o setclock setclock.c

  N.B. the -O is necessary so that outb_p will be expanded in-line, it doesn't
  really exist in the libraries so you'll get an undefined external otherwise.

  By John Wilson <wilson@dbit.com>.

  01/16/2000	JMBW	Created.

*/

#include <asm/io.h>
#include <time.h>
#include <unistd.h>

/* write a BCD value to an RTC register */
/* called with interrupts off so that nothing will write port 70h and change */
/* the register selection while we're doing this -- could get burned on SMP! */
wcmos(int reg,int val)
{
	outb_p(reg,0x70);		/* select reg # */
	outb_p(((val/10)<<4)|(val%10),0x71);  /* write value in BCD */
}

main()
{
	time_t now;
	struct tm *t;

	/* get access to (all) I/O ports and the CLI/STI instructions */
	/* (must be root) */
	if(iopl(3)<0) {
		perror("iopl");
		exit(1);
	}

	tzset();			/* probably not really needed */

	/* get current time */
	if((now=time(NULL))==(time_t)-1) {
		perror("time");
		exit(1);
	}

	/* split out individual fields according to time zone */
	t=localtime(&now);

	/* write them all out */
	__asm__ __volatile__ ("cli");	/* don't interrupt RTC use */
	wcmos(0,t->tm_sec);		/* write time out */
	wcmos(2,t->tm_min);
	wcmos(4,t->tm_hour);
	wcmos(6,t->tm_wday+1);
	wcmos(7,t->tm_mday);
	wcmos(8,t->tm_mon+1);
	wcmos(9,t->tm_year%100);	/* set year within century */
	wcmos(0x32,t->tm_year/100+19);	/* set epoch */
	__asm__ __volatile__ ("sti");	/* thanks, carry on */
}

