⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 time.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		tmp = mostek_read(regs + MOSTEK_CREG);		tmp &= ~MSTK_CREG_WRITE;		mostek_write(regs + MOSTEK_CREG, tmp);		spin_unlock_irq(&mostek_lock);	}	prom_printf("CLOCK: Kick start procedure successful.\n");}/* Return nonzero if the clock chip battery is low. */static int __init has_low_battery(void){	unsigned long regs = mstk48t02_regs;	u8 data1, data2;	spin_lock_irq(&mostek_lock);	data1 = mostek_read(regs + MOSTEK_EEPROM);	/* Read some data. */	mostek_write(regs + MOSTEK_EEPROM, ~data1);	/* Write back the complement. */	data2 = mostek_read(regs + MOSTEK_EEPROM);	/* Read back the complement. */	mostek_write(regs + MOSTEK_EEPROM, data1);	/* Restore original value. */	spin_unlock_irq(&mostek_lock);	return (data1 == data2);	/* Was the write blocked? */}#ifndef BCD_TO_BIN#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)#endif#ifndef BIN_TO_BCD#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)#endif/* Probe for the real time clock chip. */static void __init set_system_time(void){	unsigned int year, mon, day, hour, min, sec;	unsigned long mregs = mstk48t02_regs;#ifdef CONFIG_PCI	unsigned long dregs = ds1287_regs;#else	unsigned long dregs = 0UL;#endif	u8 tmp;	if (!mregs && !dregs) {		prom_printf("Something wrong, clock regs not mapped yet.\n");		prom_halt();	}			if (mregs) {		spin_lock_irq(&mostek_lock);		/* Traditional Mostek chip. */		tmp = mostek_read(mregs + MOSTEK_CREG);		tmp |= MSTK_CREG_READ;		mostek_write(mregs + MOSTEK_CREG, tmp);		sec = MSTK_REG_SEC(mregs);		min = MSTK_REG_MIN(mregs);		hour = MSTK_REG_HOUR(mregs);		day = MSTK_REG_DOM(mregs);		mon = MSTK_REG_MONTH(mregs);		year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );	} else {		int i;		/* Dallas 12887 RTC chip. */		/* Stolen from arch/i386/kernel/time.c, see there for		 * credits and descriptive comments.		 */		for (i = 0; i < 1000000; i++) {			if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)				break;			udelay(10);		}		for (i = 0; i < 1000000; i++) {			if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))				break;			udelay(10);		}		do {			sec  = CMOS_READ(RTC_SECONDS);			min  = CMOS_READ(RTC_MINUTES);			hour = CMOS_READ(RTC_HOURS);			day  = CMOS_READ(RTC_DAY_OF_MONTH);			mon  = CMOS_READ(RTC_MONTH);			year = CMOS_READ(RTC_YEAR);		} while (sec != CMOS_READ(RTC_SECONDS));		if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {			BCD_TO_BIN(sec);			BCD_TO_BIN(min);			BCD_TO_BIN(hour);			BCD_TO_BIN(day);			BCD_TO_BIN(mon);			BCD_TO_BIN(year);		}		if ((year += 1900) < 1970)			year += 100;	}	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);	xtime.tv_usec = 0;	if (mregs) {		tmp = mostek_read(mregs + MOSTEK_CREG);		tmp &= ~MSTK_CREG_READ;		mostek_write(mregs + MOSTEK_CREG, tmp);		spin_unlock_irq(&mostek_lock);	}}void __init clock_probe(void){	struct linux_prom_registers clk_reg[2];	char model[128];	int node, busnd = -1, err;	unsigned long flags;	struct linux_central *cbus;#ifdef CONFIG_PCI	struct linux_ebus *ebus = NULL;	struct isa_bridge *isa_br = NULL;#endif	static int invoked;	if (invoked)		return;	invoked = 1;	if (this_is_starfire) {		/* davem suggests we keep this within the 4M locked kernel image */		static char obp_gettod[256];		static u32 unix_tod;		sprintf(obp_gettod, "h# %08x unix-gettod",			(unsigned int) (long) &unix_tod);		prom_feval(obp_gettod);		xtime.tv_sec = unix_tod;		xtime.tv_usec = 0;		return;	}	__save_and_cli(flags);	cbus = central_bus;	if (cbus != NULL)		busnd = central_bus->child->prom_node;	/* Check FHC Central then EBUSs then ISA bridges then SBUSs.	 * That way we handle the presence of multiple properly.	 *	 * As a special case, machines with Central must provide the	 * timer chip there.	 */#ifdef CONFIG_PCI	if (ebus_chain != NULL) {		ebus = ebus_chain;		if (busnd == -1)			busnd = ebus->prom_node;	}	if (isa_chain != NULL) {		isa_br = isa_chain;		if (busnd == -1)			busnd = isa_br->prom_node;	}#endif	if (sbus_root != NULL && busnd == -1)		busnd = sbus_root->prom_node;	if (busnd == -1) {		prom_printf("clock_probe: problem, cannot find bus to search.\n");		prom_halt();	}	node = prom_getchild(busnd);	while (1) {		if (!node)			model[0] = 0;		else			prom_getstring(node, "model", model, sizeof(model));		if (strcmp(model, "mk48t02") &&		    strcmp(model, "mk48t08") &&		    strcmp(model, "mk48t59") &&		    strcmp(model, "m5819") &&		    strcmp(model, "m5819p") &&		    strcmp(model, "ds1287")) {			if (cbus != NULL) {				prom_printf("clock_probe: Central bus lacks timer chip.\n");				prom_halt();			}		   	if (node != 0)				node = prom_getsibling(node);#ifdef CONFIG_PCI			while ((node == 0) && ebus != NULL) {				ebus = ebus->next;				if (ebus != NULL) {					busnd = ebus->prom_node;					node = prom_getchild(busnd);				}			}			while ((node == 0) && isa_br != NULL) {				isa_br = isa_br->next;				if (isa_br != NULL) {					busnd = isa_br->prom_node;					node = prom_getchild(busnd);				}			}#endif			if (node == 0) {				prom_printf("clock_probe: Cannot find timer chip\n");				prom_halt();			}			continue;		}		err = prom_getproperty(node, "reg", (char *)clk_reg,				       sizeof(clk_reg));		if(err == -1) {			prom_printf("clock_probe: Cannot get Mostek reg property\n");			prom_halt();		}		if (cbus != NULL) {			apply_fhc_ranges(central_bus->child, clk_reg, 1);			apply_central_ranges(central_bus, clk_reg, 1);		}#ifdef CONFIG_PCI		else if (ebus != NULL) {			struct linux_ebus_device *edev;			for_each_ebusdev(edev, ebus)				if (edev->prom_node == node)					break;			if (edev == NULL) {				if (isa_chain != NULL)					goto try_isa_clock;				prom_printf("%s: Mostek not probed by EBUS\n",					    __FUNCTION__);				prom_halt();			}			if (!strcmp(model, "ds1287") ||			    !strcmp(model, "m5819") ||			    !strcmp(model, "m5819p")) {				ds1287_regs = edev->resource[0].start;			} else {				mstk48t59_regs = edev->resource[0].start;				mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;			}			break;		}		else if (isa_br != NULL) {			struct isa_device *isadev;try_isa_clock:			for_each_isadev(isadev, isa_br)				if (isadev->prom_node == node)					break;			if (isadev == NULL) {				prom_printf("%s: Mostek not probed by ISA\n");				prom_halt();			}			if (!strcmp(model, "ds1287") ||			    !strcmp(model, "m5819") ||			    !strcmp(model, "m5819p")) {				ds1287_regs = isadev->resource.start;			} else {				mstk48t59_regs = isadev->resource.start;				mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;			}			break;		}#endif		else {			if (sbus_root->num_sbus_ranges) {				int nranges = sbus_root->num_sbus_ranges;				int rngc;				for (rngc = 0; rngc < nranges; rngc++)					if (clk_reg[0].which_io ==					    sbus_root->sbus_ranges[rngc].ot_child_space)						break;				if (rngc == nranges) {					prom_printf("clock_probe: Cannot find ranges for "						    "clock regs.\n");					prom_halt();				}				clk_reg[0].which_io =					sbus_root->sbus_ranges[rngc].ot_parent_space;				clk_reg[0].phys_addr +=					sbus_root->sbus_ranges[rngc].ot_parent_base;			}		}		if(model[5] == '0' && model[6] == '2') {			mstk48t02_regs = (((u64)clk_reg[0].phys_addr) |					  (((u64)clk_reg[0].which_io)<<32UL));		} else if(model[5] == '0' && model[6] == '8') {			mstk48t08_regs = (((u64)clk_reg[0].phys_addr) |					  (((u64)clk_reg[0].which_io)<<32UL));			mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02;		} else {			mstk48t59_regs = (((u64)clk_reg[0].phys_addr) |					  (((u64)clk_reg[0].which_io)<<32UL));			mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;		}		break;	}	if (mstk48t02_regs != 0UL) {		/* Report a low battery voltage condition. */		if (has_low_battery())			prom_printf("NVRAM: Low battery voltage!\n");		/* Kick start the clock if it is completely stopped. */		if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP)			kick_start_clock();	}	set_system_time();		__restore_flags(flags);}/* This is gets the master TICK_INT timer going. */static unsigned long sparc64_init_timers(void (*cfunc)(int, void *, struct pt_regs *)){	unsigned long pstate, clock;	int node, err;#ifdef CONFIG_SMP	extern void smp_tick_init(void);#endif	if (tlb_type == spitfire) {		unsigned long ver, manuf, impl;		__asm__ __volatile__ ("rdpr %%ver, %0"				      : "=&r" (ver));		manuf = ((ver >> 48) & 0xffff);		impl = ((ver >> 32) & 0xffff);		if (manuf == 0x17 && impl == 0x13) {			/* Hummingbird, aka Ultra-IIe */			tick_ops = &hbtick_operations;			node = prom_root_node;			clock = prom_getint(node, "stick-frequency");		} else {			tick_ops = &tick_operations;			node = linux_cpus[0].prom_node;			clock = prom_getint(node, "clock-frequency");		}	} else {		tick_ops = &stick_operations;		node = prom_root_node;		clock = prom_getint(node, "stick-frequency");	}	timer_tick_offset = clock / HZ;#ifdef CONFIG_SMP	smp_tick_init();#endif	/* Register IRQ handler. */	err = request_irq(build_irq(0, 0, 0UL, 0UL), cfunc, SA_STATIC_ALLOC,			  "timer", NULL);	if(err) {		prom_printf("Serious problem, cannot register TICK_INT\n");		prom_halt();	}	/* Guarentee that the following sequences execute	 * uninterrupted.	 */	__asm__ __volatile__("rdpr	%%pstate, %0\n\t"			     "wrpr	%0, %1, %%pstate"			     : "=r" (pstate)			     : "i" (PSTATE_IE));	tick_ops->init_tick(timer_tick_offset);	/* Restore PSTATE_IE. */	__asm__ __volatile__("wrpr	%0, 0x0, %%pstate"			     : /* no outputs */			     : "r" (pstate));	sti();	return clock;}/* The quotient formula is taken from the IA64 port. */void __init time_init(void){	unsigned long clock = sparc64_init_timers(timer_interrupt);	timer_ticks_per_usec_quotient =		(((1000000UL << 30) +		  (clock / 2)) / clock);}static __inline__ unsigned long do_gettimeoffset(void){	unsigned long ticks = tick_ops->get_tick();	ticks += timer_tick_offset;	ticks -= timer_tick_compare;	return (ticks * timer_ticks_per_usec_quotient) >> 30UL;}void do_settimeofday(struct timeval *tv){	if (this_is_starfire)		return;	write_lock_irq(&xtime_lock);	tv->tv_usec -= do_gettimeoffset();	tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ);	while (tv->tv_usec < 0) {		tv->tv_usec += 1000000;		tv->tv_sec--;	}	xtime = *tv;	time_adjust = 0;		/* stop active adjtime() */	time_status |= STA_UNSYNC;	time_maxerror = NTP_PHASE_LIMIT;	time_esterror = NTP_PHASE_LIMIT;	write_unlock_irq(&xtime_lock);}void do_gettimeofday(struct timeval *tv){	unsigned long flags;	unsigned long usec, sec;	read_lock_irqsave(&xtime_lock, flags);	usec = do_gettimeoffset();	{		unsigned long lost = jiffies - wall_jiffies;		if (lost)			usec += lost * (1000000 / HZ);	}	sec = xtime.tv_sec;	usec += xtime.tv_usec;	read_unlock_irqrestore(&xtime_lock, flags);	while (usec >= 1000000) {		usec -= 1000000;		sec++;	}	tv->tv_sec = sec;	tv->tv_usec = usec;}static int set_rtc_mmss(unsigned long nowtime){	int real_seconds, real_minutes, chip_minutes;	unsigned long mregs = mstk48t02_regs;#ifdef CONFIG_PCI	unsigned long dregs = ds1287_regs;#else	unsigned long dregs = 0UL;#endif	unsigned long flags;	u8 tmp;	/* 	 * Not having a register set can lead to trouble.	 * Also starfire doesn't have a tod clock.	 */	if (!mregs && !dregs) 		return -1;	if (mregs) {		spin_lock_irqsave(&mostek_lock, flags);		/* Read the current RTC minutes. */		tmp = mostek_read(mregs + MOSTEK_CREG);		tmp |= MSTK_CREG_READ;		mostek_write(mregs + MOSTEK_CREG, tmp);		chip_minutes = MSTK_REG_MIN(mregs);		tmp = mostek_read(mregs + MOSTEK_CREG);		tmp &= ~MSTK_CREG_READ;		mostek_write(mregs + MOSTEK_CREG, tmp);		/*		 * since we're only adjusting minutes and seconds,		 * don't interfere with hour overflow. This avoids		 * messing with unknown time zones but requires your		 * RTC not to be off by more than 15 minutes		 */		real_seconds = nowtime % 60;		real_minutes = nowtime / 60;		if (((abs(real_minutes - chip_minutes) + 15)/30) & 1)			real_minutes += 30;	/* correct for half hour time zone */		real_minutes %= 60;		if (abs(real_minutes - chip_minutes) < 30) {			tmp = mostek_read(mregs + MOSTEK_CREG);			tmp |= MSTK_CREG_WRITE;			mostek_write(mregs + MOSTEK_CREG, tmp);			MSTK_SET_REG_SEC(mregs,real_seconds);			MSTK_SET_REG_MIN(mregs,real_minutes);			tmp = mostek_read(mregs + MOSTEK_CREG);			tmp &= ~MSTK_CREG_WRITE;			mostek_write(mregs + MOSTEK_CREG, tmp);			spin_unlock_irqrestore(&mostek_lock, flags);			return 0;		} else {			spin_unlock_irqrestore(&mostek_lock, flags);			return -1;		}	} else {		int retval = 0;		unsigned char save_control, save_freq_select;		/* Stolen from arch/i386/kernel/time.c, see there for		 * credits and descriptive comments.		 */		spin_lock_irqsave(&rtc_lock, flags);		save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */		CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);		save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */		CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);		chip_minutes = CMOS_READ(RTC_MINUTES);		if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)			BCD_TO_BIN(chip_minutes);		real_seconds = nowtime % 60;		real_minutes = nowtime / 60;		if (((abs(real_minutes - chip_minutes) + 15)/30) & 1)			real_minutes += 30;		real_minutes %= 60;		if (abs(real_minutes - chip_minutes) < 30) {			if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {				BIN_TO_BCD(real_seconds);				BIN_TO_BCD(real_minutes);			}			CMOS_WRITE(real_seconds,RTC_SECONDS);			CMOS_WRITE(real_minutes,RTC_MINUTES);		} else {			printk(KERN_WARNING			       "set_rtc_mmss: can't update from %d to %d\n",			       chip_minutes, real_minutes);			retval = -1;		}		CMOS_WRITE(save_control, RTC_CONTROL);		CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);		spin_unlock_irqrestore(&rtc_lock, flags);		return retval;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -