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