//----------------------------------------------------------------------------// // GNU GPL OS/K // // // // Desc: Interrupt related functions // // // // // // Copyright © 2018-2019 The OS/K Team // // // // This file is part of OS/K. // // // // OS/K 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 // // any later version. // // // // OS/K 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 OS/K. If not, see . // //----------------------------------------------------------------------------// #include #include #include extern void RtcIsr(void); ulong IoRtcTicks = 0; Time_t IoRtcTime; char* WeekDays[7] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}; void IoSetupRtc(void) { IdtRegisterIrq(RtcIsr, 0x28, 0x8E); } void IoGetTimeFromRtc(void) { char time24or12Mode; Time_t lastTime; char updateInProgress = 1; while(updateInProgress) { // wait while the RTC updates its value IoWriteByteOnPort(0x70, 0x0A); updateInProgress = (IoReadByteFromPort(0x71) & 0x80); } IoWriteByteOnPort(0x70, 0x0); IoRtcTime.sec = IoReadByteFromPort(0x71); IoWriteByteOnPort(0x70, 0x02); IoRtcTime.min = IoReadByteFromPort(0x71); IoWriteByteOnPort(0x70, 0x04); IoRtcTime.hour = IoReadByteFromPort(0x71); IoWriteByteOnPort(0x70, 0x06); IoRtcTime.weekday = IoReadByteFromPort(0x71); IoWriteByteOnPort(0x70, 0x07); IoRtcTime.day = IoReadByteFromPort(0x71); IoWriteByteOnPort(0x70, 0x08); IoRtcTime.month = IoReadByteFromPort(0x71); IoWriteByteOnPort(0x70, 0x09); IoRtcTime.year = IoReadByteFromPort(0x71); IoWriteByteOnPort(0x70, 0x32); IoRtcTime.century = IoReadByteFromPort(0x71); // Now while we don't get the same value, read the registers (ensure data are valid) do { lastTime.sec = IoRtcTime.sec; lastTime.min = IoRtcTime.min; lastTime.hour = IoRtcTime.hour; lastTime.weekday = IoRtcTime.weekday; lastTime.day = IoRtcTime.day; lastTime.month = IoRtcTime.month; lastTime.year = IoRtcTime.year; lastTime.century = IoRtcTime.century; while(updateInProgress) { // wait while the RTC updates its value IoWriteByteOnPort(0x70, 0x0A); updateInProgress = (IoReadByteFromPort(0x71) & 0x80); } IoWriteByteOnPort(0x70, 0x0); IoRtcTime.sec = IoReadByteFromPort(0x71); IoWriteByteOnPort(0x70, 0x02); IoRtcTime.min = IoReadByteFromPort(0x71); IoWriteByteOnPort(0x70, 0x04); IoRtcTime.hour = IoReadByteFromPort(0x71); IoWriteByteOnPort(0x70, 0x06); IoRtcTime.weekday = IoReadByteFromPort(0x71); IoWriteByteOnPort(0x70, 0x07); IoRtcTime.day = IoReadByteFromPort(0x71); IoWriteByteOnPort(0x70, 0x08); IoRtcTime.month = IoReadByteFromPort(0x71); IoWriteByteOnPort(0x70, 0x09); IoRtcTime.year = IoReadByteFromPort(0x71); IoWriteByteOnPort(0x70, 0x32); IoRtcTime.century = IoReadByteFromPort(0x71); } while ( (lastTime.sec != IoRtcTime.sec) || (lastTime.min != IoRtcTime.min) || (lastTime.hour != IoRtcTime.hour) || (lastTime.weekday != IoRtcTime.weekday) || (lastTime.day != IoRtcTime.day) || (lastTime.month != IoRtcTime.month) || (lastTime.year != IoRtcTime.year) || (lastTime.century != IoRtcTime.century) ); IoWriteByteOnPort(0x70, 0x32); time24or12Mode = IoReadByteFromPort(0x71); // Convert to binary if it is necessary if (!(time24or12Mode & 0x04)) { IoRtcTime.sec = (IoRtcTime.sec & 0x0F) + ((IoRtcTime.sec / 16) * 10); IoRtcTime.min = (IoRtcTime.min & 0x0F) + ((IoRtcTime.min / 16) * 10); IoRtcTime.hour = ( (IoRtcTime.hour & 0x0F) + (((IoRtcTime.hour & 0x70) / 16) * 10) ) | (IoRtcTime.hour & 0x80); IoRtcTime.day = (IoRtcTime.day & 0x0F) + ((IoRtcTime.day / 16) * 10); IoRtcTime.month = (IoRtcTime.month & 0x0F) + ((IoRtcTime.month / 16) * 10); IoRtcTime.year = (IoRtcTime.year & 0x0F) + ((IoRtcTime.year / 16) * 10); IoRtcTime.century = (IoRtcTime.century & 0x0F) + ((IoRtcTime.century / 16) * 10); } // Convert 12 to 24 hour if necessary if (!(time24or12Mode & 0x02) && (IoRtcTime.hour & 0x80)) { IoRtcTime.hour = ((IoRtcTime.hour & 0x7F) + 12) % 24; } } void IoEnableRtc(void) { ulong flags = KePauseIRQs(); char readedInterruptConfig; char readedRegister; char readedIrqs; uchar RtcRate; // Setting up the register control and interrupt rates RtcRate = 0x05; IoWriteByteOnPort(0x70, 0x8B); readedRegister = IoReadByteFromPort(0x71); IoWriteByteOnPort(0x70, 0x8B); // Because reading flushes IoWriteByteOnPort(0x71, readedRegister | 0x40); IoWriteByteOnPort(0x70, 0x8A); readedInterruptConfig = IoReadByteFromPort(0x71); IoWriteByteOnPort(0x70, 0x8A); // Because reading flushes IoWriteByteOnPort(0x71, (readedInterruptConfig & 0xF0) | RtcRate); IoWriteByteOnPort(0x70, 0x0C); IoReadByteFromPort(0x71); // Flush // Setting up the IRQs readedIrqs = IoReadByteFromPort(0xA1); IoWriteByteOnPort(0xA1, 0xFE & readedIrqs); // Enables IRQ on PIC 2 readedIrqs = IoReadByteFromPort(0x21); IoWriteByteOnPort(0x21, 0xFB & readedIrqs); // Enables IRQ on PIC 1 // clean-up IoWriteByteOnPort(0x70, 0x0C); // Select status reg C IoReadByteFromPort(0x71); // Flush IoGetTimeFromRtc(); KeRestoreIRQs(flags); IoEnableNMI(); } void RtcHandler(void) { //bprintf(BStdOut, " *RTC - "); IoWriteByteOnPort(0x70, 0x0C); // Selects status reg C IoReadByteFromPort(0x71); // Flush IoRtcTicks++; IoSendEOItoPIC(0x28); //bprintf(BStdOut, " - EOI* "); } void IoPrintRtcTime(void) { KernLog("[RTC Time] %s %d/%d/%d ; %d:%d:%d\n", WeekDays[IoRtcTime.weekday], IoRtcTime.day, IoRtcTime.month, IoRtcTime.year + IoRtcTime.century*100, IoRtcTime.hour, IoRtcTime.min, IoRtcTime.sec ); }