/***** cmos.c ******************************************************** * (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * * * * CMOS I/O Routines * * ================= * * * * ! IMPORTANT NOTE ! Close interrupts before any CMOS operation * ************************************************************ cta os */ #include #include #include "cmos.h" /***************************************************************** * !!!!!!!!!! IMPORTANT NOTE !!!!!!!!!! * * You should close interrupts before any CMOS operation. * *****************************************************************/ inline unsigned char i86_cmos_read (unsigned char address) { outportb(0x70, address); iowait(); return inportb(0x71); } inline void i86_cmos_write (unsigned char address, unsigned char val) { outportb(0x70, address); iowait(); outportb(0x71, val); } void i86_cmos_write_clock (const TIME* time) { unsigned char BCD = ((i86_cmos_read(0x0b)&4)==0) ? 1 : 0; unsigned char ampm = ((i86_cmos_read(0x0b)&2)==0) ? 1 : 0; i86_cmos_write (0, (BCD) ? (time->second%10) | (time->second/10*16) : time->second); // Seconds i86_cmos_write (2, (BCD) ? (time->minute%10) | (time->minute/10*16) : time->minute); // Minutes if (ampm && time->hour > 12) // Hours i86_cmos_write (4, (BCD) ? (((time->hour - 12) % 10) | ((time->hour - 12)/10*16) | 0x80) : (time->hour | 0x80) ); else if (ampm && time->hour == 0) // Midnight convention: 12 PM = 00:00 i86_cmos_write (4, (BCD) ? 0x92 : 0x8C); else i86_cmos_write (4, (BCD) ? (time->hour%10) | (time->hour/10*16) : time->hour); // 24h / AM i86_cmos_write (6, (BCD) ? (time->weekday%10) | (time->weekday/10*16) : time->weekday); // Weekday i86_cmos_write (7, (BCD) ? (time->day%10) | (time->day/10*16) : time->day); // Day i86_cmos_write (8, (BCD) ? (time->month%10) | (time->month/10*16) : time->month); // Month i86_cmos_write (9, (BCD) ? (time->year%10) | (time->year/10*16) : time->year); // Year i86_cmos_write (0x32, (BCD) ? (time->century%10) | (time->century/10*16) : time->century); // Century } void i86_cmos_read_clock(TIME* tim) { unsigned char BCD = ((i86_cmos_read(0x0b)&4)==0) ? 1 : 0; unsigned char am_pm = ((i86_cmos_read(0x0b)&2)==0) ? 1 : 0; tim->second = (BCD) ? (i86_cmos_read(0x00)%16) + 10*(i86_cmos_read(0x00)/16): i86_cmos_read(0x00); tim->minute = (BCD) ? (i86_cmos_read(0x02)%16) + 10*(i86_cmos_read(0x02)/16): i86_cmos_read(0x02); // Time is PM if (am_pm && i86_cmos_read(0x04)&80) { tim->hour = (BCD) ? ((i86_cmos_read(0x04)-0x80)%16) + 10*((i86_cmos_read(0x04)-0x80)/16): i86_cmos_read(0x04)-0x80; tim->hour += 12; } // 24Hour format, or AM else tim->hour = (BCD) ? (i86_cmos_read(0x04)%16) + 10*(i86_cmos_read(0x04)/16): i86_cmos_read(0x04); tim->weekday = (BCD) ? (i86_cmos_read(0x06)%16) + 10*(i86_cmos_read(0x06)/16): i86_cmos_read(0x06); tim->day = (BCD) ? (i86_cmos_read(0x07)%16) + 10*(i86_cmos_read(0x07)/16): i86_cmos_read(0x07); tim->month = (BCD) ? (i86_cmos_read(0x08)%16) + 10*(i86_cmos_read(0x08)/16): i86_cmos_read(0x08); tim->year = (BCD) ? (i86_cmos_read(0x09)%16) + 10*(i86_cmos_read(0x09)/16): i86_cmos_read(0x09); tim->century = (BCD) ? (i86_cmos_read(0x32)%16) + 10*(i86_cmos_read(0x32)/16): i86_cmos_read(0x32); } unsigned char i86_cmos_read_floppy_drives () { outportb (0x70, 0x10); return inportb(0x71); }