Commit 20fca9a1 authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.123pre1

parent f85f3898
......@@ -51,7 +51,7 @@ Then WaveTable goes. For some reason Plug-n-Play detects only one I/O port,
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.
......
......@@ -540,10 +540,10 @@ void release_thread(struct task_struct *dead_task)
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 @@ void __switch_to(struct task_struct *prev, struct task_struct *next)
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.
......
......@@ -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[MAX_NR_CONSOLES];
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;
......@@ -178,18 +180,17 @@ static struct vc_data *master_display_fg = NULL;
*/
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 @@ static inline unsigned short *screenpos(int currcons, int offset, int viewed)
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 @@ scrdown(int currcons, unsigned int t, unsigned int b, int nr)
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 @@ static void do_update_region(int currcons, unsigned long start, int count)
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 @@ static u8 build_attr(int currcons, u8 _color, u8 _intensity, u8 _blink, u8 _unde
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 @@ static u8 build_attr(int currcons, u8 _color, u8 _intensity, u8 _blink, u8 _unde
a <<= 1;
return a;
}
#else
return 0;
#endif
}
static void update_attr(int currcons)
......@@ -348,7 +343,6 @@ void invert_screen(int currcons, int offset, int count, int viewed)
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 @@ void invert_screen(int currcons, int offset, int count, int viewed)
}
}
}
#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 @@ void complement_pos(int currcons, int offset)
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 @@ void complement_pos(int currcons, int offset)
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 @@ static void insert_char(int currcons, unsigned int nr)
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 @@ static void delete_char(int currcons, unsigned int nr)
}
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 @@ static void add_softcursor(int currcons)
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 @@ static void hide_cursor(int currcons)
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 @@ static void set_origin(int currcons)
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 @@ static inline void save_screen(void)
* 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 @@ int vc_cons_allocated(unsigned int i)
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 @@ int vc_allocate(unsigned int currcons, int init) /* return 0 on success */
/* 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 @@ int vc_allocate(unsigned int currcons, int init) /* return 0 on success */
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 @@ int vc_resize(unsigned int lines, unsigned int cols,
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 @@ int vc_resize(unsigned int lines, unsigned int cols,
*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 @@ static void csi_J(int currcons, int vpar)
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 @@ static void csi_J(int currcons, int vpar)
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 @@ static void csi_J(int currcons, int vpar)
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 @@ static void csi_K(int currcons, int vpar)
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 @@ static void csi_X(int currcons, int vpar) /* erase the following vpar positions
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 @@ static void set_mode(int currcons, int on_off)
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 @@ static void reset_terminal(int currcons, int do_clear)
set_leds();
cursor_type = CUR_DEFAULT;
complement_mask = s_complement_mask;
default_attr(currcons);
update_attr(currcons);
......@@ -1487,7 +1491,7 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
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 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
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 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
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 void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
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 @@ static int do_con_write(struct tty_struct * tty, int from_user,
((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 @@ static void console_bh(void)
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 @@ static void console_bh(void)
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 @@ struct console vt_console_driver = {
NULL,
vt_console_device,
keyboard_wait_for_keypress,
do_unblank_screen,
unblank_screen,
NULL,
CON_PRINTBUFFER,
-1,
......@@ -2045,7 +2061,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
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 @@ static int con_open(struct tty_struct *tty, struct file * filp)
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 @@ static void vc_init(unsigned int currcons, unsigned int rows, unsigned int cols,
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 @@ __initfunc(unsigned long con_init(unsigned long kmem_start))
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 @@ __initfunc(unsigned long con_init(unsigned long kmem_start))
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 @@ __initfunc(unsigned long con_init(unsigned long kmem_start))
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 @@ void set_vesa_blanking(unsigned long arg)
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(void)
}
}
void vesa_powerdown_screen(void)
static void vesa_powerdown_screen(void)
{
timer_active &= ~(1<<BLANK_TIMER);
timer_table[BLANK_TIMER].fn = unblank_screen;
......@@ -2397,7 +2443,7 @@ void vesa_powerdown_screen(void)
vesa_powerdown();
}
void do_blank_screen(int nopowersave)
void do_blank_screen(int entering_gfx)
{
int currcons = fg_console;
int i;
......@@ -2406,9 +2452,9 @@ void do_blank_screen(int nopowersave)
return;
/* entering graphics mode? */
if (nopowersave) {
if (entering_gfx) {
hide_cursor(currcons);
save_screen();
save_screen(currcons);
sw->con_blank(vc_cons[currcons].d, -1);
console_blanked = fg_console + 1;
set_origin(currcons);
......@@ -2416,13 +2462,13 @@ void do_blank_screen(int nopowersave)
}
/* 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<<BLANK_TIMER);
......@@ -2431,26 +2477,25 @@ void do_blank_screen(int nopowersave)
timer_table[BLANK_TIMER].fn = unblank_screen;
}
save_screen();
save_screen(currcons);
/* In case we need to reset origin, blanking hook returns 1 */
i = sw->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 @@ static void blank_screen(void)
do_blank_screen(0);
}
static void unblank_screen(void)
{
do_unblank_screen();
}
void poke_blanked_console(void)
{
timer_active &= ~(1<<BLANK_TIMER);
......@@ -2504,13 +2544,13 @@ void poke_blanked_console(void)
* Palettes
*/
void set_palette(void)
void set_palette(int currcons)
{
if (vt_cons[fg_console]->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 @@ int set_get_cmap(unsigned char *arg, int set)
}
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 @@ int set_get_cmap(unsigned char *arg, int set)
* 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 @@ int con_font_op(int currcons, struct console_font_op *op)
}
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_grn);
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);
......@@ -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)
......
......@@ -575,6 +575,24 @@ con_set_default_unimap(int con)
return err;
}
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)
{
......
......@@ -123,7 +123,7 @@ int set_selection(const unsigned long arg, struct tty_struct *tty, int user)
int i, ps, pe;
unsigned int currcons = fg_console;
do_unblank_screen();
unblank_screen();
poke_blanked_console();
{ unsigned short *args, xs, ys, xe, ye;
......
/* -*- 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 @@ void handle_sysrq(int key, struct pt_regs *pt_regs,
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 @@ void handle_sysrq(int key, struct pt_regs *pt_regs,
default: /* Unknown: help */
if (kbd)
printk("unRaw ");
#ifdef CONFIG_VT
if (tty)
printk("saK ");
#endif
printk("Boot "
#ifdef CONFIG_APM
"Off "
......
......@@ -126,11 +126,11 @@ static ssize_t tty_write(struct file *, const char *, size_t, loff_t *);
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 @@ static inline ssize_t do_tty_write(
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 @@ static inline ssize_t do_tty_write(
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 @@ static int send_break(struct tty_struct *tty, int duration)
/*
* 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 @@ long __init console_init(long kmem_start, long kmem_end)
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;
}
......
......@@ -73,45 +73,6 @@ unsigned int video_scan_lines;
#define GPLAST 0x3df
#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
*
......@@ -553,7 +514,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
* 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 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
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 vt_ioctl(struct tty_struct *tty, struct file * file,
*/
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 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
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 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
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 @@ void complete_change_console(unsigned int new_console)
* 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,15 +1194,11 @@ void complete_change_console(unsigned int new_console)
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
*/
......
......@@ -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_palette_blanked;
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 @@ __initfunc(static const char *vgacon_startup(void))
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 @@ static int vgacon_switch(struct vc_data *c)
*/
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 void vga_set_palette(struct vc_data *c, unsigned char *table)
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 @@ static int vgacon_blank(struct vc_data *c, int blank)
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 @@ static int vgacon_scrolldelta(struct vc_data *c, int lines)
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 @@ static int vgacon_set_origin(struct vc_data *c)
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 @@ static void vgacon_save_screen(struct vc_data *c)
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 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
(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 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
(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;
......
......@@ -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 @@ affs_readlink(struct dentry *dentry, char *buffer, int buflen)
}
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 @@ affs_follow_link(struct dentry *dentry, struct dentry *base)
}
buffer[i] = '\0';
affs_brelse(bh);
base = lookup_dentry(buffer,base,1);
base = lookup_dentry(buffer,base,follow);
kfree(buffer);
return base;
}
......
......@@ -27,12 +27,13 @@ static int autofs_readlink(struct dentry *dentry, char *buffer, int buflen)
}
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 = {
......
......@@ -26,7 +26,7 @@
#include <linux/coda_proc.h>
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 int coda_readlink(struct dentry *de, char *buffer, int length)
}
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 @@ static struct dentry *coda_follow_link(struct dentry *de,
memcpy(path, mem, len);
path[len] = 0;
base = lookup_dentry(path, base, 1);
base = lookup_dentry(path, base, follow);
kfree(path);
return base;
}
......@@ -25,7 +25,7 @@
#include <linux/stat.h>
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 @@ struct inode_operations ext2_symlink_inode_operations = {
};
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 @@ static struct dentry * ext2_follow_link(struct dentry * dentry,
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;
......
......@@ -131,6 +131,7 @@ static inline void init_once(struct inode * inode)
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 @@ if (inode->i_count)
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)) {
......
......@@ -19,7 +19,7 @@
#include <asm/uaccess.h>
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 int isofs_readlink(struct dentry * dentry, char * buffer, int buflen)
}
static struct dentry * isofs_follow_link(struct dentry * dentry,
struct dentry *base)
struct dentry *base,
unsigned int follow)
{
char * pnt;
......@@ -76,7 +77,7 @@ static struct dentry * isofs_follow_link(struct dentry * dentry,
return ERR_PTR(-ELOOP);
}
base = lookup_dentry(pnt, base, 1);
base = lookup_dentry(pnt, base, follow);
kfree(pnt);
return base;
......
......@@ -15,7 +15,7 @@
#include <asm/uaccess.h>
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 @@ struct inode_operations minix_symlink_inode_operations = {
};
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 @@ static struct dentry * minix_follow_link(struct dentry * dentry,
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;
}
......
......@@ -266,6 +266,7 @@ int msdos_lookup(struct inode *dir,struct dentry *dentry)
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 @@ int msdos_lookup(struct inode *dir,struct dentry *dentry)
/* 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 @@ int msdos_lookup(struct inode *dir,struct dentry *dentry)
iput(inode);
goto out;
}
res = 0;
add:
d_add(dentry, inode);
res = 0;
out:
return res;
}
......@@ -446,14 +447,14 @@ int msdos_rmdir(struct inode *dir, struct dentry *dentry)
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 @@ dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count);
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 @@ int msdos_mkdir(struct inode *dir,struct dentry *dentry,int mode)
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 @@ int msdos_mkdir(struct inode *dir,struct dentry *dentry,int mode)
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 @@ int msdos_mkdir(struct inode *dir,struct dentry *dentry,int mode)
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 @@ static int msdos_rename_same(struct inode *old_dir,char *old_name,
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_parent->d_name.name, new_dentry->d_name.name,
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 @@ new_dentry->d_count);
}
#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 @@ new_dentry->d_count);
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 @@ old_dentry->d_count);
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 @@ old_dentry->d_count);
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 @@ old_dentry->d_count);
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);
}
......
......@@ -280,7 +280,18 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name)
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 @@ static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry
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 @@ static inline struct dentry * follow_mount(struct dentry * dentry)
* 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 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo
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 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo
/* 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 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo
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 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo
* 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;
......
......@@ -19,7 +19,7 @@
#include <asm/uaccess.h>
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 int nfs_readlink(struct dentry *dentry, char *buffer, int buflen)
}
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 @@ nfs_follow_link(struct dentry * dentry, struct dentry *base)
path[len] = 0;
kfree(mem);
result = lookup_dentry(path, base, 1);
result = lookup_dentry(path, base, follow);
kfree(path);
out:
return result;
......
......@@ -92,7 +92,7 @@ static ssize_t pipe_write(struct file * filp, const char * buf,
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 @@ static ssize_t pipe_write(struct file * filp, const char * buf,
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 @@ static ssize_t pipe_write(struct file * filp, const char * buf,
}
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)
......
......@@ -17,7 +17,7 @@
#include <linux/stat.h>
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 @@ struct inode_operations proc_link_inode_operations = {
};
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 @@ static int proc_readlink(struct dentry * dentry, char * buffer, int buflen)
{
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;
......
......@@ -42,7 +42,7 @@ static int property_read_proc(char *page, char **start, off_t off,
*/
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 @@ struct inode_operations devtree_symlink_inode_operations = {
};
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 @@ static struct dentry *devtree_follow_link(struct dentry *dentry,
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)
......
......@@ -55,9 +55,6 @@ static struct file_operations proc_dir_operations = {
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 int proc_self_readlink(struct dentry *dentry, char *buffer, int buflen)
}
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 @@ int proc_readlink(struct dentry * dentry, char * buffer, int buflen)
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 @@ struct dentry * proc_follow_link(struct dentry * dentry, struct dentry *base)
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;
}
......
......@@ -451,7 +451,8 @@ romfs_readlink(struct dentry *dentry, char *buffer, int len)
}
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 @@ static struct dentry *romfs_follow_link(struct dentry *dentry,
} else
link[len] = 0;
dentry = lookup_dentry(link, base, 1);
dentry = lookup_dentry(link, base, follow);
kfree(link);
if (0) {
......
......@@ -21,7 +21,7 @@
#include <asm/uaccess.h>
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 @@ struct inode_operations sysv_symlink_inode_operations = {
};
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 @@ static struct dentry *sysv_follow_link(struct dentry * dentry,
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;
}
......
......@@ -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 @@ static struct dentry * ufs_follow_link(struct dentry * dentry,
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"))
......
......@@ -64,7 +64,8 @@ static int UMSDOS_readlink (struct dentry *dentry, char *buffer, int buflen)
/* 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 @@ dentry->d_parent->d_name.name, dentry->d_name.name));
}
symname[len] = 0;
dentry = lookup_dentry (symname, base, 1);
dentry = lookup_dentry (symname, base, follow);
kfree (symname);
if (0) {
......
......@@ -53,15 +53,11 @@ extern struct consw compat_con; /* console wrapper */
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)
......
......@@ -19,7 +19,6 @@ struct vc_data {
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 @@ struct vc_data {
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 @@ extern struct vc vc_cons [MAX_NR_CONSOLES];
#define CUR_SWMASK 0xfff0
#define CUR_DEFAULT CUR_UNDERLINE
#define CON_IS_VISIBLE(conp) (*conp->vc_display_fg == conp)
......@@ -27,7 +27,7 @@ struct qstr {
#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;
......
......@@ -348,6 +348,7 @@ struct inode {
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 @@ struct inode_operations {
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 @@ extern ino_t find_inode_number(struct dentry *, struct qstr *);
#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)
......
......@@ -35,7 +35,6 @@ nbd_end_request(struct request *req)
}
#define MAX_NBD 128
#endif
struct nbd_device {
int refcnt;
......@@ -51,6 +50,7 @@ struct nbd_device {
struct request *tail;
struct semaphore queue_lock;
};
#endif
/* This now IS in some kind of include file... */
......
......@@ -21,7 +21,6 @@ extern void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry);
#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_red[];
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);
......
......@@ -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 @@ struct screen_info {
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;
......@@ -390,10 +393,6 @@ extern long serial_console_init(long kmem_start, long kmem_end);
extern int pcxe_open(struct tty_struct *tty, struct file *filp);
/* console.c */
extern void update_screen(int new_console);
/* printk.c */
extern void console_print(const char *);
......
......@@ -16,9 +16,6 @@
#include <linux/config.h>
#ifdef CONFIG_VGA_CONSOLE
#if !defined(CONFIG_FB) && !defined(CONFIG_FB_MODULE)
#define VT_BUF_VRAM_ONLY
#endif
#include <asm/vga.h>
#endif
......
......@@ -35,27 +35,29 @@ void (*kd_mksound)(unsigned int hz, unsigned int ticks);
/* 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_get_unimap(int currcons, ushort ct, ushort *uct, struct unipair *list);
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 */
......
......@@ -77,7 +77,7 @@ extern long console_init(long, long);
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);
......
......@@ -415,15 +415,6 @@ asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct
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 @@ asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct
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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment