kern

changeset 41:928b0ebfff4d

merged the timer/rtc/etc from the misc branch
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 14 Jun 2011 01:19:07 +0300
parents 2cb5ab18e76e 710739e33da8
children e6de3c6015cb
files Makefile src/intr.c src/main.c
diffstat 16 files changed, 414 insertions(+), 20 deletions(-) [+]
line diff
     1.1 --- a/Makefile	Sat May 28 08:06:47 2011 +0300
     1.2 +++ b/Makefile	Tue Jun 14 01:19:07 2011 +0300
     1.3 @@ -23,6 +23,9 @@
     1.4  $(bin): $(obj)
     1.5  	ld -melf_i386 -o $@ -Ttext 0x100000 -e kentry $(obj) -Map link.map
     1.6  
     1.7 +%.s: %.c
     1.8 +	$(CC) $(CFLAGS) -S -o $@ $<
     1.9 +
    1.10  -include $(dep)
    1.11  
    1.12  %.d: %.c
     2.1 --- a/run	Sat May 28 08:06:47 2011 +0300
     2.2 +++ b/run	Tue Jun 14 01:19:07 2011 +0300
     2.3 @@ -1,3 +1,3 @@
     2.4  #!/bin/sh
     2.5  
     2.6 -qemu -kernel kernel.elf
     2.7 +qemu -kernel kernel.elf -soundhw pcspk
     3.1 --- a/src/asmops.h	Sat May 28 08:06:47 2011 +0300
     3.2 +++ b/src/asmops.h	Tue Jun 14 01:19:07 2011 +0300
     3.3 @@ -32,4 +32,6 @@
     3.4  	"outl %0, %1\n\t" \
     3.5  	:: "a" ((unsigned long)(src)), "dN" ((unsigned short)(port)))
     3.6  
     3.7 +#define iodelay() outb(0, 0x80)
     3.8 +
     3.9  #endif	/* ASMOPS_H_ */
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/config.h	Tue Jun 14 01:19:07 2011 +0300
     4.3 @@ -0,0 +1,7 @@
     4.4 +#ifndef _CONFIG_H_
     4.5 +#define _CONFIG_H_
     4.6 +
     4.7 +/* frequency of generated timer ticks in hertz */
     4.8 +#define TICK_FREQ_HZ		250
     4.9 +
    4.10 +#endif	/* _CONFIG_H_ */
     5.1 --- a/src/intr.c	Sat May 28 08:06:47 2011 +0300
     5.2 +++ b/src/intr.c	Tue Jun 14 01:19:07 2011 +0300
     5.3 @@ -12,14 +12,6 @@
     5.4  #define GATE_DEFAULT	(1 << 11)
     5.5  #define GATE_PRESENT	(1 << 15)
     5.6  
     5.7 -/* offset used to remap IRQ numbers (+32) */
     5.8 -#define IRQ_OFFSET		32
     5.9 -/* conversion macros between IRQ and interrupt numbers */
    5.10 -#define IRQ_TO_INTR(x)	((x) + IRQ_OFFSET)
    5.11 -#define INTR_TO_IRQ(x)	((x) - IRQ_OFFSET)
    5.12 -/* checks whether a particular interrupt is an remapped IRQ */
    5.13 -#define IS_IRQ(n)	((n) >= IRQ_OFFSET && (n) < IRQ_OFFSET + 16)
    5.14 -
    5.15  /* PIC command and data ports */
    5.16  #define PIC1_CMD	0x20
    5.17  #define PIC1_DATA	0x21
     6.1 --- a/src/intr.h	Sat May 28 08:06:47 2011 +0300
     6.2 +++ b/src/intr.h	Tue Jun 14 01:19:07 2011 +0300
     6.3 @@ -4,6 +4,15 @@
     6.4  #include <inttypes.h>
     6.5  #include "asmops.h"
     6.6  
     6.7 +/* offset used to remap IRQ numbers (+32) */
     6.8 +#define IRQ_OFFSET		32
     6.9 +/* conversion macros between IRQ and interrupt numbers */
    6.10 +#define IRQ_TO_INTR(x)	((x) + IRQ_OFFSET)
    6.11 +#define INTR_TO_IRQ(x)	((x) - IRQ_OFFSET)
    6.12 +/* checks whether a particular interrupt is an remapped IRQ */
    6.13 +#define IS_IRQ(n)	((n) >= IRQ_OFFSET && (n) < IRQ_OFFSET + 16)
    6.14 +
    6.15 +
    6.16  typedef void (*intr_func_t)(int, uint32_t);
    6.17  
    6.18  
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/klibc/time.c	Tue Jun 14 01:19:07 2011 +0300
     7.3 @@ -0,0 +1,136 @@
     7.4 +#include <stdio.h>
     7.5 +#include "time.h"
     7.6 +#include "rtc.h"
     7.7 +#include "timer.h"
     7.8 +#include "config.h"
     7.9 +
    7.10 +#define MINSEC		60
    7.11 +#define HOURSEC		(60 * MINSEC)
    7.12 +#define DAYSEC		(24 * HOURSEC)
    7.13 +#define YEARDAYS(x)	(is_leap_year(x) ? 366 : 365)
    7.14 +
    7.15 +/* 1-1-1970 was a thursday */
    7.16 +#define EPOCH_WDAY	4
    7.17 +
    7.18 +static int is_leap_year(int yr);
    7.19 +
    7.20 +static int mdays[2][12] = {
    7.21 +	{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    7.22 +	{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
    7.23 +};
    7.24 +
    7.25 +static char *wday[] = {
    7.26 +	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
    7.27 +};
    7.28 +static char *mon[] = {
    7.29 +	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
    7.30 +	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    7.31 +};
    7.32 +
    7.33 +
    7.34 +time_t time(time_t *tp)
    7.35 +{
    7.36 +	time_t res = start_time + nticks / TICK_FREQ_HZ;
    7.37 +
    7.38 +	if(tp) *tp = res;
    7.39 +	return res;
    7.40 +}
    7.41 +
    7.42 +char *asctime(struct tm *tm)
    7.43 +{
    7.44 +	static char buf[64];
    7.45 +	return asctime_r(tm, buf);
    7.46 +}
    7.47 +
    7.48 +char *asctime_r(struct tm *tm, char *buf)
    7.49 +{
    7.50 +	sprintf(buf, "%s %s %d %02d:%02d:%02d %d\n", wday[tm->tm_wday],
    7.51 +			mon[tm->tm_mon], tm->tm_mday, tm->tm_hour, tm->tm_min,
    7.52 +			tm->tm_sec, tm->tm_year + 1900);
    7.53 +	return buf;
    7.54 +}
    7.55 +
    7.56 +time_t mktime(struct tm *tm)
    7.57 +{
    7.58 +	int i, num_years = tm->tm_year - 70;
    7.59 +	int year = 1970;
    7.60 +	int days = day_of_year(tm->tm_year + 1900, tm->tm_mon, tm->tm_mday - 1);
    7.61 +
    7.62 +	/* set correct yearday */
    7.63 +	tm->tm_yday = days;
    7.64 +
    7.65 +	for(i=0; i<num_years; i++) {
    7.66 +		days += YEARDAYS(year++);
    7.67 +	}
    7.68 +
    7.69 +	/* set wday correctly */
    7.70 +	tm->tm_wday = (days + EPOCH_WDAY) % 7;
    7.71 +
    7.72 +	return (time_t)days * DAYSEC + tm->tm_hour * HOURSEC +
    7.73 +		tm->tm_min * MINSEC + tm->tm_sec;
    7.74 +}
    7.75 +
    7.76 +struct tm *gmtime(time_t *tp)
    7.77 +{
    7.78 +	static struct tm tm;
    7.79 +	return gmtime_r(tp, &tm);
    7.80 +}
    7.81 +
    7.82 +struct tm *gmtime_r(time_t *tp, struct tm *tm)
    7.83 +{
    7.84 +	int year, days, leap, yrdays;
    7.85 +	time_t t;
    7.86 +
    7.87 +	year = 1970;
    7.88 +	days = *tp / DAYSEC;
    7.89 +	t = *tp % DAYSEC;
    7.90 +
    7.91 +	tm->tm_wday = (days + EPOCH_WDAY) % 7;
    7.92 +
    7.93 +	while(days >= (yrdays = YEARDAYS(year))) {
    7.94 +		days -= yrdays;
    7.95 +		year++;
    7.96 +	}
    7.97 +	tm->tm_year = year - 1900;
    7.98 +	tm->tm_yday = days;
    7.99 +
   7.100 +	leap = is_leap_year(year);
   7.101 +	tm->tm_mon = 0;
   7.102 +	while(days >= mdays[leap][tm->tm_mon]) {
   7.103 +		days -= mdays[leap][tm->tm_mon++];
   7.104 +	}
   7.105 +
   7.106 +	tm->tm_mday = days + 1;
   7.107 +
   7.108 +	tm->tm_hour = t / HOURSEC;
   7.109 +	t %= HOURSEC;
   7.110 +	tm->tm_min = t / MINSEC;
   7.111 +	tm->tm_sec = t % MINSEC;
   7.112 +	return tm;
   7.113 +}
   7.114 +
   7.115 +int day_of_year(int year, int mon, int day)
   7.116 +{
   7.117 +	int i, yday, leap;
   7.118 +
   7.119 +	leap = is_leap_year(year) ? 1 : 0;
   7.120 +	yday = day;
   7.121 +
   7.122 +	for(i=0; i<mon; i++) {
   7.123 +		yday += mdays[leap][i];
   7.124 +	}
   7.125 +	return yday;
   7.126 +}
   7.127 +
   7.128 +static int is_leap_year(int yr)
   7.129 +{
   7.130 +	/* exceptions first */
   7.131 +	if(yr % 400 == 0) {
   7.132 +		return 1;
   7.133 +	}
   7.134 +	if(yr % 100 == 0) {
   7.135 +		return 0;
   7.136 +	}
   7.137 +	/* standard case */
   7.138 +	return yr % 4 == 0;
   7.139 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/klibc/time.h	Tue Jun 14 01:19:07 2011 +0300
     8.3 @@ -0,0 +1,30 @@
     8.4 +#ifndef _TIME_H_
     8.5 +#define _TIME_H_
     8.6 +
     8.7 +typedef long time_t;
     8.8 +
     8.9 +struct tm {
    8.10 +	int tm_sec;
    8.11 +	int tm_min;
    8.12 +	int tm_hour;
    8.13 +	int tm_mday;
    8.14 +	int tm_mon;
    8.15 +	int tm_year;
    8.16 +	int tm_wday;
    8.17 +	int tm_yday;
    8.18 +	int tm_isdst;
    8.19 +};
    8.20 +
    8.21 +time_t time(time_t *tp);
    8.22 +char *asctime(struct tm *tm);
    8.23 +char *asctime_r(struct tm *tm, char *buf);
    8.24 +
    8.25 +time_t mktime(struct tm *tm);
    8.26 +struct tm *gmtime(time_t *tp);
    8.27 +struct tm *gmtime_r(time_t *tp, struct tm *tm);
    8.28 +
    8.29 +/* non-standard helpers */
    8.30 +int day_of_year(int year, int mon, int day);
    8.31 +
    8.32 +
    8.33 +#endif	/* _TIME_H_ */
     9.1 --- a/src/main.c	Sat May 28 08:06:47 2011 +0300
     9.2 +++ b/src/main.c	Tue Jun 14 01:19:07 2011 +0300
     9.3 @@ -5,6 +5,8 @@
     9.4  #include "asmops.h"
     9.5  #include "segm.h"
     9.6  #include "intr.h"
     9.7 +#include "rtc.h"
     9.8 +#include "timer.h"
     9.9  #include "mem.h"
    9.10  #include "vm.h"
    9.11  
    9.12 @@ -55,14 +57,16 @@
    9.13  	init_segm();
    9.14  	init_intr();
    9.15  
    9.16 -	/* silence the blasted timer interrupt */
    9.17 -	interrupt(32, do_nothing);
    9.18  
    9.19  	/* initialize the physical memory manager */
    9.20  	init_mem(mbinf);
    9.21  	/* initialize paging and the virtual memory manager */
    9.22  	init_vm();
    9.23  
    9.24 +	/* initialize the timer and RTC */
    9.25 +	init_timer();
    9.26 +	init_rtc();
    9.27 +
    9.28  	/* initialization complete, enable interrupts */
    9.29  	enable_intr();
    9.30  
    9.31 @@ -78,7 +82,3 @@
    9.32  		}
    9.33  	}
    9.34  }
    9.35 -
    9.36 -static void do_nothing()
    9.37 -{
    9.38 -}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/rtc.c	Tue Jun 14 01:19:07 2011 +0300
    10.3 @@ -0,0 +1,106 @@
    10.4 +#include <stdio.h>
    10.5 +#include <time.h>
    10.6 +#include <asmops.h>
    10.7 +#include "rtc.h"
    10.8 +
    10.9 +/* CMOS I/O ports */
   10.10 +#define PORT_CTL	0x70
   10.11 +#define PORT_DATA	0x71
   10.12 +
   10.13 +/* CMOS RTC registers */
   10.14 +#define REG_SEC			0
   10.15 +#define REG_ALARM_SEC	1
   10.16 +#define REG_MIN			2
   10.17 +#define REG_ALARM_MIN	3
   10.18 +#define REG_HOUR		4
   10.19 +#define REG_ALARM_HOUR	5
   10.20 +#define REG_WEEKDAY		6
   10.21 +#define REG_DAY			7
   10.22 +#define REG_MONTH		8
   10.23 +#define REG_YEAR		9
   10.24 +#define REG_STATA		10
   10.25 +#define REG_STATB		11
   10.26 +#define REG_STATC		12
   10.27 +#define REG_STATD		13
   10.28 +
   10.29 +#define STATA_BUSY	(1 << 7)
   10.30 +#define STATB_24HR	(1 << 1)
   10.31 +#define STATB_BIN	(1 << 2)
   10.32 +
   10.33 +#define HOUR_PM_BIT		(1 << 7)
   10.34 +
   10.35 +#define BCD_TO_BIN(x)	((((x) >> 4) & 0xf) * 10 + ((x) & 0xf))
   10.36 +
   10.37 +static void read_rtc(struct tm *tm);
   10.38 +static int read_reg(int reg);
   10.39 +
   10.40 +
   10.41 +void init_rtc(void)
   10.42 +{
   10.43 +	struct tm tm;
   10.44 +
   10.45 +	read_rtc(&tm);
   10.46 +	start_time = mktime(&tm);
   10.47 +
   10.48 +	printf("System real-time clock: %s", asctime(&tm));
   10.49 +}
   10.50 +
   10.51 +
   10.52 +static void read_rtc(struct tm *tm)
   10.53 +{
   10.54 +	int statb, pm;
   10.55 +
   10.56 +	/* wait for any clock updates to finish */
   10.57 +	while(read_reg(REG_STATA) & STATA_BUSY);
   10.58 +
   10.59 +	tm->tm_sec = read_reg(REG_SEC);
   10.60 +	tm->tm_min = read_reg(REG_MIN);
   10.61 +	tm->tm_hour = read_reg(REG_HOUR);
   10.62 +	tm->tm_mday = read_reg(REG_DAY);
   10.63 +	tm->tm_mon = read_reg(REG_MONTH);
   10.64 +	tm->tm_year = read_reg(REG_YEAR);
   10.65 +
   10.66 +	/* in 12hour mode, bit 7 means post-meridiem */
   10.67 +	pm = tm->tm_hour & HOUR_PM_BIT;
   10.68 +	tm->tm_hour &= ~HOUR_PM_BIT;
   10.69 +
   10.70 +	/* convert to binary if needed */
   10.71 +	statb = read_reg(REG_STATB);
   10.72 +	if(!(statb & STATB_BIN)) {
   10.73 +		tm->tm_sec = BCD_TO_BIN(tm->tm_sec);
   10.74 +		tm->tm_min = BCD_TO_BIN(tm->tm_min);
   10.75 +		tm->tm_hour = BCD_TO_BIN(tm->tm_hour);
   10.76 +		tm->tm_mday = BCD_TO_BIN(tm->tm_mday);
   10.77 +		tm->tm_mon = BCD_TO_BIN(tm->tm_mon);
   10.78 +		tm->tm_year = BCD_TO_BIN(tm->tm_year);
   10.79 +	}
   10.80 +
   10.81 +	/* make the year an offset from 1900 */
   10.82 +	if(tm->tm_year < 100) {
   10.83 +		tm->tm_year += 100;
   10.84 +	} else {
   10.85 +		tm->tm_year -= 1900;
   10.86 +	}
   10.87 +
   10.88 +	/* if tm_hour is in 12h mode, convert to 24h */
   10.89 +	if(!(statb & STATB_24HR)) {
   10.90 +		if(tm->tm_hour == 12) {
   10.91 +			tm->tm_hour = 0;
   10.92 +		}
   10.93 +		if(pm) {
   10.94 +			tm->tm_hour += 12;
   10.95 +		}
   10.96 +	}
   10.97 +
   10.98 +	tm->tm_mon -= 1;	/* we want months to start from 0 */
   10.99 +}
  10.100 +
  10.101 +static int read_reg(int reg)
  10.102 +{
  10.103 +	unsigned char val;
  10.104 +	outb(reg, PORT_CTL);
  10.105 +	iodelay();
  10.106 +	inb(val, PORT_DATA);
  10.107 +	iodelay();
  10.108 +	return val;
  10.109 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/rtc.h	Tue Jun 14 01:19:07 2011 +0300
    11.3 @@ -0,0 +1,11 @@
    11.4 +#ifndef _RTC_H_
    11.5 +#define _RTC_H_
    11.6 +
    11.7 +#include <time.h>
    11.8 +
    11.9 +/* the time read from rtc during init */
   11.10 +time_t start_time;
   11.11 +
   11.12 +void init_rtc(void);
   11.13 +
   11.14 +#endif	/* _RTC_H_ */
    12.1 --- a/src/term.c	Sat May 28 08:06:47 2011 +0300
    12.2 +++ b/src/term.c	Tue Jun 14 01:19:07 2011 +0300
    12.3 @@ -29,7 +29,6 @@
    12.4  
    12.5  /* output a single character, handles formatting, cursor advancement
    12.6   * and scrolling the screen when we reach the bottom.
    12.7 - * TODO make visible cursor actually move.
    12.8   */
    12.9  int putchar(int c)
   12.10  {
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/src/timer.c	Tue Jun 14 01:19:07 2011 +0300
    13.3 @@ -0,0 +1,77 @@
    13.4 +#include <stdio.h>
    13.5 +#include <time.h>
    13.6 +#include "intr.h"
    13.7 +#include "asmops.h"
    13.8 +#include "timer.h"
    13.9 +#include "config.h"
   13.10 +
   13.11 +/* frequency of the oscillator driving the 8254 timer */
   13.12 +#define OSC_FREQ_HZ		1193182
   13.13 +
   13.14 +/* macro to divide and round to the nearest integer */
   13.15 +#define DIV_ROUND(a, b) ((a) / (b) + ((a) % (b)) / ((b) / 2))
   13.16 +
   13.17 +/* I/O ports connected to the 8254 */
   13.18 +#define PORT_DATA0	0x40
   13.19 +#define PORT_DATA1	0x41
   13.20 +#define PORT_DATA2	0x42
   13.21 +#define PORT_CMD	0x43
   13.22 +
   13.23 +/* command bits */
   13.24 +#define CMD_CHAN0			0
   13.25 +#define CMD_CHAN1			(1 << 6)
   13.26 +#define CMD_CHAN2			(2 << 6)
   13.27 +#define CMD_RDBACK			(3 << 6)
   13.28 +
   13.29 +#define CMD_LATCH			0
   13.30 +#define CMD_ACCESS_LOW		(1 << 4)
   13.31 +#define CMD_ACCESS_HIGH		(2 << 4)
   13.32 +#define CMD_ACCESS_BOTH		(3 << 4)
   13.33 +
   13.34 +#define CMD_OP_INT_TERM		0
   13.35 +#define CMD_OP_ONESHOT		(1 << 1)
   13.36 +#define CMD_OP_RATE			(2 << 1)
   13.37 +#define CMD_OP_SQWAVE		(3 << 1)
   13.38 +#define CMD_OP_SOFT_STROBE	(4 << 1)
   13.39 +#define CMD_OP_HW_STROBE	(5 << 1)
   13.40 +
   13.41 +#define CMD_MODE_BIN		0
   13.42 +#define CMD_MODE_BCD		1
   13.43 +
   13.44 +
   13.45 +static void intr_handler();
   13.46 +
   13.47 +
   13.48 +void init_timer(void)
   13.49 +{
   13.50 +	/* calculate the reload count: round(osc / freq) */
   13.51 +	int reload_count = DIV_ROUND(OSC_FREQ_HZ, TICK_FREQ_HZ);
   13.52 +
   13.53 +	/* set the mode to square wave for channel 0, both low
   13.54 +	 * and high reload count bytes will follow...
   13.55 +	 */
   13.56 +	outb(CMD_CHAN0 | CMD_ACCESS_BOTH | CMD_OP_SQWAVE, PORT_CMD);
   13.57 +
   13.58 +	/* write the low and high bytes of the reload count to the
   13.59 +	 * port for channel 0
   13.60 +	 */
   13.61 +	outb(reload_count & 0xff, PORT_DATA0);
   13.62 +	outb((reload_count >> 8) & 0xff, PORT_DATA0);
   13.63 +
   13.64 +	/* set the timer interrupt handler */
   13.65 +	interrupt(IRQ_TO_INTR(0), intr_handler);
   13.66 +}
   13.67 +
   13.68 +/* This will be called by the interrupt dispatcher approximately
   13.69 + * every 1/250th of a second, so it must be extremely fast.
   13.70 + * For now, just increasing a tick counter will suffice.
   13.71 + */
   13.72 +static void intr_handler()
   13.73 +{
   13.74 +	nticks++;
   13.75 +
   13.76 +	if(nticks % TICK_FREQ_HZ == 0) {
   13.77 +		time_t t = time(0);
   13.78 +		printf("%s", asctime(gmtime(&t)));
   13.79 +	}
   13.80 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/src/timer.h	Tue Jun 14 01:19:07 2011 +0300
    14.3 @@ -0,0 +1,8 @@
    14.4 +#ifndef _TIMER_H_
    14.5 +#define _TIMER_H_
    14.6 +
    14.7 +unsigned long nticks;
    14.8 +
    14.9 +void init_timer(void);
   14.10 +
   14.11 +#endif	/* _TIMER_H_ */
    15.1 --- a/src/vid.c	Sat May 28 08:06:47 2011 +0300
    15.2 +++ b/src/vid.c	Tue Jun 14 01:19:07 2011 +0300
    15.3 @@ -1,5 +1,6 @@
    15.4  #include <string.h>
    15.5  #include "vid.h"
    15.6 +#include "intr.h"
    15.7  #include "asmops.h"
    15.8  
    15.9  /* height of our virtual console text buffer */
   15.10 @@ -27,10 +28,15 @@
   15.11  
   15.12  void clear_scr(void)
   15.13  {
   15.14 +	int istate = get_intr_state();
   15.15 +	disable_intr();
   15.16 +
   15.17  	memset16(vmem, VMEM_CHAR(' ', LTGRAY, BLACK), WIDTH * HEIGHT);
   15.18  	start_line = 0;
   15.19  	set_start_line(0);
   15.20  	set_cursor(0, 0);
   15.21 +
   15.22 +	set_intr_state(istate);
   15.23  }
   15.24  
   15.25  void set_char(char c, int x, int y, int fg, int bg)
   15.26 @@ -41,6 +47,8 @@
   15.27  void set_cursor(int x, int y)
   15.28  {
   15.29  	int loc;
   15.30 +	int istate = get_intr_state();
   15.31 +	disable_intr();
   15.32  
   15.33  	if(x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) {
   15.34  		loc = 0xffff;
   15.35 @@ -52,10 +60,15 @@
   15.36  	outb(loc, CRTC_DATA);
   15.37  	outb(CRTC_CURSOR_HIGH, CRTC_ADDR);
   15.38  	outb(loc >> 8, CRTC_DATA);
   15.39 +
   15.40 +	set_intr_state(istate);
   15.41  }
   15.42  
   15.43  void scroll_scr(void)
   15.44  {
   15.45 +	int new_line, istate = get_intr_state();
   15.46 +	disable_intr();
   15.47 +
   15.48  	if(++start_line > VIRT_HEIGHT - HEIGHT) {
   15.49  		/* The bottom of the visible range reached the end of our text buffer.
   15.50  		 * Copy the rest of the lines to the top and reset start_line.
   15.51 @@ -65,10 +78,11 @@
   15.52  	}
   15.53  
   15.54  	/* clear the next line that will be revealed by scrolling */
   15.55 -	int new_line = start_line + HEIGHT - 1;
   15.56 +	new_line = start_line + HEIGHT - 1;
   15.57  	memset16(vmem + new_line * WIDTH, VMEM_CHAR(' ', LTGRAY, BLACK), WIDTH);
   15.58 +	set_start_line(start_line);
   15.59  
   15.60 -	set_start_line(start_line);
   15.61 +	set_intr_state(istate);
   15.62  }
   15.63  
   15.64  static void set_start_line(int line)
    16.1 --- a/src/vm.c	Sat May 28 08:06:47 2011 +0300
    16.2 +++ b/src/vm.c	Tue Jun 14 01:19:07 2011 +0300
    16.3 @@ -259,7 +259,7 @@
    16.4  
    16.5  void pgfree(int start, int num)
    16.6  {
    16.7 -	int i, area, end, intr_state;
    16.8 +	int i, area, intr_state;
    16.9  	struct page_range *node, *new, *prev, *next;
   16.10  
   16.11  	intr_state = get_intr_state();
   16.12 @@ -276,7 +276,7 @@
   16.13  		panic("pgfree: can't allocate new page_range node to add the freed pages\n");
   16.14  	}
   16.15  	new->start = start;
   16.16 -	end = new->end = start + num;
   16.17 +	new->end = start + num;
   16.18  
   16.19  	area = PAGE_TO_ADDR(start) >= KMEM_START ? MEM_KERNEL : MEM_USER;
   16.20