do not edit — generated by btf.
git.druid.rocksindexdruid520kaboomsrc/drivers/rtc.nsc

src/drivers/rtc.nsc


/*
 * cmos real-time clock, port 0x70 (index)/0x71 (data) -- the same
 * pair every pc-compatible has had since the original at. polling
 * only, no periodic-interrupt mode (register 0x0b's bit 6, unused
 * here) -- a program that wants the time reads it once, same as
 * every other "read a value" syscall in this kernel.
 *
 * one real, documented race: reading all 6 fields isn't atomic, so a
 * read that straddles the clock actually ticking over (e.g. reading
 * hour=23 minute=59 second=59, then the clock ticks to the next
 * minute, then this reads day/month/year -- still showing yesterday)
 * can come back very slightly wrong, extremely rarely. checking
 * "update in progress" (status register a, bit 7) before reading
 * avoids reading MID-update, which is the real failure mode (torn,
 * nonsensical values, not just off-by-a-few-seconds); the remaining
 * tick-over race is a known, accepted imprecision, not worth a
 * read-twice-and-compare loop for what's still just a debug-grade
 * clock with no periodic sync to anything real.
 */
 
void outb(u16 port, u8 val);
u8 inb(u16 port);
 
u8
rtc_read_reg(u8 reg)
{
	outb((u16)0x70, reg);
	return inb((u16)0x71);
}
 
i32
rtc_update_in_progress(void)
{
	if((rtc_read_reg((u8)0x0a) & (u8)0x80) != (u8)0)
	{
		return 1;
	}
	return 0;
}
 
u64
rtc_bcd_to_bin(u8 v)
{
	return (u64)(v & (u8)0x0f) + (u64)((v >> (u8)4) & (u8)0x0f) * (u64)10;
}
 
/* fills buf (room for 6 u64s = 48 bytes) with second, minute, hour,
 * day, month, year (full, e.g. 2026 -- assumes the 2000s, same as
 * every other from-scratch rtc reader that doesn't bother with the
 * century register). buf is word-aligned by construction (a fresh
 * caller-side u64[6] or equivalent), so these are plain aligned
 * 8-byte stores, no packed-word technique needed. */
global void
rtc_read_datetime(ptr buf)
{
	u8 sec;
	u8 min;
	u8 hour;
	u8 day;
	u8 month;
	u8 year;
	u8 status_b;
	i32 binary_mode;
 
	while(rtc_update_in_progress() == 1)
	{
	}
 
	sec = rtc_read_reg((u8)0x00);
	min = rtc_read_reg((u8)0x02);
	hour = rtc_read_reg((u8)0x04);
	day = rtc_read_reg((u8)0x07);
	month = rtc_read_reg((u8)0x08);
	year = rtc_read_reg((u8)0x09);
	status_b = rtc_read_reg((u8)0x0b);
 
	binary_mode = 0;
	if((status_b & (u8)0x04) != (u8)0)
	{
		binary_mode = 1;
	}
 
	if(binary_mode == 1)
	{
		*buf = (i64)(u64)sec;
		*(buf + 8) = (i64)(u64)min;
		*(buf + 16) = (i64)(u64)hour;
		*(buf + 24) = (i64)(u64)day;
		*(buf + 32) = (i64)(u64)month;
		*(buf + 40) = (i64)((u64)2000 + (u64)year);
	}
	else
	{
		*buf = (i64)rtc_bcd_to_bin(sec);
		*(buf + 8) = (i64)rtc_bcd_to_bin(min);
		*(buf + 16) = (i64)rtc_bcd_to_bin(hour);
		*(buf + 24) = (i64)rtc_bcd_to_bin(day);
		*(buf + 32) = (i64)rtc_bcd_to_bin(month);
		*(buf + 40) = (i64)((u64)2000 + rtc_bcd_to_bin(year));
	}
}
powered by btf.