diff options
author | Cody Cutler <[email protected]> | 2014-09-12 17:18:57 -0400 |
---|---|---|
committer | Cody Cutler <[email protected]> | 2014-09-12 18:09:51 -0400 |
commit | aae4e7490fbb61de13f61d90092b177eeb258216 (patch) | |
tree | 22cebdefb8bc72ed95d2c11759896023adf1da99 | |
parent | 75dee1219ffee14f9cb3ec6bb739f06bae27de9c (diff) | |
download | xv6-labs-aae4e7490fbb61de13f61d90092b177eeb258216.tar.gz xv6-labs-aae4e7490fbb61de13f61d90092b177eeb258216.tar.bz2 xv6-labs-aae4e7490fbb61de13f61d90092b177eeb258216.zip |
cmosgetdate() for system-call homework
the day of reckoning has come for the debug port "Shutdown" hack.
instead of mucking with ACPI or using a new hack, the student will now write
sys_date() using the cmosgetdate() helper.
-rw-r--r-- | defs.h | 2 | ||||
-rw-r--r-- | lapic.c | 71 | ||||
-rw-r--r-- | sysproc.c | 1 | ||||
-rw-r--r-- | user.h | 1 |
4 files changed, 72 insertions, 3 deletions
@@ -4,6 +4,7 @@ struct file; struct inode; struct pipe; struct proc; +struct rtcdate; struct spinlock; struct stat; struct superblock; @@ -71,6 +72,7 @@ void kinit2(void*, void*); void kbdintr(void); // lapic.c +void cmostime(struct rtcdate *r); int cpunum(void); extern volatile uint* lapic; void lapiceoi(void); @@ -3,6 +3,7 @@ #include "types.h" #include "defs.h" +#include "date.h" #include "memlayout.h" #include "traps.h" #include "mmu.h" @@ -130,7 +131,8 @@ microdelay(int us) { } -#define IO_RTC 0x70 +#define CMOS_PORT 0x70 +#define CMOS_RETURN 0x71 // Start additional processor running entry code at addr. // See Appendix B of MultiProcessor Specification. @@ -143,8 +145,8 @@ lapicstartap(uchar apicid, uint addr) // "The BSP must initialize CMOS shutdown code to 0AH // and the warm reset vector (DWORD based at 40:67) to point at // the AP startup code prior to the [universal startup algorithm]." - outb(IO_RTC, 0xF); // offset 0xF is shutdown code - outb(IO_RTC+1, 0x0A); + outb(CMOS_PORT, 0xF); // offset 0xF is shutdown code + outb(CMOS_PORT+1, 0x0A); wrv = (ushort*)P2V((0x40<<4 | 0x67)); // Warm reset vector wrv[0] = 0; wrv[1] = addr >> 4; @@ -169,4 +171,67 @@ lapicstartap(uchar apicid, uint addr) } } +#define CMOS_STATA 0x0a +#define CMOS_STATB 0x0b +#define CMOS_UIP (1 << 7) // RTC update in progress +#define SECS 0x00 +#define MINS 0x02 +#define HOURS 0x04 +#define DAY 0x07 +#define MONTH 0x08 +#define YEAR 0x09 + +static uint cmos_read(uint reg) +{ + outb(CMOS_PORT, reg); + microdelay(200); + + return inb(CMOS_RETURN); +} + +static void fill_rtcdate(struct rtcdate *r) +{ + r->second = cmos_read(SECS); + r->minute = cmos_read(MINS); + r->hour = cmos_read(HOURS); + r->day = cmos_read(DAY); + r->month = cmos_read(MONTH); + r->year = cmos_read(YEAR); +} + +// qemu seems to use 24-hour GWT and the values are BCD encoded +void cmostime(struct rtcdate *r) +{ + struct rtcdate t1, t2; + int sb, bcd; + + sb = cmos_read(CMOS_STATB); + + bcd = (sb & (1 << 2)) == 0; + + // make sure CMOS doesn't modify time while we read it + for (;;) { + fill_rtcdate(&t1); + if (cmos_read(CMOS_STATA) & CMOS_UIP) + continue; + fill_rtcdate(&t2); + if (memcmp(&t1, &t2, sizeof(t1)) == 0) + break; + } + + // convert + if (bcd) { +#define CONV(x) (t1.x = ((t1.x >> 4) * 10) + (t1.x & 0xf)) + CONV(second); + CONV(minute); + CONV(hour ); + CONV(day ); + CONV(month ); + CONV(year ); +#undef CONV + } + + *r = t1; + r->year += 2000; +} @@ -1,6 +1,7 @@ #include "types.h" #include "x86.h" #include "defs.h" +#include "date.h" #include "param.h" #include "memlayout.h" #include "mmu.h" @@ -1,4 +1,5 @@ struct stat; +struct rtcdate; // system calls int fork(void); |