time.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 1,282 行 · 第 1/3 页

C
1,282
字号
	static long last_rtc_update;	/* Determine when to update the Mostek clock. */	if ((time_status & STA_UNSYNC) == 0 &&	    xtime.tv_sec > last_rtc_update + 660 &&	    (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&	    (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {		if (set_rtc_mmss(xtime.tv_sec) == 0)			last_rtc_update = xtime.tv_sec;		else			last_rtc_update = xtime.tv_sec - 600;			/* do it again in 60 s */	}}void sparc64_do_profile(struct pt_regs *regs){	unsigned long pc;	profile_hook(regs);	if (user_mode(regs))		return;	if (!prof_buffer)		return;	pc = regs->tpc;	pc -= (unsigned long) _stext;	pc >>= prof_shift;	if(pc >= prof_len)		pc = prof_len - 1;	atomic_inc((atomic_t *)&prof_buffer[pc]);}static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs){	unsigned long ticks, pstate;	write_seqlock(&xtime_lock);	do {#ifndef CONFIG_SMP		sparc64_do_profile(regs);#endif		do_timer(regs);		/* Guarantee that the following sequences execute		 * uninterrupted.		 */		__asm__ __volatile__("rdpr	%%pstate, %0\n\t"				     "wrpr	%0, %1, %%pstate"				     : "=r" (pstate)				     : "i" (PSTATE_IE));		timer_tick_compare = tick_ops->add_compare(timer_tick_offset);		ticks = tick_ops->get_tick();		/* Restore PSTATE_IE. */		__asm__ __volatile__("wrpr	%0, 0x0, %%pstate"				     : /* no outputs */				     : "r" (pstate));	} while (time_after_eq(ticks, timer_tick_compare));	timer_check_rtc();	write_sequnlock(&xtime_lock);	return IRQ_HANDLED;}#ifdef CONFIG_SMPvoid timer_tick_interrupt(struct pt_regs *regs){	write_seqlock(&xtime_lock);	do_timer(regs);	/*	 * Only keep timer_tick_offset uptodate, but don't set TICK_CMPR.	 */	timer_tick_compare = tick_ops->get_compare() + timer_tick_offset;	timer_check_rtc();	write_sequnlock(&xtime_lock);}#endif/* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */static void __init kick_start_clock(void){	unsigned long regs = mstk48t02_regs;	u8 sec, tmp;	int i, count;	prom_printf("CLOCK: Clock was stopped. Kick start ");	spin_lock_irq(&mostek_lock);	/* Turn on the kick start bit to start the oscillator. */	tmp = mostek_read(regs + MOSTEK_CREG);	tmp |= MSTK_CREG_WRITE;	mostek_write(regs + MOSTEK_CREG, tmp);	tmp = mostek_read(regs + MOSTEK_SEC);	tmp &= ~MSTK_STOP;	mostek_write(regs + MOSTEK_SEC, tmp);	tmp = mostek_read(regs + MOSTEK_HOUR);	tmp |= MSTK_KICK_START;	mostek_write(regs + MOSTEK_HOUR, tmp);	tmp = mostek_read(regs + MOSTEK_CREG);	tmp &= ~MSTK_CREG_WRITE;	mostek_write(regs + MOSTEK_CREG, tmp);	spin_unlock_irq(&mostek_lock);	/* Delay to allow the clock oscillator to start. */	sec = MSTK_REG_SEC(regs);	for (i = 0; i < 3; i++) {		while (sec == MSTK_REG_SEC(regs))			for (count = 0; count < 100000; count++)				/* nothing */ ;		prom_printf(".");		sec = MSTK_REG_SEC(regs);	}	prom_printf("\n");	spin_lock_irq(&mostek_lock);	/* Turn off kick start and set a "valid" time and date. */	tmp = mostek_read(regs + MOSTEK_CREG);	tmp |= MSTK_CREG_WRITE;	mostek_write(regs + MOSTEK_CREG, tmp);	tmp = mostek_read(regs + MOSTEK_HOUR);	tmp &= ~MSTK_KICK_START;	mostek_write(regs + MOSTEK_HOUR, tmp);	MSTK_SET_REG_SEC(regs,0);	MSTK_SET_REG_MIN(regs,0);	MSTK_SET_REG_HOUR(regs,0);	MSTK_SET_REG_DOW(regs,5);	MSTK_SET_REG_DOM(regs,1);	MSTK_SET_REG_MONTH(regs,8);	MSTK_SET_REG_YEAR(regs,1996 - MSTK_YEAR_ZERO);	tmp = mostek_read(regs + MOSTEK_CREG);	tmp &= ~MSTK_CREG_WRITE;	mostek_write(regs + MOSTEK_CREG, tmp);	spin_unlock_irq(&mostek_lock);	/* Ensure the kick start bit is off. If it isn't, turn it off. */	while (mostek_read(regs + MOSTEK_HOUR) & MSTK_KICK_START) {		prom_printf("CLOCK: Kick start still on!\n");		spin_lock_irq(&mostek_lock);		tmp = mostek_read(regs + MOSTEK_CREG);		tmp |= MSTK_CREG_WRITE;		mostek_write(regs + MOSTEK_CREG, tmp);		tmp = mostek_read(regs + MOSTEK_HOUR);		tmp &= ~MSTK_KICK_START;		mostek_write(regs + MOSTEK_HOUR, tmp);		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? */}/* 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_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);	set_normalized_timespec(&wall_to_monotonic, 	                        -xtime.tv_sec, -xtime.tv_nsec);	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 sparc_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_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);		set_normalized_timespec(&wall_to_monotonic,		                        -xtime.tv_sec, -xtime.tv_nsec);		return;	}	local_irq_save(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 sparc_isa_device *isadev;try_isa_clock:			for_each_isadev(isadev, isa_br)				if (isadev->prom_node == node)					break;			if (isadev == NULL) {

⌨️ 快捷键说明

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