diff -u --recursive --new-file v2.1.122/linux/Documentation/sound/AWE32 linux/Documentation/sound/AWE32 --- v2.1.122/linux/Documentation/sound/AWE32 Sun Jul 26 11:57:14 1998 +++ linux/Documentation/sound/AWE32 Fri Sep 18 22:33:55 1998 @@ -51,7 +51,7 @@ but the wavetable needs THREE! My working string is: "(CONFIGURE CTL044/1132685 (LD 2 (IO 0 (BASE 0x0620)) (IO 1 (BASE 0x0A20)) -(IO 3 (BASE 0x0E20)) (ACT Y) ))" +(IO 2 (BASE 0x0E20)) (ACT Y) ))" Resources 0x0620, 0x0A20 and 0x0E20 should work. Other on-board devices: Gameport and StereoEnhance are not required to be inited. diff -u --recursive --new-file v2.1.122/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- v2.1.122/linux/arch/i386/kernel/process.c Thu Sep 17 17:53:34 1998 +++ linux/arch/i386/kernel/process.c Thu Sep 17 17:41:51 1998 @@ -540,10 +540,10 @@ static inline void unlazy_fpu(struct task_struct *tsk) { if (tsk->flags & PF_USEDFPU) { - tsk->flags &= ~PF_USEDFPU; __asm__("fnsave %0":"=m" (tsk->tss.i387)); - stts(); asm volatile("fwait"); + tsk->flags &= ~PF_USEDFPU; + stts(); } } @@ -737,8 +737,11 @@ asm volatile("lldt %0": :"g" (*(unsigned short *)&next->tss.ldt)); /* Re-load page tables */ - if (next->tss.cr3 != prev->tss.cr3) - asm volatile("movl %0,%%cr3": :"r" (next->tss.cr3)); + { + unsigned long new_cr3 = next->tss.cr3; + if (new_cr3 != prev->tss.cr3) + asm volatile("movl %0,%%cr3": :"r" (new_cr3)); + } /* * Restore %fs and %gs. diff -u --recursive --new-file v2.1.122/linux/drivers/char/console.c linux/drivers/char/console.c --- v2.1.122/linux/drivers/char/console.c Thu Aug 6 14:06:31 1998 +++ linux/drivers/char/console.c Thu Sep 17 09:42:28 1998 @@ -47,7 +47,6 @@ * - video_num_columns * - video_num_lines * - video_size_row - * - video_screen_size * - can_do_color * * The abstract console driver provides a generic interface for a text @@ -108,8 +107,6 @@ struct consw *conswitchp = NULL; -static int vesa_blank_mode = 0; /* 0:none 1:suspendV 2:suspendH 3:powerdown */ - /* A bitmap for codes <32. A bit of 1 indicates that the code * corresponding to that bit number invokes some special action * (such as cursor movement) and should not be displayed as a @@ -133,21 +130,26 @@ static struct termios *console_termios_locked[MAX_NR_CONSOLES]; struct vc vc_cons [MAX_NR_CONSOLES]; +static struct consw *con_driver_map[MAX_NR_CONSOLES]; + static int con_open(struct tty_struct *, struct file *); static void vc_init(unsigned int console, unsigned int rows, unsigned int cols, int do_clear); static void blank_screen(void); -static void unblank_screen(void); static void gotoxy(int currcons, int new_x, int new_y); static void save_cur(int currcons); static void reset_terminal(int currcons, int do_clear); static void con_flush_chars(struct tty_struct *tty); +static void set_vesa_blanking(unsigned long arg); +static void set_cursor(int currcons); +static void hide_cursor(int currcons); static int printable = 0; /* Is console ready for printing? */ int do_poke_blanked_console = 0; int console_blanked = 0; +static int vesa_blank_mode = 0; /* 0:none 1:suspendV 2:suspendH 3:powerdown */ static int blankinterval = 10*60*HZ; static int vesa_off_interval = 0; @@ -179,17 +181,16 @@ DECLARE_TASK_QUEUE(con_task_queue); /* + * For the same reason, we defer scrollback to the console_bh. + */ +static int scrollback_delta = 0; + +/* * Low-Level Functions */ #define IS_FG (currcons == fg_console) -#define IS_VISIBLE (*display_fg == vc_cons[currcons].d) - -#ifdef VT_BUF_VRAM_ONLY -#define DO_UPDATE 0 -#else -#define DO_UPDATE IS_VISIBLE -#endif +#define IS_VISIBLE CON_IS_VISIBLE(vc_cons[currcons].d) static inline unsigned short *screenpos(int currcons, int offset, int viewed) { @@ -197,13 +198,10 @@ return p; } -static void scrolldelta(int lines) +static inline void scrolldelta(int lines) { - int currcons = fg_console; - - clear_selection(); - if (vcmode == KD_TEXT) - sw->con_scrolldelta(vc_cons[currcons].d, lines); + scrollback_delta += lines; + mark_bh(CONSOLE_BH); } static void scrup(int currcons, unsigned int t, unsigned int b, int nr) @@ -242,7 +240,6 @@ static void do_update_region(int currcons, unsigned long start, int count) { -#ifndef VT_BUF_VRAM_ONLY unsigned int xx, yy, offset; u16 *p; @@ -279,13 +276,15 @@ xx = 0; yy++; } -#endif } void update_region(int currcons, unsigned long start, int count) { - if (DO_UPDATE) + if (IS_VISIBLE) { + hide_cursor(currcons); do_update_region(currcons, start, count); + set_cursor(currcons); + } } /* Structure of attributes is hardware-dependent */ @@ -295,7 +294,6 @@ if (sw->con_build_attr) return sw->con_build_attr(vc_cons[currcons].d, _color, _intensity, _blink, _underline, _reverse); -#ifndef VT_BUF_VRAM_ONLY /* * ++roman: I completely changed the attribute format for monochrome * mode (!can_do_color). The formerly used MDA (monochrome display @@ -327,9 +325,6 @@ a <<= 1; return a; } -#else - return 0; -#endif } static void update_attr(int currcons) @@ -348,7 +343,6 @@ p = screenpos(currcons, offset, viewed); if (sw->con_invert_region) sw->con_invert_region(vc_cons[currcons].d, p, count); -#ifndef VT_BUF_VRAM_ONLY else { u16 *q = p; int cnt = count; @@ -369,8 +363,8 @@ } } } -#endif - update_region(currcons, (unsigned long) p, count); + if (IS_VISIBLE) + do_update_region(currcons, (unsigned long) p, count); } /* used by selection: complement pointer position */ @@ -382,7 +376,7 @@ if (p) { scr_writew(old, p); - if (DO_UPDATE) + if (IS_VISIBLE) sw->con_putc(vc_cons[currcons].d, old, oldy, oldx); } if (offset == -1) @@ -393,7 +387,7 @@ old = scr_readw(p); new = old ^ complement_mask; scr_writew(new, p); - if (DO_UPDATE) { + if (IS_VISIBLE) { oldx = (offset >> 1) % video_num_columns; oldy = (offset >> 1) / video_num_columns; sw->con_putc(vc_cons[currcons].d, new, oldy, oldx); @@ -410,7 +404,7 @@ scr_writew(scr_readw(p), p + nr); scr_memsetw(q, video_erase_char, nr*2); need_wrap = 0; - if (DO_UPDATE) { + if (IS_VISIBLE) { unsigned short oldattr = attr; sw->con_bmove(vc_cons[currcons].d,y,x,y,x+nr,1, video_num_columns-x-nr); @@ -433,7 +427,7 @@ } scr_memsetw(p, video_erase_char, nr*2); need_wrap = 0; - if (DO_UPDATE) { + if (IS_VISIBLE) { unsigned short oldattr = attr; sw->con_bmove(vc_cons[currcons].d, y, x+nr, y, x, 1, video_num_columns-x-nr); @@ -461,7 +455,7 @@ if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000; if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700; scr_writew(i, (u16 *) pos); - if (DO_UPDATE) + if (IS_VISIBLE) sw->con_putc(vc_cons[currcons].d, i, y, x); } @@ -471,14 +465,14 @@ clear_selection(); if (softcursor_original != -1) { scr_writew(softcursor_original,(u16 *) pos); - if (DO_UPDATE) + if (IS_VISIBLE) sw->con_putc(vc_cons[currcons].d, softcursor_original, y, x); softcursor_original = -1; } sw->con_cursor(vc_cons[currcons].d,CM_ERASE); } -void set_cursor(int currcons) +static void set_cursor(int currcons) { if (!IS_FG || console_blanked || vcmode == KD_GRAPHICS) return; @@ -503,9 +497,8 @@ pos = origin + video_size_row*y + 2*x; } -static inline void save_screen(void) +static inline void save_screen(int currcons) { - int currcons = fg_console; if (sw->con_save_screen) sw->con_save_screen(vc_cons[currcons].d); } @@ -514,45 +507,55 @@ * Redrawing of screen */ -void update_screen(int new_console) +void redraw_screen(int new_console, int is_switch) { - int currcons = fg_console; int redraw = 1; - int old_console; + int currcons, old_console; static int lock = 0; - struct vc_data **display; if (lock) return; if (!vc_cons_allocated(new_console)) { /* strange ... */ - printk("update_screen: tty %d not allocated ??\n", new_console+1); + printk("redraw_screen: tty %d not allocated ??\n", new_console+1); return; } lock = 1; - hide_cursor(currcons); - if (fg_console != new_console) { - display = vc_cons[new_console].d->vc_display_fg; - old_console = (*display) ? (*display)->vc_num : fg_console; - *display = vc_cons[new_console].d; - fg_console = new_console; - currcons = old_console; - if (!IS_VISIBLE) - set_origin(currcons); + if (is_switch) { + currcons = fg_console; + hide_cursor(currcons); + if (fg_console != new_console) { + struct vc_data **display = vc_cons[new_console].d->vc_display_fg; + old_console = (*display) ? (*display)->vc_num : fg_console; + *display = vc_cons[new_console].d; + fg_console = new_console; + currcons = old_console; + if (!IS_VISIBLE) { + save_screen(currcons); + set_origin(currcons); + } + currcons = new_console; + if (old_console == new_console) + redraw = 0; + } + } else { currcons = new_console; - if (old_console == new_console) - redraw = 0; + hide_cursor(currcons); } + if (redraw) { set_origin(currcons); - if (sw->con_switch(vc_cons[currcons].d)) + set_palette(currcons); + if (sw->con_switch(vc_cons[currcons].d) && vcmode != KD_GRAPHICS) /* Update the screen contents */ do_update_region(currcons, origin, screenbuf_size/2); } set_cursor(currcons); - set_leds(); - compute_shiftstate(); + if (is_switch) { + set_leds(); + compute_shiftstate(); + } lock = 0; } @@ -565,27 +568,31 @@ return (i < MAX_NR_CONSOLES && vc_cons[i].d); } -void visual_init(int currcons) +static void visual_init(int currcons, int init) { /* ++Geert: sw->con_init determines console size */ sw = conswitchp; + if (con_driver_map[currcons]) + sw = con_driver_map[currcons]; cons_num = currcons; display_fg = &master_display_fg; vc_cons[currcons].d->vc_uni_pagedir_loc = &vc_cons[currcons].d->vc_uni_pagedir; vc_cons[currcons].d->vc_uni_pagedir = 0; hi_font_mask = 0; complement_mask = 0; - sw->con_init(vc_cons[currcons].d, 1); + can_do_color = 0; + sw->con_init(vc_cons[currcons].d, init); if (!complement_mask) complement_mask = can_do_color ? 0x7700 : 0x0800; + s_complement_mask = complement_mask; video_size_row = video_num_columns<<1; - video_screen_size = video_num_lines*video_size_row; + screenbuf_size = video_num_lines*video_size_row; } -int vc_allocate(unsigned int currcons, int init) /* return 0 on success */ +int vc_allocate(unsigned int currcons) /* return 0 on success */ { if (currcons >= MAX_NR_CONSOLES) - return -ENXIO; + return -ENXIO; if (!vc_cons[currcons].d) { long p, q; @@ -595,7 +602,7 @@ /* due to the granularity of kmalloc, we waste some memory here */ /* the alloc is done in two steps, to optimize the common situation - of a 25x80 console (structsize=216, video_screen_size=4000) */ + of a 25x80 console (structsize=216, screenbuf_size=4000) */ /* although the numbers above are not valid since long ago, the point is still up-to-date and the comment still has its value even if only as a historical artifact. --mj, July 1998 */ @@ -604,22 +611,19 @@ return -ENOMEM; vc_cons[currcons].d = (struct vc_data *)p; vt_cons[currcons] = (struct vt_struct *)(p+sizeof(struct vc_data)); - visual_init(currcons); - q = (long)kmalloc(video_screen_size, GFP_KERNEL); + visual_init(currcons, 1); + if (!*vc_cons[currcons].d->vc_uni_pagedir_loc) + con_set_default_unimap(currcons); + q = (long)kmalloc(screenbuf_size, GFP_KERNEL); if (!q) { kfree_s((char *) p, structsize); vc_cons[currcons].d = NULL; vt_cons[currcons] = NULL; return -ENOMEM; } - con_set_default_unimap(currcons); screenbuf = (unsigned short *) q; kmalloced = 1; - screenbuf_size = video_screen_size; - if (!sw->con_save_screen) - init = 0; /* If console does not have save_screen routine, - we should clear the screen */ - vc_init(currcons, video_num_lines, video_num_columns, !init); + vc_init(currcons, video_num_lines, video_num_columns, 1); } return 0; } @@ -669,12 +673,12 @@ oll = video_num_lines; occ = video_num_columns; osr = video_size_row; - oss = video_screen_size; + oss = screenbuf_size; video_num_lines = ll; video_num_columns = cc; video_size_row = sr; - video_screen_size = ss; + screenbuf_size = ss; rlth = MIN(osr, sr); rrem = sr - rlth; @@ -719,11 +723,10 @@ *cws = ws; } - if (IS_FG && vt_cons[fg_console]->vc_mode == KD_TEXT) - update_screen(fg_console); + if (IS_VISIBLE) + update_screen(currcons); } - set_cursor(fg_console); return 0; } @@ -884,7 +887,7 @@ case 0: /* erase from cursor to end of display */ count = (scr_end-pos)>>1; start = (unsigned short *) pos; - if (DO_UPDATE) { + if (IS_VISIBLE) { /* do in two stages */ sw->con_clear(vc_cons[currcons].d, y, x, 1, video_num_columns-x); @@ -896,7 +899,7 @@ case 1: /* erase from start to cursor */ count = ((pos-origin)>>1)+1; start = (unsigned short *) origin; - if (DO_UPDATE) { + if (IS_VISIBLE) { /* do in two stages */ sw->con_clear(vc_cons[currcons].d, 0, 0, y, video_num_columns); @@ -907,7 +910,7 @@ case 2: /* erase whole display */ count = video_num_columns * video_num_lines; start = (unsigned short *) origin; - if (DO_UPDATE) + if (IS_VISIBLE) sw->con_clear(vc_cons[currcons].d, 0, 0, video_num_lines, video_num_columns); @@ -928,21 +931,21 @@ case 0: /* erase from cursor to end of line */ count = video_num_columns-x; start = (unsigned short *) pos; - if (DO_UPDATE) + if (IS_VISIBLE) sw->con_clear(vc_cons[currcons].d, y, x, 1, video_num_columns-x); break; case 1: /* erase from start of line to cursor */ start = (unsigned short *) (pos - (x<<1)); count = x+1; - if (DO_UPDATE) + if (IS_VISIBLE) sw->con_clear(vc_cons[currcons].d, y, 0, 1, x + 1); break; case 2: /* erase whole line */ start = (unsigned short *) (pos - (x<<1)); count = video_num_columns; - if (DO_UPDATE) + if (IS_VISIBLE) sw->con_clear(vc_cons[currcons].d, y, 0, 1, video_num_columns); break; @@ -962,7 +965,7 @@ count = (vpar > video_num_columns-x) ? (video_num_columns-x) : vpar; scr_memsetw((unsigned short *) pos, video_erase_char, 2 * count); - if (DO_UPDATE) + if (IS_VISIBLE) sw->con_clear(vc_cons[currcons].d, y, x, 1, count); need_wrap = 0; } @@ -1138,7 +1141,7 @@ case 5: /* Inverted screen on/off */ if (decscnm != on_off) { decscnm = on_off; - invert_screen(currcons, 0, video_screen_size, 0); + invert_screen(currcons, 0, screenbuf_size, 0); update_attr(currcons); } break; @@ -1350,6 +1353,7 @@ set_leds(); cursor_type = CUR_DEFAULT; + complement_mask = s_complement_mask; default_attr(currcons); update_attr(currcons); @@ -1487,7 +1491,7 @@ vc_state = ESpalette; return; } else if (c=='R') { /* reset palette */ - reset_palette (currcons); + reset_palette(currcons); vc_state = ESnormal; } else vc_state = ESnormal; @@ -1503,7 +1507,7 @@ palette[i++] += par[j++]; palette[i] = 16*par[j++]; palette[i] += par[j]; - set_palette() ; + set_palette(currcons); vc_state = ESnormal; } } else @@ -1548,6 +1552,16 @@ return; } break; + case 'm': + if (ques) { + clear_selection(); + if (par[0]) + complement_mask = par[0]<<8 | par[1]; + else + complement_mask = s_complement_mask; + return; + } + break; case 'n': if (!ques) { if (par[0] == 5) @@ -1729,14 +1743,10 @@ static int do_con_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { -#ifdef VT_BUF_VRAM_ONLY -#define FLUSH do { } while(0); -#else #define FLUSH if (draw_x >= 0) { \ sw->con_putcs(vc_cons[currcons].d, (u16 *)draw_from, (u16 *)draw_to-(u16 *)draw_from, y, draw_x); \ draw_x = -1; \ } -#endif int c, tc, ok, n = 0, draw_x = -1; unsigned int currcons; @@ -1864,7 +1874,7 @@ ((attr & ~himask) << 8) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : (attr << 8) + tc, (u16 *) pos); - if (DO_UPDATE && draw_x < 0) { + if (IS_VISIBLE && draw_x < 0) { draw_x = x; draw_from = pos; } @@ -1901,7 +1911,6 @@ if (want_console >= 0) { if (want_console != fg_console && vc_cons_allocated(want_console)) { hide_cursor(fg_console); - save_screen(); change_console(want_console); /* we only changed when the console had already been allocated - a new console is not created @@ -1913,6 +1922,13 @@ do_poke_blanked_console = 0; poke_blanked_console(); } + if (scrollback_delta) { + int currcons = fg_console; + clear_selection(); + if (vcmode == KD_TEXT) + sw->con_scrolldelta(vc_cons[currcons].d, scrollback_delta); + scrollback_delta = 0; + } } /* @@ -2015,7 +2031,7 @@ NULL, vt_console_device, keyboard_wait_for_keypress, - do_unblank_screen, + unblank_screen, NULL, CON_PRINTBUFFER, -1, @@ -2045,7 +2061,7 @@ case 3: return paste_selection(tty); case 4: - do_unblank_screen(); + unblank_screen(); return 0; case 5: return sel_loadlut(arg); @@ -2173,7 +2189,7 @@ currcons = MINOR(tty->device) - tty->driver.minor_start; - i = vc_allocate(currcons, 0); + i = vc_allocate(currcons); if (i) return i; @@ -2194,7 +2210,7 @@ video_num_columns = cols; video_num_lines = rows; video_size_row = cols<<1; - video_screen_size = video_num_lines * video_size_row; + screenbuf_size = video_num_lines * video_size_row; set_origin(currcons); pos = origin; @@ -2279,11 +2295,10 @@ kmem_start += sizeof(struct vc_data); vt_cons[currcons] = (struct vt_struct *) kmem_start; kmem_start += sizeof(struct vt_struct); - visual_init(currcons); + visual_init(currcons, 1); screenbuf = (unsigned short *) kmem_start; - kmem_start += video_screen_size; + kmem_start += screenbuf_size; kmalloced = 0; - screenbuf_size = video_screen_size; vc_init(currcons, video_num_lines, video_num_columns, currcons || !sw->con_save_screen); for (j=k=0; j<16; j++) { @@ -2295,11 +2310,10 @@ currcons = fg_console = 0; master_display_fg = vc_cons[currcons].d; set_origin(currcons); - save_screen(); + save_screen(currcons); gotoxy(currcons,x,y); csi_J(currcons, 0); update_screen(fg_console); - set_cursor(currcons); printk("Console: %s %s %dx%d", can_do_color ? "colour" : "mono", display_desc, video_num_columns, video_num_lines); @@ -2315,47 +2329,85 @@ return kmem_start; } +static void clear_buffer_attributes(int currcons) +{ + unsigned short *p = (unsigned short *) origin; + int count = screenbuf_size/2; + int mask = hi_font_mask | 0xff; + + for (; count > 0; count--, p++) { + scr_writew((scr_readw(p)&mask) | (video_erase_char&~mask), p); + } +} + /* * If we support more console drivers, this function is used * when a driver wants to take over some existing consoles * and become default driver for newly opened ones. */ -#ifndef VT_BUF_VRAM_ONLY - void take_over_console(struct consw *csw, int first, int last, int deflt) { - int i; + int i, j = -1; const char *desc; - if (deflt) - conswitchp = csw; desc = csw->con_startup(); if (!desc) return; + if (deflt) + conswitchp = csw; for (i = first; i <= last; i++) { + int old_was_color; + int currcons = i; + + con_driver_map[i] = csw; + if (!vc_cons[i].d || !vc_cons[i].d->vc_sw) continue; - if (i == fg_console && - vc_cons[i].d->vc_sw->con_save_screen) - vc_cons[i].d->vc_sw->con_save_screen(vc_cons[i].d); + + j = i; + if (IS_VISIBLE) + save_screen(i); + old_was_color = vc_cons[i].d->vc_can_do_color; vc_cons[i].d->vc_sw->con_deinit(vc_cons[i].d); - vc_cons[i].d->vc_sw = csw; - vc_cons[i].d->vc_sw->con_init(vc_cons[i].d, 0); - } - printk("Console: switching to %s %s %dx%d\n", - vc_cons[fg_console].d->vc_can_do_color ? "colour" : "mono", - desc, vc_cons[fg_console].d->vc_cols, vc_cons[fg_console].d->vc_rows); - set_palette(); + visual_init(i, 0); + update_attr(i); + + /* If the console changed between mono <-> color, then + * the attributes in the screenbuf will be wrong. The + * following resets all attributes to something sane. + */ + if (old_was_color != vc_cons[i].d->vc_can_do_color) + clear_buffer_attributes(i); + + if (IS_VISIBLE) + update_screen(i); + } + printk("Console: switching "); + if (!deflt) + printk("consoles %d-%d ", first, last); + if (j >= 0) + printk("to %s %s %dx%d\n", + vc_cons[j].d->vc_can_do_color ? "colour" : "mono", + desc, vc_cons[j].d->vc_cols, vc_cons[j].d->vc_rows); + else + printk("to %s\n", desc); } -#endif +void give_up_console(struct consw *csw) +{ + int i; + + for(i = 0; i < MAX_NR_CONSOLES; i++) + if (con_driver_map[i] == csw) + con_driver_map[i] = NULL; +} /* * Screen blanking */ -void set_vesa_blanking(unsigned long arg) +static void set_vesa_blanking(unsigned long arg) { char *argp = (char *)arg + 1; unsigned int mode; @@ -2363,13 +2415,7 @@ vesa_blank_mode = (mode < 4) ? mode : 0; } -void vesa_blank(void) -{ - struct vc_data *c = vc_cons[fg_console].d; - c->vc_sw->con_blank(c, vesa_blank_mode + 1); -} - -void vesa_powerdown(void) +static void vesa_powerdown(void) { struct vc_data *c = vc_cons[fg_console].d; /* @@ -2389,7 +2435,7 @@ } } -void vesa_powerdown_screen(void) +static void vesa_powerdown_screen(void) { timer_active &= ~(1<con_blank(vc_cons[currcons].d, -1); console_blanked = fg_console + 1; set_origin(currcons); @@ -2416,13 +2462,13 @@ } /* don't blank graphics */ - if (vt_cons[fg_console]->vc_mode != KD_TEXT) { + if (vcmode != KD_TEXT) { console_blanked = fg_console + 1; return; } - hide_cursor(fg_console); - if(vesa_off_interval && !nopowersave) { + hide_cursor(currcons); + if (vesa_off_interval) { timer_table[BLANK_TIMER].fn = vesa_powerdown_screen; timer_table[BLANK_TIMER].expires = jiffies + vesa_off_interval; timer_active |= (1<con_blank(vc_cons[currcons].d, 1); console_blanked = fg_console + 1; if (i) set_origin(currcons); - if(!nopowersave) - { #ifdef CONFIG_APM - if (apm_display_blank()) - return; + if (apm_display_blank()) + return; #endif - vesa_blank(); - } + if (vesa_blank_mode) + sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1); } -void do_unblank_screen(void) +void unblank_screen(void) { int currcons; + if (!console_blanked) return; if (!vc_cons_allocated(fg_console)) { @@ -2480,11 +2525,6 @@ do_blank_screen(0); } -static void unblank_screen(void) -{ - do_unblank_screen(); -} - void poke_blanked_console(void) { timer_active &= ~(1<vc_mode != KD_GRAPHICS) - vc_cons[fg_console].d->vc_sw->con_set_palette(vc_cons[fg_console].d, color_table); + if (vcmode != KD_GRAPHICS) + sw->con_set_palette(vc_cons[currcons].d, color_table); } -int set_get_cmap(unsigned char *arg, int set) +static int set_get_cmap(unsigned char *arg, int set) { int i, j, k; @@ -2526,13 +2566,14 @@ } if (set) { for (i = 0; i < MAX_NR_CONSOLES; i++) - if (vc_cons_allocated(i)) + if (vc_cons_allocated(i)) { for (j = k = 0; j < 16; j++) { vc_cons[i].d->vc_palette[k++] = default_red[j]; vc_cons[i].d->vc_palette[k++] = default_grn[j]; vc_cons[i].d->vc_palette[k++] = default_blu[j]; } - set_palette(); + set_palette(i); + } } return 0; } @@ -2542,25 +2583,25 @@ * map, 3 bytes per colour, 16 colours, range from 0 to 255. */ -int con_set_cmap (unsigned char *arg) +int con_set_cmap(unsigned char *arg) { return set_get_cmap (arg,1); } -int con_get_cmap (unsigned char *arg) +int con_get_cmap(unsigned char *arg) { return set_get_cmap (arg,0); } -void reset_palette (int currcons) +void reset_palette(int currcons) { - int j, k ; + int j, k; for (j=k=0; j<16; j++) { palette[k++] = default_red[j]; palette[k++] = default_grn[j]; palette[k++] = default_blu[j]; } - set_palette() ; + set_palette(currcons); } /* @@ -2635,7 +2676,9 @@ } op->data = temp; } + disable_bh(CONSOLE_BH); rc = sw->con_font_op(vc_cons[currcons].d, op); + enable_bh(CONSOLE_BH); op->data = old_op.data; if (!rc && !set) { int c = (op->width+7)/8 * 32 * op->charcount; @@ -2721,7 +2764,7 @@ EXPORT_SYMBOL(default_blu); EXPORT_SYMBOL(video_font_height); EXPORT_SYMBOL(video_scan_lines); +EXPORT_SYMBOL(vc_resize); -#ifndef VT_BUF_VRAM_ONLY EXPORT_SYMBOL(take_over_console); -#endif +EXPORT_SYMBOL(give_up_console); diff -u --recursive --new-file v2.1.122/linux/drivers/char/console_macros.h linux/drivers/char/console_macros.h --- v2.1.122/linux/drivers/char/console_macros.h Sun Jul 26 11:57:15 1998 +++ linux/drivers/char/console_macros.h Thu Sep 17 09:35:03 1998 @@ -26,8 +26,6 @@ #define utf (vc_cons[currcons].d->vc_utf) #define utf_count (vc_cons[currcons].d->vc_utf_count) #define utf_char (vc_cons[currcons].d->vc_utf_char) -#define video_mem_start (vc_cons[currcons].d->vc_video_mem_start) -#define video_mem_end (vc_cons[currcons].d->vc_video_mem_end) #define video_erase_char (vc_cons[currcons].d->vc_video_erase_char) #define disp_ctrl (vc_cons[currcons].d->vc_disp_ctrl) #define toggle_meta (vc_cons[currcons].d->vc_toggle_meta) @@ -64,6 +62,7 @@ #define cursor_type (vc_cons[currcons].d->vc_cursor_type) #define display_fg (vc_cons[currcons].d->vc_display_fg) #define complement_mask (vc_cons[currcons].d->vc_complement_mask) +#define s_complement_mask (vc_cons[currcons].d->vc_s_complement_mask) #define hi_font_mask (vc_cons[currcons].d->vc_hi_font_mask) #define vcmode (vt_cons[currcons]->vc_mode) diff -u --recursive --new-file v2.1.122/linux/drivers/char/consolemap.c linux/drivers/char/consolemap.c --- v2.1.122/linux/drivers/char/consolemap.c Tue Jul 28 14:21:08 1998 +++ linux/drivers/char/consolemap.c Thu Sep 17 09:35:03 1998 @@ -576,6 +576,24 @@ } int +con_copy_unimap(int dstcon, int srccon) +{ + struct vc_data *sconp = vc_cons[srccon].d; + struct vc_data *dconp = vc_cons[dstcon].d; + struct uni_pagedir *q; + + if (!vc_cons_allocated(srccon) || !*sconp->vc_uni_pagedir_loc) + return -EINVAL; + if (*dconp->vc_uni_pagedir_loc == *sconp->vc_uni_pagedir_loc) + return 0; + con_free_unimap(dstcon); + q = (struct uni_pagedir *)*sconp->vc_uni_pagedir_loc; + q->refcount++; + *dconp->vc_uni_pagedir_loc = (long)q; + return 0; +} + +int con_get_unimap(int con, ushort ct, ushort *uct, struct unipair *list) { int i, j, k, ect; diff -u --recursive --new-file v2.1.122/linux/drivers/char/selection.c linux/drivers/char/selection.c --- v2.1.122/linux/drivers/char/selection.c Tue Jul 28 14:21:08 1998 +++ linux/drivers/char/selection.c Thu Sep 17 09:35:03 1998 @@ -123,7 +123,7 @@ int i, ps, pe; unsigned int currcons = fg_console; - do_unblank_screen(); + unblank_screen(); poke_blanked_console(); { unsigned short *args, xs, ys, xe, ye; diff -u --recursive --new-file v2.1.122/linux/drivers/char/sysrq.c linux/drivers/char/sysrq.c --- v2.1.122/linux/drivers/char/sysrq.c Tue Jul 28 14:21:08 1998 +++ linux/drivers/char/sysrq.c Thu Sep 17 09:35:03 1998 @@ -1,6 +1,6 @@ /* -*- linux-c -*- * - * $Id: sysrq.c,v 1.7 1997/11/06 15:57:09 mj Exp $ + * $Id: sysrq.c,v 1.15 1998/08/23 14:56:41 mj Exp $ * * Linux Magic System Request Key Hacks * @@ -70,12 +70,14 @@ printk("Keyboard mode set to XLATE\n"); } break; +#ifdef CONFIG_VT case 'k': /* K -- SAK */ printk("SAK\n"); if (tty) do_SAK(tty); reset_vc(fg_console); break; +#endif case 'b': /* B -- boot immediately */ printk("Resetting\n"); machine_restart(NULL); @@ -131,8 +133,10 @@ default: /* Unknown: help */ if (kbd) printk("unRaw "); +#ifdef CONFIG_VT if (tty) printk("saK "); +#endif printk("Boot " #ifdef CONFIG_APM "Off " diff -u --recursive --new-file v2.1.122/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.1.122/linux/drivers/char/tty_io.c Wed Aug 26 11:37:37 1998 +++ linux/drivers/char/tty_io.c Sat Sep 19 15:13:19 1998 @@ -126,11 +126,11 @@ static unsigned int tty_poll(struct file *, poll_table *); static int tty_open(struct inode *, struct file *); static int tty_release(struct inode *, struct file *); -static int tty_ioctl(struct inode * inode, struct file * file, - unsigned int cmd, unsigned long arg); +int tty_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg); static int tty_fasync(int fd, struct file * filp, int on); #ifdef CONFIG_8xx -extern long console_8xx_init(void); +extern long console_8xx_init(long, long); extern int rs_8xx_init(void); #endif /* CONFIG_8xx */ @@ -640,7 +640,13 @@ size_t count) { ssize_t ret = 0, written = 0; - + struct inode *inode = file->f_dentry->d_inode; + + up(&inode->i_sem); + if (down_interruptible(&inode->i_atomic_write)) { + down(&inode->i_sem); + return -ERESTARTSYS; + } for (;;) { unsigned long size = PAGE_SIZE*2; if (size > count) @@ -663,6 +669,8 @@ file->f_dentry->d_inode->i_mtime = CURRENT_TIME; ret = written; } + up(&inode->i_atomic_write); + down(&inode->i_sem); return ret; } @@ -1604,8 +1612,8 @@ /* * Split this up, as gcc can choke on it otherwise.. */ -static int tty_ioctl(struct inode * inode, struct file * file, - unsigned int cmd, unsigned long arg) +int tty_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg) { struct tty_struct *tty, *real_tty; int retval; @@ -2004,7 +2012,11 @@ kmem_start = con_init(kmem_start); #endif #ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_8xx + kmem_start = console_8xx_init(kmem_start, kmem_end); +#else kmem_start = serial_console_init(kmem_start, kmem_end); +#endif /* CONFIG_8xx */ #endif return kmem_start; } diff -u --recursive --new-file v2.1.122/linux/drivers/char/vt.c linux/drivers/char/vt.c --- v2.1.122/linux/drivers/char/vt.c Thu Aug 6 14:06:31 1998 +++ linux/drivers/char/vt.c Thu Sep 17 09:35:03 1998 @@ -74,45 +74,6 @@ #define GPNUM (GPLAST - GPFIRST + 1) /* - * This function is called when the size of the physical screen has been - * changed. If either the row or col argument is nonzero, set the appropriate - * entry in each winsize structure for all the virtual consoles, then - * send SIGWINCH to all processes with a virtual console as controlling - * tty. - */ - -static int -kd_size_changed(int row, int col) -{ - struct task_struct *p; - int i; - - if ( !row && !col ) return 0; - - for ( i = 0 ; i < MAX_NR_CONSOLES ; i++ ) - { - if ( console_driver.table[i] ) - { - if ( row ) console_driver.table[i]->winsize.ws_row = row; - if ( col ) console_driver.table[i]->winsize.ws_col = col; - } - } - - read_lock(&tasklist_lock); - for_each_task(p) - { - if ( p->tty && MAJOR(p->tty->device) == TTY_MAJOR && - MINOR(p->tty->device) <= MAX_NR_CONSOLES && MINOR(p->tty->device) ) - { - send_sig(SIGWINCH, p, 1); - } - } - read_unlock(&tasklist_lock); - - return 0; -} - -/* * Generates sound of some frequency for some number of clock ticks * * If freq is 0, will turn off sound, else will turn it on for that time. @@ -553,7 +514,7 @@ * explicitly blank/unblank the screen if switching modes */ if (arg == KD_TEXT) - do_unblank_screen(); + unblank_screen(); else do_blank_screen(1); return 0; @@ -781,7 +742,7 @@ if (arg == 0 || arg > MAX_NR_CONSOLES) return -ENXIO; arg--; - i = vc_allocate(arg, 0); + i = vc_allocate(arg); if (i) return i; set_console(arg); @@ -833,7 +794,7 @@ */ int newvt = vt_cons[console]->vt_newvt; vt_cons[console]->vt_newvt = -1; - i = vc_allocate(newvt, 0); + i = vc_allocate(newvt); if (i) return i; /* @@ -893,8 +854,7 @@ return i; __get_user(ll, &vtsizes->v_rows); __get_user(cc, &vtsizes->v_cols); - i = vc_resize_all(ll, cc); - return i ? i : kd_size_changed(ll, cc); + return vc_resize_all(ll, cc); } case VT_RESIZEX: @@ -942,12 +902,7 @@ if ( clin ) video_font_height = clin; - i = vc_resize_all(ll, cc); - if (i) - return i; - - kd_size_changed(ll, cc); - return 0; + return vc_resize_all(ll, cc); } case PIO_FONT: { @@ -1201,7 +1156,7 @@ * unblank the screen later. */ old_vc_mode = vt_cons[fg_console]->vc_mode; - update_screen(new_console); + switch_screen(new_console); /* * If this new console is under process control, send it a signal @@ -1239,14 +1194,10 @@ if (old_vc_mode != vt_cons[new_console]->vc_mode) { if (vt_cons[new_console]->vc_mode == KD_TEXT) - do_unblank_screen(); + unblank_screen(); else do_blank_screen(1); } - - /* Set the colour palette for this VT */ - if (vt_cons[new_console]->vc_mode == KD_TEXT) - set_palette() ; /* * Wake anyone waiting for their VT to activate diff -u --recursive --new-file v2.1.122/linux/drivers/video/vgacon.c linux/drivers/video/vgacon.c --- v2.1.122/linux/drivers/video/vgacon.c Tue Aug 18 22:02:05 1998 +++ linux/drivers/video/vgacon.c Thu Sep 17 09:35:03 1998 @@ -64,8 +64,6 @@ */ #undef TRIDENT_GLITCH -#undef VGA_CAN_DO_64KB - #define dac_reg 0x3c8 #define dac_val 0x3c9 #define attrib_port 0x3c0 @@ -115,6 +113,7 @@ static int vga_is_gfx; static int vga_512_chars; static int vga_video_font_height; +static unsigned int vga_rolled_over = 0; void no_scroll(char *str, int *ints) @@ -190,7 +189,7 @@ display_desc = "*MDA"; request_region(0x3b0,12,"mda"); request_region(0x3bf, 1,"mda"); - vga_video_font_height = 16; + vga_video_font_height = 14; } } else /* If not, it is color. */ @@ -453,9 +452,8 @@ */ vga_video_num_columns = c->vc_cols; vga_video_num_lines = c->vc_rows; - if (vga_is_gfx) - return 1; - scr_memcpyw_to((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf, c->vc_screenbuf_size); + if (!vga_is_gfx) + scr_memcpyw_to((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf, c->vc_screenbuf_size); return 0; /* Redrawing not needed */ } @@ -474,8 +472,7 @@ static int vgacon_set_palette(struct vc_data *c, unsigned char *table) { #ifdef CAN_LOAD_PALETTE - - if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked) + if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked || !CON_IS_VISIBLE(c)) return -EINVAL; vga_set_palette(c, table); return 0; @@ -637,10 +634,11 @@ vga_palette_blanked = 1; return 0; } - scr_memsetw((void *)vga_vram_base, BLANK, vc_cons[0].d->vc_screenbuf_size); + vgacon_set_origin(c); + scr_memsetw((void *)vga_vram_base, BLANK, c->vc_screenbuf_size); return 1; case -1: /* Entering graphic mode */ - scr_memsetw((void *)vga_vram_base, BLANK, vc_cons[0].d->vc_screenbuf_size); + scr_memsetw((void *)vga_vram_base, BLANK, c->vc_screenbuf_size); vga_is_gfx = 1; return 1; default: /* VESA blanking */ @@ -899,14 +897,24 @@ if (!lines) /* Turn scrollback off */ c->vc_visible_origin = c->vc_origin; else { - int p = c->vc_visible_origin - vga_vram_base; - int margin = c->vc_rows/4 * c->vc_size_row; - p += lines * c->vc_size_row; - if (lines < 0 && p < margin) + int vram_size = vga_vram_end - vga_vram_base; + int margin = c->vc_size_row * 4; + int ul, we, p, st; + + if (vga_rolled_over > (c->vc_scr_end - vga_vram_base) + margin) { + ul = c->vc_scr_end - vga_vram_base; + we = vga_rolled_over + c->vc_size_row; + } else { + ul = 0; + we = vram_size; + } + p = (c->vc_visible_origin - vga_vram_base - ul + we) % we + lines * c->vc_size_row; + st = (c->vc_origin - vga_vram_base - ul + we) % we; + if (p < margin) p = 0; - c->vc_visible_origin = p + vga_vram_base; - if (lines > 0 && c->vc_visible_origin > c->vc_origin - margin) - c->vc_visible_origin = c->vc_origin; + if (p > st - margin) + p = st; + c->vc_visible_origin = vga_vram_base + (p + ul) % we; } vga_set_mem_top(c); return 1; @@ -919,6 +927,7 @@ return 0; c->vc_origin = c->vc_visible_origin = vga_vram_base; vga_set_mem_top(c); + vga_rolled_over = 0; return 1; } @@ -935,9 +944,8 @@ c->vc_x = ORIG_X; c->vc_y = ORIG_Y; } - if (vga_is_gfx) - return; - scr_memcpyw_from((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin, c->vc_screenbuf_size); + if (!vga_is_gfx) + scr_memcpyw_from((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin, c->vc_screenbuf_size); } static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, int lines) @@ -962,6 +970,7 @@ (u16 *)(oldo + delta), c->vc_screenbuf_size - delta); c->vc_origin = vga_vram_base; + vga_rolled_over = oldo - vga_vram_base; } else c->vc_origin += delta; scr_memsetw((u16 *)(c->vc_origin + c->vc_screenbuf_size - delta), c->vc_video_erase_char, delta); @@ -971,6 +980,7 @@ (u16 *)oldo, c->vc_screenbuf_size - delta); c->vc_origin = vga_vram_end - c->vc_screenbuf_size; + vga_rolled_over = 0; } else c->vc_origin -= delta; c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size; diff -u --recursive --new-file v2.1.122/linux/fs/affs/symlink.c linux/fs/affs/symlink.c --- v2.1.122/linux/fs/affs/symlink.c Mon Jan 12 14:46:24 1998 +++ linux/fs/affs/symlink.c Sat Sep 19 13:39:45 1998 @@ -20,7 +20,7 @@ #define MIN(a,b) (((a) < (b)) ? (a) : (b)) static int affs_readlink(struct dentry *, char *, int); -static struct dentry *affs_follow_link(struct dentry *dentry, struct dentry *base); +static struct dentry *affs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int); struct inode_operations affs_symlink_inode_operations = { NULL, /* no file-operations */ @@ -98,7 +98,7 @@ } static struct dentry * -affs_follow_link(struct dentry *dentry, struct dentry *base) +affs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow) { struct inode *inode = dentry->d_inode; struct buffer_head *bh; @@ -150,7 +150,7 @@ } buffer[i] = '\0'; affs_brelse(bh); - base = lookup_dentry(buffer,base,1); + base = lookup_dentry(buffer,base,follow); kfree(buffer); return base; } diff -u --recursive --new-file v2.1.122/linux/fs/autofs/symlink.c linux/fs/autofs/symlink.c --- v2.1.122/linux/fs/autofs/symlink.c Sun Jan 4 00:53:43 1998 +++ linux/fs/autofs/symlink.c Sat Sep 19 13:41:02 1998 @@ -27,12 +27,13 @@ } static struct dentry * autofs_follow_link(struct dentry *dentry, - struct dentry *base) + struct dentry *base, + unsigned int follow) { struct autofs_symlink *sl; sl = (struct autofs_symlink *)dentry->d_inode->u.generic_ip; - return lookup_dentry(sl->data, base, 1); + return lookup_dentry(sl->data, base, follow); } struct inode_operations autofs_symlink_inode_operations = { diff -u --recursive --new-file v2.1.122/linux/fs/coda/symlink.c linux/fs/coda/symlink.c --- v2.1.122/linux/fs/coda/symlink.c Thu May 7 22:51:53 1998 +++ linux/fs/coda/symlink.c Sat Sep 19 13:41:28 1998 @@ -26,7 +26,7 @@ #include static int coda_readlink(struct dentry *de, char *buffer, int length); -static struct dentry *coda_follow_link(struct dentry *, struct dentry *); +static struct dentry *coda_follow_link(struct dentry *, struct dentry *, unsigned int); struct inode_operations coda_symlink_inode_operations = { NULL, /* no file-operations */ @@ -86,7 +86,8 @@ } static struct dentry *coda_follow_link(struct dentry *de, - struct dentry *base) + struct dentry *base, + unsigned int follow) { struct inode *inode = de->d_inode; int error; @@ -116,7 +117,7 @@ memcpy(path, mem, len); path[len] = 0; - base = lookup_dentry(path, base, 1); + base = lookup_dentry(path, base, follow); kfree(path); return base; } diff -u --recursive --new-file v2.1.122/linux/fs/ext2/symlink.c linux/fs/ext2/symlink.c --- v2.1.122/linux/fs/ext2/symlink.c Sun Jan 4 00:53:41 1998 +++ linux/fs/ext2/symlink.c Sat Sep 19 13:38:18 1998 @@ -25,7 +25,7 @@ #include static int ext2_readlink (struct dentry *, char *, int); -static struct dentry *ext2_follow_link(struct dentry *, struct dentry *); +static struct dentry *ext2_follow_link(struct dentry *, struct dentry *, unsigned int); /* * symlinks can't do much... @@ -52,7 +52,8 @@ }; static struct dentry * ext2_follow_link(struct dentry * dentry, - struct dentry *base) + struct dentry *base, + unsigned int follow) { struct inode *inode = dentry->d_inode; struct buffer_head * bh = NULL; @@ -68,7 +69,7 @@ link = bh->b_data; } UPDATE_ATIME(inode); - base = lookup_dentry(link, base, 1); + base = lookup_dentry(link, base, follow); if (bh) brelse(bh); return base; diff -u --recursive --new-file v2.1.122/linux/fs/inode.c linux/fs/inode.c --- v2.1.122/linux/fs/inode.c Wed Sep 9 14:51:09 1998 +++ linux/fs/inode.c Sat Sep 19 15:13:19 1998 @@ -131,6 +131,7 @@ INIT_LIST_HEAD(&inode->i_hash); INIT_LIST_HEAD(&inode->i_dentry); sema_init(&inode->i_sem, 1); + sema_init(&inode->i_atomic_write, 1); } static inline void write_inode(struct inode *inode) @@ -714,8 +715,11 @@ printk(KERN_ERR "iput: device %s inode %ld count changed, count=%d\n", kdevname(inode->i_dev), inode->i_ino, inode->i_count); if (atomic_read(&inode->i_sem.count) != 1) -printk(KERN_ERR "iput: Aieee, semaphore in use device %s, count=%d\n", -kdevname(inode->i_dev), atomic_read(&inode->i_sem.count)); +printk(KERN_ERR "iput: Aieee, semaphore in use inode %s/%ld, count=%d\n", +kdevname(inode->i_dev), inode->i_ino, atomic_read(&inode->i_sem.count)); +if (atomic_read(&inode->i_atomic_write.count) != 1) +printk(KERN_ERR "iput: Aieee, atomic write semaphore in use inode %s/%ld, count=%d\n", +kdevname(inode->i_dev), inode->i_ino, atomic_read(&inode->i_sem.count)); #endif } if (inode->i_count > (1<<31)) { diff -u --recursive --new-file v2.1.122/linux/fs/isofs/symlink.c linux/fs/isofs/symlink.c --- v2.1.122/linux/fs/isofs/symlink.c Wed Jun 24 22:54:09 1998 +++ linux/fs/isofs/symlink.c Sat Sep 19 13:42:23 1998 @@ -19,7 +19,7 @@ #include static int isofs_readlink(struct dentry *, char *, int); -static struct dentry * isofs_follow_link(struct dentry *, struct dentry *); +static struct dentry * isofs_follow_link(struct dentry *, struct dentry *, unsigned int); /* * symlinks can't do much... @@ -66,7 +66,8 @@ } static struct dentry * isofs_follow_link(struct dentry * dentry, - struct dentry *base) + struct dentry *base, + unsigned int follow) { char * pnt; @@ -76,7 +77,7 @@ return ERR_PTR(-ELOOP); } - base = lookup_dentry(pnt, base, 1); + base = lookup_dentry(pnt, base, follow); kfree(pnt); return base; diff -u --recursive --new-file v2.1.122/linux/fs/minix/symlink.c linux/fs/minix/symlink.c --- v2.1.122/linux/fs/minix/symlink.c Sun Jan 4 00:53:41 1998 +++ linux/fs/minix/symlink.c Sat Sep 19 13:42:44 1998 @@ -15,7 +15,7 @@ #include static int minix_readlink(struct dentry *, char *, int); -static struct dentry *minix_follow_link(struct dentry *, struct dentry *); +static struct dentry *minix_follow_link(struct dentry *, struct dentry *, unsigned int); /* * symlinks can't do much... @@ -41,7 +41,8 @@ }; static struct dentry * minix_follow_link(struct dentry * dentry, - struct dentry * base) + struct dentry * base, + unsigned int follow) { struct inode *inode = dentry->d_inode; struct buffer_head * bh; @@ -52,7 +53,7 @@ return ERR_PTR(-EIO); } UPDATE_ATIME(inode); - base = lookup_dentry(bh->b_data, base, 1); + base = lookup_dentry(bh->b_data, base, follow); brelse(bh); return base; } diff -u --recursive --new-file v2.1.122/linux/fs/msdos/namei.c linux/fs/msdos/namei.c --- v2.1.122/linux/fs/msdos/namei.c Thu Sep 17 17:53:38 1998 +++ linux/fs/msdos/namei.c Thu Sep 17 09:43:46 1998 @@ -266,6 +266,7 @@ res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &bh, &de, &ino); + if (res == -ENOENT) goto add; if (res < 0) @@ -275,7 +276,7 @@ /* try to get the inode */ res = -EACCES; - inode = iget(dir->i_sb, ino); + inode = iget(sb, ino); if (!inode) goto out; if (!inode->i_sb || @@ -289,9 +290,9 @@ iput(inode); goto out; } - res = 0; add: d_add(dentry, inode); + res = 0; out: return res; } @@ -446,14 +447,14 @@ if (dir->i_dev != inode->i_dev || dir == inode) printk("msdos_rmdir: impossible condition\n"); /* - * Prune any child dentries, then verify that - * the directory is empty and not in use. + * Check whether the directory is empty, then prune + * any child dentries and make sure it's not in use. */ - shrink_dcache_parent(dentry); res = msdos_empty(inode); if (res) goto rmdir_done; res = -EBUSY; + shrink_dcache_parent(dentry); if (dentry->d_count > 1) { #ifdef MSDOS_DEBUG printk("msdos_rmdir: %s/%s busy, d_count=%d\n", @@ -476,6 +477,7 @@ de->name[0] = DELETED_FLAG; fat_mark_buffer_dirty(sb, bh, 1); res = 0; + rmdir_done: fat_brelse(sb, bh); return res; @@ -499,18 +501,21 @@ return res; is_hid = (dentry->d_name.name[0]=='.') && (msdos_name[0]!='.'); fat_lock_creation(); - if (fat_scan(dir,msdos_name,&bh,&de,&ino,SCAN_ANY) >= 0) { - fat_unlock_creation(); - /* N.B. does this need to be released on the other path? */ - fat_brelse(sb, bh); - return -EEXIST; - } + if (fat_scan(dir,msdos_name,&bh,&de,&ino,SCAN_ANY) >= 0) + goto out_exist; + res = msdos_create_entry(dir,msdos_name,1,is_hid, &inode); if (res < 0) goto out_unlock; + dir->i_nlink++; inode->i_nlink = 2; /* no need to mark them dirty */ MSDOS_I(inode)->i_busy = 1; /* prevent lookups */ + /* + * Instantiate the dentry now, in case we need to cleanup. + */ + d_instantiate(dentry, inode); + if ((res = fat_add_cluster(inode)) < 0) goto mkdir_error; if ((res = msdos_create_entry(inode,MSDOS_DOT,1,0,&dot)) < 0) @@ -521,9 +526,9 @@ dot->i_nlink = inode->i_nlink; mark_inode_dirty(dot); iput(dot); + if ((res = msdos_create_entry(inode,MSDOS_DOTDOT,1,0,&dot)) < 0) goto mkdir_error; - fat_unlock_creation(); dot->i_size = dir->i_size; MSDOS_I(dot)->i_start = MSDOS_I(dir)->i_start; MSDOS_I(dot)->i_logstart = MSDOS_I(dir)->i_logstart; @@ -531,15 +536,22 @@ mark_inode_dirty(dot); MSDOS_I(inode)->i_busy = 0; iput(dot); - d_instantiate(dentry, inode); - return 0; + res = 0; -mkdir_error: - if (msdos_rmdir(dir,dentry) < 0) - fat_fs_panic(dir->i_sb,"rmdir in mkdir failed"); out_unlock: fat_unlock_creation(); return res; + +mkdir_error: + printk("msdos_mkdir: error=%d, attempting cleanup\n", res); + if (msdos_rmdir(dir,dentry) < 0) + fat_fs_panic(dir->i_sb,"rmdir in mkdir failed"); + goto out_unlock; + +out_exist: + fat_brelse(sb, bh); + res = -EEXIST; + goto out_unlock; } /***** Unlink a file */ @@ -636,10 +648,14 @@ if ((old_de->attr & ATTR_SYS)) goto out_error; + if (S_ISDIR(new_inode->i_mode)) { + /* make sure it's empty */ + error = msdos_empty(new_inode); + if (error) + goto out_error; #ifdef MSDOS_CHECK_BUSY - /* check for a busy dentry */ - error = -EBUSY; - if (new_dentry->d_count > 1) { + /* check for a busy dentry */ + error = -EBUSY; shrink_dcache_parent(new_dentry); if (new_dentry->d_count > 1) { printk("msdos_rename_same: %s/%s busy, count=%d\n", @@ -647,20 +663,19 @@ new_dentry->d_count); goto out_error; } - } #endif - - if (S_ISDIR(new_inode->i_mode)) { new_dir->i_nlink--; mark_inode_dirty(new_dir); } new_inode->i_nlink = 0; MSDOS_I(new_inode)->i_busy = 1; mark_inode_dirty(new_inode); -#ifdef MSDOS_CHECK_BUSY - /* d_delete the dentry, as we killed its inode */ - d_delete(new_dentry); -#endif + /* + * Make it negative if it's not busy; + * otherwise let d_move() drop it. + */ + if (new_dentry->d_count == 1) + d_delete(new_dentry); new_de->name[0] = DELETED_FLAG; fat_mark_buffer_dirty(sb, new_bh, 1); @@ -763,16 +778,22 @@ } #endif if (S_ISDIR(new_inode->i_mode)) { + /* make sure it's empty */ + error = msdos_empty(new_inode); + if (error) + goto out_new; new_dir->i_nlink--; mark_inode_dirty(new_dir); } new_inode->i_nlink = 0; MSDOS_I(new_inode)->i_busy = 1; mark_inode_dirty(new_inode); -#ifdef MSDOS_CHECK_BUSY - /* d_delete the dentry, as we killed its inode */ - d_delete(new_dentry); -#endif + /* + * Make it negative if it's not busy; + * otherwise let d_move() drop it. + */ + if (new_dentry->d_count == 1) + d_delete(new_dentry); new_de->name[0] = DELETED_FLAG; fat_mark_buffer_dirty(sb, new_bh, 1); fat_brelse(sb, new_bh); @@ -804,12 +825,20 @@ free_inode = iget(sb, free_ino); if (!free_inode) goto out_iput; + /* make sure it's not busy! */ + if (MSDOS_I(free_inode)->i_busy) + printk(KERN_ERR "msdos_rename_diff: new inode %ld busy!\n", + (ino_t) free_ino); + if (!list_empty(&free_inode->i_dentry)) + printk("msdos_rename_diff: free inode has aliases??\n"); msdos_read_inode(free_inode); + fat_mark_buffer_dirty(sb, free_bh, 1); /* * Make sure the old dentry isn't busy, * as we need to change inodes ... */ + error = -EBUSY; if (old_dentry->d_count > 1) { shrink_dcache_parent(old_dentry); if (old_dentry->d_count > 1) { @@ -836,6 +865,11 @@ MSDOS_I(free_inode)->i_logstart = MSDOS_I(old_inode)->i_logstart; MSDOS_I(free_inode)->i_attrs = MSDOS_I(old_inode)->i_attrs; + /* release the old inode's resources */ + MSDOS_I(old_inode)->i_start = 0; + MSDOS_I(old_inode)->i_logstart = 0; + old_inode->i_nlink = 0; + /* * Install the new inode ... */ @@ -845,7 +879,6 @@ mark_inode_dirty(old_inode); old_de->name[0] = DELETED_FLAG; fat_mark_buffer_dirty(sb, old_bh, 1); - fat_mark_buffer_dirty(sb, free_bh, 1); iput(old_inode); /* a directory? */ @@ -854,13 +887,13 @@ MSDOS_I(dotdot_inode)->i_logstart = MSDOS_I(new_dir)->i_logstart; dotdot_de->start = CT_LE_W(MSDOS_I(new_dir)->i_logstart); dotdot_de->starthi = CT_LE_W((MSDOS_I(new_dir)->i_logstart) >> 16); - mark_inode_dirty(dotdot_inode); - fat_mark_buffer_dirty(sb, dotdot_bh, 1); old_dir->i_nlink--; new_dir->i_nlink++; /* no need to mark them dirty */ dotdot_inode->i_nlink = new_dir->i_nlink; + mark_inode_dirty(dotdot_inode); iput(dotdot_inode); + fat_mark_buffer_dirty(sb, dotdot_bh, 1); fat_brelse(sb, dotdot_bh); } diff -u --recursive --new-file v2.1.122/linux/fs/namei.c linux/fs/namei.c --- v2.1.122/linux/fs/namei.c Thu Sep 17 17:53:38 1998 +++ linux/fs/namei.c Sat Sep 19 14:37:45 1998 @@ -280,7 +280,18 @@ return result; } -static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry) +/* + * The bitmask for a follow event: normal + * follow, and follow requires a directory + * entry due to a slash ('/') after the + * name, and whether to continue to parse + * the name.. + */ +#define FOLLOW_LINK (1) +#define FOLLOW_DIRECTORY (2) +#define FOLLOW_CONTINUE (4) + +static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry, unsigned int follow) { struct inode * inode = dentry->d_inode; @@ -290,7 +301,7 @@ current->link_count++; /* This eats the base */ - result = inode->i_op->follow_link(dentry, base); + result = inode->i_op->follow_link(dentry, base, follow); current->link_count--; dput(dentry); return result; @@ -320,9 +331,10 @@ * This is the basic name resolution function, turning a pathname * into the final dentry. */ -struct dentry * lookup_dentry(const char * name, struct dentry * base, int follow_link) +struct dentry * lookup_dentry(const char * name, struct dentry * base, unsigned int follow_link) { struct dentry * dentry; + struct inode *inode; if (*name == '/') { if (base) @@ -338,35 +350,34 @@ if (!*name) goto return_base; + inode = base->d_inode; + follow_link &= FOLLOW_LINK | FOLLOW_DIRECTORY; + /* At this point we know we have a real path component. */ for(;;) { int err; unsigned long hash; struct qstr this; - struct inode *inode; - char c, follow; + unsigned int follow; + unsigned int c; dentry = ERR_PTR(-ENOENT); - inode = base->d_inode; if (!inode) break; - - dentry = ERR_PTR(-ENOTDIR); - if (!inode->i_op || !inode->i_op->lookup) - break; - + err = permission(inode, MAY_EXEC); dentry = ERR_PTR(err); if (err) break; this.name = name; - c = *name; + c = *(const unsigned char *)name; hash = init_name_hash(); do { + name++; hash = partial_name_hash(c, hash); - c = *++name; + c = *(const unsigned char *)name; } while (c && (c != '/')); this.len = name - (const char *) this.name; this.hash = end_name_hash(hash); @@ -374,10 +385,14 @@ /* remove trailing slashes? */ follow = follow_link; if (c) { - follow |= c; + char tmp; + + follow |= FOLLOW_DIRECTORY; do { - c = *++name; - } while (c == '/'); + tmp = *++name; + } while (tmp == '/'); + if (tmp) + follow |= FOLLOW_CONTINUE; } /* @@ -410,8 +425,18 @@ if (!follow) break; - base = do_follow_link(base, dentry); - if (c && !IS_ERR(base)) + base = do_follow_link(base, dentry, follow); + if (IS_ERR(base)) + goto return_base; + + dentry = ERR_PTR(-ENOTDIR); + inode = base->d_inode; + if (follow & FOLLOW_DIRECTORY) { + if (!inode || !inode->i_op || !inode->i_op->lookup) + break; + } + + if (follow & FOLLOW_CONTINUE) continue; return_base: @@ -431,7 +456,7 @@ * namei exists in two versions: namei/lnamei. The only difference is * that namei follows links, while lnamei does not. */ -struct dentry * __namei(const char *pathname, int follow_link) +struct dentry * __namei(const char *pathname, unsigned int follow_link) { char *name; struct dentry *dentry; diff -u --recursive --new-file v2.1.122/linux/fs/nfs/symlink.c linux/fs/nfs/symlink.c --- v2.1.122/linux/fs/nfs/symlink.c Sun Jan 4 00:53:41 1998 +++ linux/fs/nfs/symlink.c Sat Sep 19 13:43:09 1998 @@ -19,7 +19,7 @@ #include static int nfs_readlink(struct dentry *, char *, int); -static struct dentry *nfs_follow_link(struct dentry *, struct dentry *); +static struct dentry *nfs_follow_link(struct dentry *, struct dentry *, unsigned int); /* * symlinks can't do much... @@ -68,7 +68,7 @@ } static struct dentry * -nfs_follow_link(struct dentry * dentry, struct dentry *base) +nfs_follow_link(struct dentry * dentry, struct dentry *base, unsigned int follow) { int error; unsigned int len; @@ -94,7 +94,7 @@ path[len] = 0; kfree(mem); - result = lookup_dentry(path, base, 1); + result = lookup_dentry(path, base, follow); kfree(path); out: return result; diff -u --recursive --new-file v2.1.122/linux/fs/pipe.c linux/fs/pipe.c --- v2.1.122/linux/fs/pipe.c Wed Aug 26 11:37:43 1998 +++ linux/fs/pipe.c Sat Sep 19 15:13:19 1998 @@ -92,7 +92,7 @@ size_t count, loff_t *ppos) { struct inode * inode = filp->f_dentry->d_inode; - ssize_t chars = 0, free = 0, written = 0; + ssize_t chars = 0, free = 0, written = 0, err=0; char *pipebuf; if (ppos != &filp->f_pos) @@ -107,16 +107,26 @@ free = count; else free = 1; /* can't do it atomically, wait for any free space */ + up(&inode->i_sem); + if (down_interruptible(&inode->i_atomic_write)) { + down(&inode->i_sem); + return -ERESTARTSYS; + } while (count>0) { while ((PIPE_FREE(*inode) < free) || PIPE_LOCK(*inode)) { if (!PIPE_READERS(*inode)) { /* no readers */ send_sig(SIGPIPE,current,0); - return written? :-EPIPE; + err = -EPIPE; + goto errout; + } + if (signal_pending(current)) { + err = -ERESTARTSYS; + goto errout; + } + if (filp->f_flags & O_NONBLOCK) { + err = -EAGAIN; + goto errout; } - if (signal_pending(current)) - return written? :-ERESTARTSYS; - if (filp->f_flags & O_NONBLOCK) - return written? :-EAGAIN; interruptible_sleep_on(&PIPE_WAIT(*inode)); } PIPE_LOCK(*inode)++; @@ -139,7 +149,10 @@ } inode->i_ctime = inode->i_mtime = CURRENT_TIME; mark_inode_dirty(inode); - return written; +errout: + up(&inode->i_atomic_write); + down(&inode->i_sem); + return written ? written : err; } static long long pipe_lseek(struct file * file, long long offset, int orig) diff -u --recursive --new-file v2.1.122/linux/fs/proc/link.c linux/fs/proc/link.c --- v2.1.122/linux/fs/proc/link.c Wed Aug 26 11:37:43 1998 +++ linux/fs/proc/link.c Sat Sep 19 15:11:37 1998 @@ -17,7 +17,7 @@ #include static int proc_readlink(struct dentry *, char *, int); -static struct dentry * proc_follow_link(struct dentry *, struct dentry *); +static struct dentry * proc_follow_link(struct dentry *, struct dentry *, unsigned int); /* * links can't do much... @@ -57,7 +57,8 @@ }; static struct dentry * proc_follow_link(struct dentry *dentry, - struct dentry *base) + struct dentry *base, + unsigned int follow) { struct inode *inode = dentry->d_inode; struct task_struct *p; @@ -172,7 +173,7 @@ { int error; - dentry = proc_follow_link(dentry, NULL); + dentry = proc_follow_link(dentry, NULL, 1); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { error = -ENOENT; diff -u --recursive --new-file v2.1.122/linux/fs/proc/proc_devtree.c linux/fs/proc/proc_devtree.c --- v2.1.122/linux/fs/proc/proc_devtree.c Thu Apr 23 20:21:37 1998 +++ linux/fs/proc/proc_devtree.c Sat Sep 19 13:43:36 1998 @@ -42,7 +42,7 @@ */ static int devtree_readlink(struct dentry *, char *, int); -static struct dentry *devtree_follow_link(struct dentry *, struct dentry *); +static struct dentry *devtree_follow_link(struct dentry *, struct dentry *, unsigned int); struct inode_operations devtree_symlink_inode_operations = { NULL, /* no file-operations */ @@ -66,7 +66,8 @@ }; static struct dentry *devtree_follow_link(struct dentry *dentry, - struct dentry *base) + struct dentry *base, + unsigned int follow) { struct inode *inode = dentry->d_inode; struct proc_dir_entry * de; @@ -74,7 +75,7 @@ de = (struct proc_dir_entry *) inode->u.generic_ip; link = (char *) de->data; - return lookup_dentry(link, base, 1); + return lookup_dentry(link, base, follow); } static int devtree_readlink(struct dentry *dentry, char *buffer, int buflen) diff -u --recursive --new-file v2.1.122/linux/fs/proc/root.c linux/fs/proc/root.c --- v2.1.122/linux/fs/proc/root.c Wed Aug 26 11:37:43 1998 +++ linux/fs/proc/root.c Sat Sep 19 13:44:48 1998 @@ -55,9 +55,6 @@ NULL /* can't fsync */ }; -int proc_readlink(struct dentry * dentry, char * buffer, int buflen); -struct dentry * proc_follow_link(struct dentry *dentry, struct dentry *base); - /* * proc directories can do almost nothing.. */ @@ -388,12 +385,13 @@ } static struct dentry * proc_self_follow_link(struct dentry *dentry, - struct dentry *base) + struct dentry *base, + unsigned int follow) { char tmp[30]; sprintf(tmp, "%d", current->pid); - return lookup_dentry(tmp, base, 1); + return lookup_dentry(tmp, base, follow); } int proc_readlink(struct dentry * dentry, char * buffer, int buflen) @@ -420,7 +418,7 @@ return len; } -struct dentry * proc_follow_link(struct dentry * dentry, struct dentry *base) +struct dentry * proc_follow_link(struct dentry * dentry, struct dentry *base, unsigned int follow) { struct inode *inode = dentry->d_inode; struct proc_dir_entry * de; @@ -435,7 +433,7 @@ if (de->readlink_proc) len = de->readlink_proc(de, page); - d = lookup_dentry(page, base, 1); + d = lookup_dentry(page, base, follow); free_page((unsigned long) page); return d; } diff -u --recursive --new-file v2.1.122/linux/fs/romfs/inode.c linux/fs/romfs/inode.c --- v2.1.122/linux/fs/romfs/inode.c Thu Aug 27 19:56:30 1998 +++ linux/fs/romfs/inode.c Sat Sep 19 13:45:18 1998 @@ -451,7 +451,8 @@ } static struct dentry *romfs_follow_link(struct dentry *dentry, - struct dentry *base) + struct dentry *base, + unsigned int follow) { struct inode *inode = dentry->d_inode; char *link; @@ -470,7 +471,7 @@ } else link[len] = 0; - dentry = lookup_dentry(link, base, 1); + dentry = lookup_dentry(link, base, follow); kfree(link); if (0) { diff -u --recursive --new-file v2.1.122/linux/fs/sysv/symlink.c linux/fs/sysv/symlink.c --- v2.1.122/linux/fs/sysv/symlink.c Sun Jan 4 00:53:41 1998 +++ linux/fs/sysv/symlink.c Sat Sep 19 13:45:42 1998 @@ -21,7 +21,7 @@ #include static int sysv_readlink(struct dentry *, char *, int); -static struct dentry *sysv_follow_link(struct dentry *, struct dentry *); +static struct dentry *sysv_follow_link(struct dentry *, struct dentry *, unsigned int); /* * symlinks can't do much... @@ -47,7 +47,8 @@ }; static struct dentry *sysv_follow_link(struct dentry * dentry, - struct dentry * base) + struct dentry * base, + unsigned int follow) { struct inode *inode = dentry->d_inode; struct buffer_head * bh; @@ -58,7 +59,7 @@ return ERR_PTR(-EIO); } UPDATE_ATIME(inode); - base = lookup_dentry(bh->b_data, base, 1); + base = lookup_dentry(bh->b_data, base, follow); brelse(bh); return base; } diff -u --recursive --new-file v2.1.122/linux/fs/ufs/symlink.c linux/fs/ufs/symlink.c --- v2.1.122/linux/fs/ufs/symlink.c Sat Sep 5 16:46:41 1998 +++ linux/fs/ufs/symlink.c Sat Sep 19 13:46:01 1998 @@ -43,7 +43,7 @@ static struct dentry * ufs_follow_link(struct dentry * dentry, - struct dentry * base) + struct dentry * base, unsigned int follow) { struct inode * inode; struct buffer_head * bh; @@ -67,7 +67,7 @@ link = (char *) inode->u.ufs_i.i_u1.i_symlink; } UPDATE_ATIME(inode); - base = lookup_dentry(link, base, 1); + base = lookup_dentry(link, base, follow); if (bh) brelse(bh); UFSD(("EXIT\n")) diff -u --recursive --new-file v2.1.122/linux/fs/umsdos/symlink.c linux/fs/umsdos/symlink.c --- v2.1.122/linux/fs/umsdos/symlink.c Thu Sep 17 17:53:38 1998 +++ linux/fs/umsdos/symlink.c Sat Sep 19 13:46:28 1998 @@ -64,7 +64,8 @@ /* this one mostly stolen from romfs :) */ static struct dentry *UMSDOS_followlink (struct dentry *dentry, - struct dentry *base) + struct dentry *base, + unsigned int follow) { struct inode *inode = dentry->d_inode; char *symname; @@ -91,7 +92,7 @@ } symname[len] = 0; - dentry = lookup_dentry (symname, base, 1); + dentry = lookup_dentry (symname, base, follow); kfree (symname); if (0) { diff -u --recursive --new-file v2.1.122/linux/include/linux/console.h linux/include/linux/console.h --- v2.1.122/linux/include/linux/console.h Sun Jul 26 11:57:19 1998 +++ linux/include/linux/console.h Thu Sep 17 09:35:03 1998 @@ -53,15 +53,11 @@ extern struct consw prom_con; /* SPARC PROM console */ void take_over_console(struct consw *sw, int first, int last, int deflt); - -/* flag bits */ -#define CON_INITED (1) +void give_up_console(struct consw *sw); /* scroll */ #define SM_UP (1) #define SM_DOWN (2) -#define SM_LEFT (3) -#define SM_RIGHT (4) /* cursor */ #define CM_DRAW (1) diff -u --recursive --new-file v2.1.122/linux/include/linux/console_struct.h linux/include/linux/console_struct.h --- v2.1.122/linux/include/linux/console_struct.h Thu Aug 6 14:06:34 1998 +++ linux/include/linux/console_struct.h Thu Sep 17 09:35:04 1998 @@ -19,7 +19,6 @@ struct consw *vc_sw; unsigned short *vc_screenbuf; /* In-memory character/attribute buffer */ unsigned int vc_screenbuf_size; - unsigned short vc_video_erase_char; /* Background erase character */ unsigned char vc_attr; /* Current attributes */ unsigned char vc_def_color; /* Default colors */ unsigned char vc_color; /* Foreground & background */ @@ -28,6 +27,8 @@ unsigned char vc_halfcolor; /* Color for half intensity mode */ unsigned short vc_complement_mask; /* [#] Xor mask for mouse pointer */ unsigned short vc_hi_font_mask; /* [#] Attribute set for upper 256 chars of font or 0 if not supported */ + unsigned short vc_video_erase_char; /* Background erase character */ + unsigned short vc_s_complement_mask; /* Saved mouse pointer mask */ unsigned int vc_x, vc_y; /* Cursor position */ unsigned int vc_top, vc_bottom; /* Scrolling region */ unsigned int vc_state; /* Escape sequence parser state */ @@ -104,3 +105,5 @@ #define CUR_SWMASK 0xfff0 #define CUR_DEFAULT CUR_UNDERLINE + +#define CON_IS_VISIBLE(conp) (*conp->vc_display_fg == conp) diff -u --recursive --new-file v2.1.122/linux/include/linux/dcache.h linux/include/linux/dcache.h --- v2.1.122/linux/include/linux/dcache.h Tue Aug 18 22:02:07 1998 +++ linux/include/linux/dcache.h Sat Sep 19 14:27:29 1998 @@ -27,7 +27,7 @@ #define init_name_hash() 0 /* partial hash update function. Assume roughly 4 bits per character */ -static __inline__ unsigned long partial_name_hash(unsigned char c, unsigned long prevhash) +static __inline__ unsigned long partial_name_hash(unsigned long c, unsigned long prevhash) { prevhash = (prevhash << 4) | (prevhash >> (8*sizeof(unsigned long)-4)); return prevhash ^ c; diff -u --recursive --new-file v2.1.122/linux/include/linux/fs.h linux/include/linux/fs.h --- v2.1.122/linux/include/linux/fs.h Sat Sep 5 16:46:41 1998 +++ linux/include/linux/fs.h Sat Sep 19 15:13:19 1998 @@ -348,6 +348,7 @@ unsigned long i_version; unsigned long i_nrpages; struct semaphore i_sem; + struct semaphore i_atomic_write; struct inode_operations *i_op; struct super_block *i_sb; struct wait_queue *i_wait; @@ -622,7 +623,7 @@ int (*rename) (struct inode *, struct dentry *, struct inode *, struct dentry *); int (*readlink) (struct dentry *, char *,int); - struct dentry * (*follow_link) (struct dentry *, struct dentry *); + struct dentry * (*follow_link) (struct dentry *, struct dentry *, unsigned int); int (*readpage) (struct file *, struct page *); int (*writepage) (struct file *, struct page *); int (*bmap) (struct inode *,int); @@ -783,8 +784,8 @@ #define PTR_ERR(ptr) ((long)(ptr)) #define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000)) -extern struct dentry * lookup_dentry(const char *, struct dentry *, int); -extern struct dentry * __namei(const char *, int); +extern struct dentry * lookup_dentry(const char *, struct dentry *, unsigned int); +extern struct dentry * __namei(const char *, unsigned int); #define namei(pathname) __namei(pathname, 1) #define lnamei(pathname) __namei(pathname, 0) diff -u --recursive --new-file v2.1.122/linux/include/linux/nbd.h linux/include/linux/nbd.h --- v2.1.122/linux/include/linux/nbd.h Sat Sep 5 16:46:41 1998 +++ linux/include/linux/nbd.h Thu Sep 17 09:16:28 1998 @@ -35,7 +35,6 @@ } #define MAX_NBD 128 -#endif struct nbd_device { int refcnt; @@ -51,6 +50,7 @@ struct request *tail; struct semaphore queue_lock; }; +#endif /* This now IS in some kind of include file... */ diff -u --recursive --new-file v2.1.122/linux/include/linux/selection.h linux/include/linux/selection.h --- v2.1.122/linux/include/linux/selection.h Fri Jul 31 17:07:03 1998 +++ linux/include/linux/selection.h Thu Sep 17 18:01:48 1998 @@ -21,7 +21,6 @@ #define video_num_columns (vc_cons[currcons].d->vc_cols) #define video_num_lines (vc_cons[currcons].d->vc_rows) #define video_size_row (vc_cons[currcons].d->vc_size_row) -#define video_screen_size (vc_cons[currcons].d->vc_screenbuf_size) #define can_do_color (vc_cons[currcons].d->vc_can_do_color) extern int console_blanked; @@ -31,7 +30,6 @@ extern int default_grn[]; extern int default_blu[]; -extern void do_unblank_screen(void); extern unsigned short *screen_pos(int currcons, int w_offset, int viewed); extern u16 screen_glyph(int currcons, int offset); extern void complement_pos(int currcons, int offset); diff -u --recursive --new-file v2.1.122/linux/include/linux/tty.h linux/include/linux/tty.h --- v2.1.122/linux/include/linux/tty.h Thu Aug 6 14:06:34 1998 +++ linux/include/linux/tty.h Thu Sep 17 18:04:56 1998 @@ -9,7 +9,7 @@ * These constants are also useful for user-level apps (e.g., VC * resizing). */ -#define MIN_NR_CONSOLES 1 /* must be at least 1 */ +#define MIN_NR_CONSOLES 1 /* must be at least 1 */ #define MAX_NR_CONSOLES 63 /* serial lines start at 64 */ #define MAX_NR_USER_CONSOLES 63 /* must be root to allocate above this */ /* Note: the ioctl VT_GETSTATE does not work for @@ -87,7 +87,10 @@ unsigned char blue_pos; /* 0x2b */ unsigned char rsvd_size; /* 0x2c */ unsigned char rsvd_pos; /* 0x2d */ - /* 0x2e -- 0x3f reserved for future expansion */ + unsigned short vesapm_seg; /* 0x2e */ + unsigned short vesapm_off; /* 0x30 */ + unsigned short pages; /* 0x32 */ + /* 0x34 -- 0x3f reserved for future expansion */ }; extern struct screen_info screen_info; @@ -389,10 +392,6 @@ /* pcxx.c */ extern int pcxe_open(struct tty_struct *tty, struct file *filp); - -/* console.c */ - -extern void update_screen(int new_console); /* printk.c */ diff -u --recursive --new-file v2.1.122/linux/include/linux/vt_buffer.h linux/include/linux/vt_buffer.h --- v2.1.122/linux/include/linux/vt_buffer.h Fri Jul 31 17:07:03 1998 +++ linux/include/linux/vt_buffer.h Thu Sep 17 18:01:47 1998 @@ -16,9 +16,6 @@ #include #ifdef CONFIG_VGA_CONSOLE -#if !defined(CONFIG_FB) && !defined(CONFIG_FB_MODULE) -#define VT_BUF_VRAM_ONLY -#endif #include #endif diff -u --recursive --new-file v2.1.122/linux/include/linux/vt_kern.h linux/include/linux/vt_kern.h --- v2.1.122/linux/include/linux/vt_kern.h Fri Jul 31 17:07:03 1998 +++ linux/include/linux/vt_kern.h Thu Sep 17 18:01:47 1998 @@ -35,27 +35,29 @@ /* console.c */ struct console_font_op; +struct consw; -int vc_allocate(unsigned int console, int init); +int vc_allocate(unsigned int console); int vc_cons_allocated(unsigned int console); int vc_resize(unsigned int lines, unsigned int cols, unsigned int first, unsigned int last); #define vc_resize_all(l, c) vc_resize(l, c, 0, MAX_NR_CONSOLES-1) #define vc_resize_con(l, c, x) vc_resize(l, c, x, x) void vc_disallocate(unsigned int console); -void poke_blanked_console(void); -void set_vesa_blanking(unsigned long arg); -void vesa_blank(void); -void vesa_powerdown(void); void reset_palette(int currcons); -void set_palette(void); -void do_blank_screen(int nopowersave); +void set_palette(int currcons); +void do_blank_screen(int gfx_mode); +void unblank_screen(void); +void poke_blanked_console(void); int con_font_op(int currcons, struct console_font_op *op); int con_set_cmap(unsigned char *cmap); int con_get_cmap(unsigned char *cmap); void scrollback(int); void scrollfront(int); void update_region(int currcons, unsigned long start, int count); +void redraw_screen(int new_console, int is_switch); +#define update_screen(x) redraw_screen(x, 0) +#define switch_screen(x) redraw_screen(x, 1) struct tty_struct; int tioclinux(struct tty_struct *tty, unsigned long arg); @@ -75,6 +77,7 @@ int con_set_default_unimap(int currcons); void con_free_unimap(int currcons); void con_protect_unimap(int currcons, int rdonly); +int con_copy_unimap(int dstcons, int srccons); /* vt.c */ diff -u --recursive --new-file v2.1.122/linux/init/main.c linux/init/main.c --- v2.1.122/linux/init/main.c Thu Sep 17 17:53:39 1998 +++ linux/init/main.c Thu Sep 17 15:09:32 1998 @@ -77,7 +77,7 @@ extern void sock_init(void); extern void uidcache_init(void); extern void mca_init(void); -extern long sbus_init(long, long); +extern long sbus_init(void); extern long powermac_init(unsigned long, unsigned long); extern void sysctl_init(void); extern void filescache_init(void); diff -u --recursive --new-file v2.1.122/linux/kernel/exit.c linux/kernel/exit.c --- v2.1.122/linux/kernel/exit.c Thu Sep 17 17:53:39 1998 +++ linux/kernel/exit.c Sat Sep 19 10:43:51 1998 @@ -415,15 +415,6 @@ struct wait_queue wait = { current, NULL }; struct task_struct *p; - if (stat_addr) { - if(verify_area(VERIFY_WRITE, stat_addr, sizeof(*stat_addr))) - return -EFAULT; - } - if (ru) { - if(verify_area(VERIFY_WRITE, ru, sizeof(*ru))) - return -EFAULT; - } - if (options & ~(WNOHANG|WUNTRACED|__WCLONE)) return -EINVAL; @@ -453,21 +444,23 @@ if (!(options & WUNTRACED) && !(p->flags & PF_PTRACED)) continue; read_unlock(&tasklist_lock); - if (ru != NULL) - getrusage(p, RUSAGE_BOTH, ru); - if (stat_addr) - __put_user((p->exit_code << 8) | 0x7f, stat_addr); - p->exit_code = 0; - retval = p->pid; + retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0; + if (!retval && stat_addr) + retval = put_user((p->exit_code << 8) | 0x7f, stat_addr); + if (!retval) { + p->exit_code = 0; + retval = p->pid; + } goto end_wait4; case TASK_ZOMBIE: current->times.tms_cutime += p->times.tms_utime + p->times.tms_cutime; current->times.tms_cstime += p->times.tms_stime + p->times.tms_cstime; read_unlock(&tasklist_lock); - if (ru != NULL) - getrusage(p, RUSAGE_BOTH, ru); - if (stat_addr) - __put_user(p->exit_code, stat_addr); + retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0; + if (!retval && stat_addr) + retval = put_user(p->exit_code, stat_addr); + if (retval) + goto end_wait4; retval = p->pid; if (p->p_opptr != p->p_pptr) { write_lock_irq(&tasklist_lock);