*** /usr/src/linux-ipaq-arm/kernel/drivers/char/sa1100-rtc.c	Tue Nov  6 13:14:45 2001
--- sa1100-rtc.c	Tue Nov  6 13:18:59 2001
***************
*** 14,19 ****
--- 14,23 ----
   *	as published by the Free Software Foundation; either version
   *	2 of the License, or (at your option) any later version.
   *
+  *	1.01	2001-11-06	Nils Faerber <nils@@kernelconcepts.de>
+  *	- re-inserted old timemk() function from GLIBC as decodetime() since
+  *	  decodetime() failed on invalid dates (hung)
+  *
   *	1.00	2001-06-08	Nicolas Pitre <nico@cam.org>
   *	- added periodic timer capability using OSMR1
   *	- flag compatibility with other RTC chips
***************
*** 42,48 ****
  #include <asm/irq.h>
  #include <linux/rtc.h>
  
! #define	DRIVER_VERSION		"1.00"
  
  #define epoch			1970
  
--- 46,52 ----
  #include <asm/irq.h>
  #include <linux/rtc.h>
  
! #define	DRIVER_VERSION		"1.01"
  
  #define epoch			1970
  
***************
*** 66,120 ****
  
  extern spinlock_t rtc_lock;
  
! static const unsigned char days_in_mo[] =
! 	{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  
! #define is_leap(year) \
! 	((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
  
  /*
!  * Converts seconds since 1970-01-01 00:00:00 to Gregorian date.
   */
! 
! static void decodetime (unsigned long t, struct rtc_time *tval)
  {
! 	unsigned long days, month, year, rem;
  
  	days = t / 86400;
  	rem = t % 86400;
  	tval->tm_hour = rem / 3600;
  	rem %= 3600;
  	tval->tm_min = rem / 60;
  	tval->tm_sec = rem % 60;
! 	tval->tm_wday = (4 + days) % 7;
! 
! #define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
! 
! 	year = epoch;
! 	while (days >= (365 + is_leap(year))) {
! 		unsigned long yg = year + days / 365;
! 		days -= ((yg - year) * 365
! 				+ LEAPS_THRU_END_OF (yg - 1)
! 				- LEAPS_THRU_END_OF (year - 1));
! 		year = yg;
! 	}
! 	tval->tm_year = year - 1900;
! 	tval->tm_yday = days + 1;
! 
! 	month = 0;
! 	if (days >= 31) {
! 		days -= 31;
! 		month++;
! 		if (days >= (28 + is_leap(year))) {
! 			days -= (28 + is_leap(year));
! 			month++;
! 			while (days >= days_in_mo[month]) {
! 				days -= days_in_mo[month];
! 				month++;
! 			}
! 		}
  	}
! 	tval->tm_mon = month;
  	tval->tm_mday = days + 1;
  }
  
--- 70,135 ----
  
  extern spinlock_t rtc_lock;
  
! static const unsigned char days_in_mo[] = 
! {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  
! #define __isleap(year) \
!  	((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
  
  /*
!  * Convert seconds to time, from the GNU C Library
!  * (this code is ugly ;)
   */
! void decodetime (unsigned long t, struct rtc_time *tval)
  {
! long int days, rem, y;
! const unsigned short int *ip;
! unsigned int wday;
! unsigned int yday;
! const unsigned short int __mon_yday[2][13] =
! 	{ /* Normal years.  */
! 	  { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
! 	  /* Leap years.  */
! 	  { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
! 	};
  
  	days = t / 86400;
  	rem = t % 86400;
+ 	while (rem < 0)
+ 	{
+ 		rem += 86400;
+ 		--days;
+ 	}
+ 	while (rem >= 86400)
+ 	{
+ 		rem -= 86400;
+ 		++days;
+ 	}
  	tval->tm_hour = rem / 3600;
  	rem %= 3600;
  	tval->tm_min = rem / 60;
  	tval->tm_sec = rem % 60;
! 	wday = (4 + days) % 7;
! 	if (wday < 0)   
! 		wday += 7;
! 	y = 1970;
! #define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
! #define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
! 	while (days < 0 || days >= (__isleap (y) ? 366 : 365))
! 	{
! 		long int yg = y + days / 365 - (days % 365 < 0);
! 		days -= ((yg - y) * 365
! 			+ LEAPS_THRU_END_OF (yg - 1)
! 			- LEAPS_THRU_END_OF (y - 1));
! 		y = yg;
  	}
! 	tval->tm_year = y - 1900;
! 	yday = days;
! 	ip = __mon_yday[__isleap(y)];
! 	for (y = 11; days < (long int) ip[y]; --y)
! 		continue;
! 	days -= ip[y];   
! 	tval->tm_mon = y;
  	tval->tm_mday = days + 1;
  }
  
***************
*** 336,342 ****
  		tm.tm_year += 1900;
  		if (tm.tm_year < epoch || (unsigned)tm.tm_mon >= 12 ||
  		    tm.tm_mday < 1 || tm.tm_mday > (days_in_mo[tm.tm_mon] +
! 				(tm.tm_mon == 1 && is_leap(tm.tm_year))) ||
  		    (unsigned)tm.tm_hour >= 24 ||
  		    (unsigned)tm.tm_min >= 60 ||
  		    (unsigned)tm.tm_sec >= 60)
--- 351,357 ----
  		tm.tm_year += 1900;
  		if (tm.tm_year < epoch || (unsigned)tm.tm_mon >= 12 ||
  		    tm.tm_mday < 1 || tm.tm_mday > (days_in_mo[tm.tm_mon] +
! 				(tm.tm_mon == 1 && __isleap(tm.tm_year))) ||
  		    (unsigned)tm.tm_hour >= 24 ||
  		    (unsigned)tm.tm_min >= 60 ||
  		    (unsigned)tm.tm_sec >= 60)
