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:
parent
75dee1219f
commit
aae4e7490f
2
defs.h
2
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);
|
||||
|
|
71
lapic.c
71
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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue