diff --git a/sortix/Makefile b/sortix/Makefile index e0eefbae..0d8041f5 100644 --- a/sortix/Makefile +++ b/sortix/Makefile @@ -54,6 +54,7 @@ ifdef X86FAMILY $(CPU)/thread.o \ $(CPU)/scheduler.o \ $(CPU)/process.o \ + x86-family/cmos.o \ x86-family/time.o \ x86-family/msr.o \ x86-family/float.o \ diff --git a/sortix/kernel.cpp b/sortix/kernel.cpp index ea532db1..f00453d6 100644 --- a/sortix/kernel.cpp +++ b/sortix/kernel.cpp @@ -62,6 +62,7 @@ #include #include "kernelinfo.h" +#include "x86-family/cmos.h" #include "x86-family/gdt.h" #include "x86-family/float.h" #include "multiboot.h" @@ -380,6 +381,13 @@ static void BootThread(void* /*user*/) // We no longer need the initrd, so free its resources. InitRD::Delete(); + // + // Stage 5. Loading and Initializing Core Drivers. + // + + // Initialize the real-time clock. + CMOS::Init(); + // Get a descriptor for the /dev directory so we can populate it. if ( droot->mkdir(&ctx, "dev", 0775) != 0 && errno != EEXIST ) Panic("Unable to create RAM filesystem /dev directory."); @@ -387,10 +395,6 @@ static void BootThread(void* /*user*/) if ( !slashdev ) Panic("Unable to create descriptor for RAM filesystem /dev directory."); - // - // Stage 5. Loading and Initializing Core Drivers. - // - // Initialize the keyboard. Keyboard* keyboard = new PS2Keyboard(0x60, Interrupt::IRQ1); if ( !keyboard ) diff --git a/sortix/x86-family/cmos.cpp b/sortix/x86-family/cmos.cpp new file mode 100644 index 00000000..958e7b92 --- /dev/null +++ b/sortix/x86-family/cmos.cpp @@ -0,0 +1,109 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of Sortix. + + Sortix is free software: you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + Sortix is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License along with + Sortix. If not, see . + + x86-family/cmos.cpp + Provides access to CMOS and the real-time clock. + +*******************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace Sortix { +namespace CMOS { + +const uint16_t CMOS_ADDRESS_REG = 0x70; +const uint16_t CMOS_DATA_REG = 0x71; + +uint8_t ReadRTC(uint8_t reg) +{ + CPU::OutPortB(CMOS_ADDRESS_REG, reg); + return CPU::InPortB(CMOS_DATA_REG); +} + +bool IsRTCUpdateInProgress() +{ + return ReadRTC(0x0A) & 0x80; +} + +uint8_t DecodeBCD(uint8_t bcd) +{ + return bcd / 16 * 10 + bcd % 16; +} + +void Init() +{ + while ( !IsRTCUpdateInProgress() ); + while ( IsRTCUpdateInProgress() ); + uint8_t second = ReadRTC(0x00); + uint8_t minute = ReadRTC(0x02); + uint8_t hour = ReadRTC(0x04); + uint8_t day = ReadRTC(0x07); + uint8_t month = ReadRTC(0x08); + uint8_t year = ReadRTC(0x09); + uint8_t century = ReadRTC(0x32); + uint8_t reg_b = ReadRTC(0x0B); + + bool hour12 = !(reg_b & 0x02); + bool is_pm = hour12 && hour & 0x80; + if ( hour12 ) + hour &= 0x7F; + + if ( !(reg_b & 0x04) ) + { + second = DecodeBCD(second); + minute = DecodeBCD(minute); + hour = DecodeBCD(hour); + day = DecodeBCD(day); + month = DecodeBCD(month); + year = DecodeBCD(year); + century = DecodeBCD(century); + } + + if ( hour12 && is_pm ) + hour = (hour + 12) % 24; + + time_t full_year = century * 100 + year; + + struct tm tm; + memset(&tm, 0, sizeof(tm)); + tm.tm_sec = second; + tm.tm_min = minute; + tm.tm_hour = hour; + tm.tm_mday = day ; + tm.tm_mon = month - 1; + tm.tm_year = full_year - 1900; + time_t now = timegm(&tm); + + struct timespec current_time = timespec_make(now, 0); + Time::GetClock(CLOCK_REALTIME)->Set(¤t_time, NULL); +} + +} // namespace CMOS +} // namespace Sortix diff --git a/sortix/x86-family/cmos.h b/sortix/x86-family/cmos.h new file mode 100644 index 00000000..d36b4d1e --- /dev/null +++ b/sortix/x86-family/cmos.h @@ -0,0 +1,59 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of Sortix. + + Sortix is free software: you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + Sortix is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License along with + Sortix. If not, see . + + x86-family/cmos.h + Provides access to CMOS and the real-time clock. + +*******************************************************************************/ + +#ifndef SORTIX_X86_FAMILY_CMOS_H +#define SORTIX_X86_FAMILY_CMOS_H + +#include + +namespace Sortix { +namespace CMOS { + +uint8_t Read(uint8_t reg); +uint8_t Write(uint8_t reg, uint8_t val); + +struct cmos_tm +{ + uint8_t seconds; + uint8_t minutes; + uint8_t hours; + uint8_t weekday; /* Supposedly not reliably set in CMOS. */ + uint8_t day_of_month; + uint8_t month; + uint8_t year; + uint8_t century; +}; + +struct timespec DecodeTime(struct cmos_tm time); +struct cmos_tm EncodeTIme(struct timespec time); + +struct cmos_tm GetTime(); +void SetTime(struct cmos_tm time); + +void Init(); + +} // namespace CMOS +} // namespace Sortix + +#endif