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.
This commit is contained in:
Cody Cutler 2014-09-12 17:18:57 -04:00
parent 75dee1219f
commit aae4e7490f
4 changed files with 72 additions and 3 deletions

2
defs.h
View file

@ -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);

71
lapic.c
View file

@ -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;
}

View file

@ -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
user.h
View file

@ -1,4 +1,5 @@
struct stat;
struct rtcdate;
// system calls
int fork(void);