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

📄 cmos.c

📁 nucleus_arm.rar
💻 C
字号:
/*
* CMOS Date/Time functions v0.2	*
* v0.1: JensMoppel				*
*       - basic routines		*
* v0.2: TDS (30.03.2004)		*
*       - bcd/bin check			*
*       - 12/24 hours check		*
* v0.3: Doug Gale (05.09.2004)						*
*		- Fixed wait for RTC update					*
*		- Disables interrupts during access			*
*		- Added function for getting time & date	*
*/

#include <support.h>
#include <stdio.h>
#include <drivers/cmos.h>

// If a time update never occurs, stop trying to wait
static int cmos_bad_rtc;

// Wait until a CMOS update has just completed
// WARNING: assumes interrupts are already disabled
static void cmos_wait_rtc(void)
{
	int longwait;

	if (cmos_bad_rtc)
		return;

	longwait = 2000;	// Timeout after 2 seconds

	// Wait for an update to start
	do {
		outb(0x70, 0x0A);
		if (--longwait == 0) {
			cmos_bad_rtc = 1;
			return;		// Abandon
		}
	} while ((inb(0x71) & 0x80) == 0);

	// Wait for the update to stop
		do {
		outb(0x70, 0x0A);
		if (--longwait == 0) {
			cmos_bad_rtc = 1;
			return;		// Abandon
		}
		} while ((inb(0x71) & 0x80) != 0);
}

// Read a CMOS register. Does not care if RTC update is in progress.
// Don't use this to read the clock, use cmos_get_time
int cmos_read_register(int address)
{
	int retval;
	int ints_were_enabled = interrupts_disable();

	outb(0x70, address);
	retval = inb(0x71);

	if (ints_were_enabled)
		interrupts_enable();

	return retval;
}

#define BCD_TO_BIN(val) (((val)&0x0f) + ((val)>>4)*10)
#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)

// Read CMOS register, and convert from BCD to binary if necessary
static int cmos_read_register_special(int address)
{
	int tmp;
	
	tmp = cmos_read_register(address);
	if (!(cmos_read_register(CMOS_STATUS) & 0x04))
		return BCD_TO_BIN(tmp);
    return tmp;
}

// Properly get the current wallclock time and date
struct datetime cmos_get_time(void)
{
	struct datetime datetime1;
	unsigned char amp, pm;
	
	int ints_were_enabled = interrupts_disable();

	cmos_wait_rtc();

	datetime1.second = cmos_read_register_special(CMOS_SECOND);
	datetime1.alarm_second = cmos_read_register_special(CMOS_ALARMSECOND);
	datetime1.minute = cmos_read_register_special(CMOS_MINUTE);
	datetime1.alarm_minute = cmos_read_register_special(CMOS_ALARMMINUTE);
	amp = cmos_read_register_special(CMOS_HOUR);
	pm = amp & 0x80;
	amp &= 0x7F;
	datetime1.alarm_hour = cmos_read_register_special(CMOS_ALARMHOUR);
	datetime1.day_in_week = cmos_read_register_special(CMOS_DAYINWEEK);
	datetime1.day = cmos_read_register_special(CMOS_DAY);
	datetime1.month = cmos_read_register_special(CMOS_MONTH);
	datetime1.year = cmos_read_register_special(CMOS_YEAR);
	datetime1.century = cmos_read_register_special(CMOS_CENTURY);

	if (!(cmos_read_register(CMOS_STATUS) & 0x02))	// 12 hour (am/pm) mode
	{
		if (pm == 0x80)
		{
			datetime1.hour = (amp == 12) ? 12 : (amp + 12);
		}
		else
		{
			datetime1.hour = (amp == 12) ? 0 : amp;
		}
	}
	else
		datetime1.hour = amp;
	
	if (ints_were_enabled)
		interrupts_enable();

	return datetime1;
}

⌨️ 快捷键说明

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