summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCody Cutler <[email protected]>2014-09-12 17:18:57 -0400
committerCody Cutler <[email protected]>2014-09-12 18:09:51 -0400
commitaae4e7490fbb61de13f61d90092b177eeb258216 (patch)
tree22cebdefb8bc72ed95d2c11759896023adf1da99
parent75dee1219ffee14f9cb3ec6bb739f06bae27de9c (diff)
downloadxv6-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.h2
-rw-r--r--lapic.c71
-rw-r--r--sysproc.c1
-rw-r--r--user.h1
4 files changed, 72 insertions, 3 deletions
diff --git a/defs.h b/defs.h
index 560b19a..43431e3 100644
--- a/defs.h
+++ b/defs.h
@@ -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);
diff --git a/lapic.c b/lapic.c
index 94b484f..4da4214 100644
--- a/lapic.c
+++ b/lapic.c
@@ -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;
+}
diff --git a/sysproc.c b/sysproc.c
index c66339e..027a5e5 100644
--- a/sysproc.c
+++ b/sysproc.c
@@ -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"
diff --git a/user.h b/user.h
index 9e26cf1..f45b8d5 100644
--- a/user.h
+++ b/user.h
@@ -1,4 +1,5 @@
struct stat;
+struct rtcdate;
// system calls
int fork(void);