Hi, Michael Schroeder has written a console driver that only uses functions from the ARCS prom and therefore should work on all SGIs. The disadvantage is that it is not very fast and it needs the RAM area reserved for the PROM. But you'll get a nice console on IMPACT machines and other. enjoy, adrian ********************************************************************** Adrian Schroeter SuSE AG, Deutschherrnstr. 15-19, 90429 Nuernberg, Germany email: adrian@suse.de (296 mails already received today.)
--- ./arch/mips/arc/arc_con.c.orig 2002-05-11 17:17:06.000000000 +0200 +++ ./arch/mips/arc/arc_con.c 2002-05-11 17:17:08.000000000 +0200 @@ -35,8 +35,11 @@ return prom_getchar(); } +extern int prom_memory_freed; + static int __init prom_console_setup(struct console *co, char *options) { + prom_memory_freed = -1; /* needed for prom functions */ return 0; } --- ./arch/mips/config.in.orig 2002-05-11 19:09:59.000000000 +0200 +++ ./arch/mips/config.in 2002-05-11 19:38:57.000000000 +0200 @@ -590,7 +590,8 @@ comment 'SGI Character devices' if [ "$CONFIG_VT" = "y" ]; then tristate 'SGI Newport Console support' CONFIG_SGI_NEWPORT_CONSOLE - if [ "$CONFIG_SGI_NEWPORT_CONSOLE" = "y" ]; then + tristate 'SGI ARCS Console support' CONFIG_SGI_ARCS_CONSOLE + if [ "$CONFIG_SGI_NEWPORT_CONSOLE" = "y" -o "$CONFIG_SGI_ARCS_CONSOLE" = "y" ]; then define_bool CONFIG_FONT_8x16 y fi define_bool CONFIG_DUMMY_CONSOLE y --- ./arch/mips/mm/init.c.orig 2002-05-11 17:15:22.000000000 +0200 +++ ./arch/mips/mm/init.c 2002-05-11 17:15:47.000000000 +0200 @@ -360,11 +360,16 @@ extern char __init_begin, __init_end; extern void prom_free_prom_memory(void); +int prom_memory_freed; + void free_initmem(void) { unsigned long addr; - prom_free_prom_memory (); + if (prom_memory_freed == 0) { + prom_free_prom_memory (); + prom_memory_freed = 1; + } addr = (unsigned long) &__init_begin; while (addr < (unsigned long) &__init_end) { --- ./arch/mips/sgi-ip22/ip22-mc.c.orig 2002-05-13 21:59:37.000000000 +0200 +++ ./arch/mips/sgi-ip22/ip22-mc.c 2002-05-13 22:57:30.000000000 +0200 @@ -162,3 +162,8 @@ } mcmisc_regs->gioparm = tmpreg; /* poof */ } + +void +sgimc_exp064() { + mcmisc_regs->gioparm |= SGIMC_GIOPARM_EXP064; +} --- ./arch/mips/sgi-ip22/ip22-setup.c.orig 2002-05-11 16:59:43.000000000 +0200 +++ ./arch/mips/sgi-ip22/ip22-setup.c 2002-05-13 23:26:39.000000000 +0200 @@ -124,6 +124,26 @@ { } +struct sgi_promgfxinfo sgi_promgfxinfo; +struct sgi_promgfx *sgi_promgfx; + +static void sgi_getgfxinfo(void) +{ + struct sgi_pvector *pvector = (PROMBLOCK)->pvector; + sgi_promgfx = ARC_CALL0_VEC(pvector, get_promgfx); + if (sgi_promgfx && sgi_promgfx->gfxaddr) { + /* we copy some fields into sgi_promgfxinfo so that + * we have the info even if the prom data is freed. + */ + sgi_promgfxinfo.addr = sgi_promgfx->gfxaddr; + sgi_promgfxinfo.width = sgi_promgfx->width; + sgi_promgfxinfo.height = sgi_promgfx->height; + } + /* impact graphics seems to need EXP064 */ + if (sgi_promgfxinfo.addr == 0xbf400000) + sgimc_exp064(); +} + void __init ip22_setup(void) { #ifdef CONFIG_SERIAL_CONSOLE @@ -142,6 +162,7 @@ /* Init INDY memory controller. */ sgimc_init(); + sgi_getgfxinfo(); /* Now enable boardcaches, if any. */ indy_sc_init(); @@ -186,10 +207,11 @@ sgi_volume_set(simple_strtoul(ArcGetEnvironmentVariable("volume"), NULL, 10)); + sgi_getgfxinfo(); #ifdef CONFIG_VT + conswitchp = 0; #ifdef CONFIG_SGI_NEWPORT_CONSOLE - if( mips_machtype == MACH_SGI_INDY ) { - conswitchp = &newport_con; + if (sgi_promgfxinfo.addr == 0xbf0f0000 || sgi_promgfxinfo.addr == 0xbf4f0000) { screen_info = (struct screen_info) { 0, 0, /* orig-x, orig-y */ @@ -202,12 +224,28 @@ 0, /* orig_video_isVGA */ 16 /* orig_video_points */ }; - } else { - conswitchp = &dummy_con; + conswitchp = &newport_con; + } +#endif +#ifdef CONFIG_SGI_ARCS_CONSOLE + if (!conswitchp && sgi_promgfxinfo.addr) { + extern const struct consw sgiarcs_con; + screen_info = (struct screen_info) { + 0, 0, /* orig-x, orig-y */ + 0, /* unused */ + 0, /* orig_video_page */ + 0, /* orig_video_mode */ + 160, /* orig_video_cols */ + 0, 0, 0, /* unused, ega_bx, unused */ + 64, /* orig_video_lines */ + 0, /* orig_video_isVGA */ + 16 /* orig_video_points */ + }; + conswitchp = &sgiarcs_con; } -#else - conswitchp = &dummy_con; #endif + if (conswitchp == 0) + conswitchp == &dummy_con; #endif rtc_ops = &indy_rtc_ops; --- ./drivers/video/Makefile.orig 2002-05-11 18:57:13.000000000 +0200 +++ ./drivers/video/Makefile 2002-05-11 18:57:44.000000000 +0200 @@ -21,6 +21,7 @@ obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o +obj-$(CONFIG_SGI_ARCS_CONSOLE) += sgiarcs_con.o obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o obj-$(CONFIG_STI_CONSOLE) += sticon.o sticon-bmode.o sticore.o obj-$(CONFIG_VGA_CONSOLE) += vgacon.o --- ./drivers/video/sgiarcs_con.c.orig 2002-05-11 17:19:51.000000000 +0200 +++ ./drivers/video/sgiarcs_con.c 2002-05-13 23:28:52.000000000 +0200 @@ -0,0 +1,627 @@ +/* + * sgiarcs_con.c: generic console for SGI ARCS systems + * + * (C) 2002 Michael Schroeder (mls@suse.de) + * + * Advantages: + * - should work on every SGI with ARCS prom + * Disadvantages: + * - is slow + * - needs prom memory block + * + * Some code stolen from fbcon.c and newport_con.c + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/tty.h> +#include <linux/kd.h> +#include <linux/selection.h> +#include <linux/console.h> +#include <linux/console_struct.h> +#include <linux/vt_kern.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <asm/sgiarcs.h> +#include <asm/bcache.h> + +#ifndef CONFIG_SGI_NEWPORT_CONSOLE +# define INCLUDE_LINUX_LOGO_DATA +#endif +#include <asm/linux_logo.h> + +#include <video/font.h> + +#define LOGO_W 80 +#define LOGO_H 80 + +extern struct fbcon_font_desc font_vga_8x16; + +#define FONT_DATA ((unsigned char *)font_vga_8x16.data) + +/* borrowed from fbcon.c */ +#define REFCOUNT(fd) (((int *)(fd))[-1]) +#define FNTSIZE(fd) (((int *)(fd))[-2]) +#define FNTCHARCNT(fd) (((int *)(fd))[-3]) +#define FONT_EXTRA_WORDS 3 + +static unsigned char *font_data[MAX_NR_CONSOLES]; + +static int logo_active; + +extern struct sgi_promgfx *sgi_promgfx; +extern int prom_memory_freed; + +extern void sgi_hpc64_restore(void), sgi_hpc64_off(void); + +#define SGIGFXVECTOR ((struct sgi_gfxvector *)sgi_promgfx->gfxvector) +#define SGIARCS_CALL0(func) ARC_CALL1_VEC(SGIGFXVECTOR, func, sgi_promgfx->gfxaddr) +#define SGIARCS_CALL1(func,a1) ARC_CALL2_VEC(SGIGFXVECTOR, func, sgi_promgfx->gfxaddr, a1) +#define SGIARCS_CALL2(func,a1,a2) ARC_CALL3_VEC(SGIGFXVECTOR, func, sgi_promgfx->gfxaddr, a1, a2) +#define SGIARCS_CALL3(func,a1,a2,a3) ARC_CALL4_VEC(SGIGFXVECTOR, func, sgi_promgfx->gfxaddr, a1, a2, a3) +#define SGIARCS_CALL4(func,a1,a2,a3,a4) ARC_CALL5_VEC(SGIGFXVECTOR, func, sgi_promgfx->gfxaddr, a1, a2, a3, a4) + +#define SGIARCS_START(flags) do {save_and_cli(flags);bc_disable();} while (0) +#define SGIARCS_END(flags) do {bc_enable();restore_flags(flags);} while (0) + +#define CURSOR_DRAW_DELAY (1) +#define DEFAULT_CURSOR_BLINK_RATE (20) + +static int cursor_drawn; +static int vbl_cursor_cnt; +static int cursor_on; +static int cursor_blink_rate; +static int cursor_x; +static int cursor_y; + +static inline void cursor_undrawn(void) +{ + vbl_cursor_cnt = 0; + cursor_drawn = 0; +} + +static void cursor_timer_handler(unsigned long dev_addr); +static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp); + +static struct timer_list cursor_timer = { + function: cursor_timer_handler +}; + +static void cursor_timer_handler(unsigned long dev_addr) +{ + fbcon_vbl_handler(0, NULL, NULL); + cursor_timer.expires = jiffies+HZ/50; + add_timer(&cursor_timer); +} + +static inline void sgiarcs_init_cmap(void) +{ + unsigned short i; + unsigned long flags; + + SGIARCS_START(flags); + for (i = 0; i < 16; i++) { + SGIARCS_CALL4(SetCmap, color_table[i], default_red[i], default_grn[i], default_blu[i]); + } + SGIARCS_END(flags); +} + +static inline void sgiarcs_show_logo(void) +{ + unsigned long i, x, y; + unsigned long flags; + + SGIARCS_START(flags); + for (i = 0; i < LINUX_LOGO_COLORS; i++) + SGIARCS_CALL4(SetCmap, i + 0x20, linux_logo_red[i], linux_logo_green[i], linux_logo_blue[i]); + for (y = 0; y < LOGO_H; y++) + for (x = 0; x < LOGO_W; x++) { + SGIARCS_CALL1(SetColor, linux_logo[y * LOGO_W + x]); + SGIARCS_CALL2(DrawPixel, sgi_promgfx->width - LOGO_W + x, sgi_promgfx->height - 1 - y); + } + SGIARCS_END(flags); +} + +static inline void sgiarcs_clear_screen(int xstart, int ystart, int xend, + int yend, int ci) +{ + unsigned long flags; + if (logo_active) + return; + SGIARCS_START(flags); + SGIARCS_CALL1(SetColor, ci); + SGIARCS_CALL4(DrawBlock, xstart, sgi_promgfx->height - 1 - ystart, xend, sgi_promgfx->height - 1 - yend); + SGIARCS_END(flags); +} + +#ifdef MODULE +static const char *sgiarcs_startup(void) +#else +static const char *__init sgiarcs_startup(void) +#endif +{ + int i; + unsigned long flags; + + if (sgi_promgfx == 0 || prom_memory_freed > 0) + return NULL; + prom_memory_freed = -1; + for (i = 0; i < MAX_NR_CONSOLES; i++) + font_data[i] = FONT_DATA; + sgiarcs_init_cmap(); + sgiarcs_clear_screen(0, 0, sgi_promgfx->width - 1, sgi_promgfx->height - 1, 0); + SGIARCS_START(flags); + /* move mouse offscreen */ + SGIARCS_CALL2(SetCursor, sgi_promgfx->width + 10, sgi_promgfx->height + 10); + SGIARCS_END(flags); + + cursor_blink_rate = DEFAULT_CURSOR_BLINK_RATE; + cursor_timer.expires = jiffies+HZ/50; + add_timer(&cursor_timer); + + printk("SGIARCS colole driver, %dx%d at 0x%x\n", sgi_promgfx->width, sgi_promgfx->height, sgi_promgfx->gfxaddr); + return "SGI_ARCS"; +} + +static void sgiarcs_init(struct vc_data *vc, int init) +{ + vc->vc_cols = sgi_promgfx->width / 8; + vc->vc_rows = sgi_promgfx->height / 16; + vc->vc_can_do_color = 1; +} + +static void sgiarcs_clear(struct vc_data *vc, int sy, int sx, int height, + int width) +{ + int redraw_cursor = 0; + if (logo_active) + return; + if ((sy <= cursor_y) && (cursor_y < sy+height) && + (sx <= cursor_x) && (cursor_x < sx+width)) { + cursor_undrawn(); + redraw_cursor = 1; + } + sgiarcs_clear_screen(sx << 3, sy << 4, ((sx + width) << 3) - 1, ((sy + height) << 4) - 1, (vc->vc_color & 0xf0) >> 4); + if (redraw_cursor) + vbl_cursor_cnt = CURSOR_DRAW_DELAY; +} + +static void sgiarcs_putc_raw(struct vc_data *vc, int charattr, int ypos, + int xpos) +{ + struct sgi_gfxbitmap bm; + unsigned char *p; + USHORT m[16]; + int i; + unsigned long flags; + + p = &font_data[vc->vc_num][(charattr & 0xff) << 4]; + charattr = (charattr >> 8) & 0xff; + xpos <<= 3; + ypos <<= 4; + + if (!logo_active) + sgiarcs_clear_screen(xpos, ypos, xpos + 7, ypos + 15, (charattr & 0xf0) >> 4); + for (i = 0; i < 16; i++) + m[15 - i] = p[i] << 8; + bm.bitmap = m; + bm.width = 8; + bm.height = 16; + bm.offx = bm.offy = bm.movex = bm.movey = 0; + bm.shortsperline = 1; + SGIARCS_START(flags); + SGIARCS_CALL1(SetColor, charattr & 0x0f); + SGIARCS_CALL2(SetPos, xpos, sgi_promgfx->height - 16 - ypos); + SGIARCS_CALL1(DrawBitmap, &bm); + SGIARCS_END(flags); +} + +static void sgiarcs_putc(struct vc_data *vc, int charattr, int ypos, + int xpos) +{ + int redraw_cursor = 0; + if ((cursor_x == xpos) && (cursor_y == ypos)) { + cursor_undrawn(); + redraw_cursor = 1; + } + sgiarcs_putc_raw(vc, charattr, ypos, xpos); + if (redraw_cursor) + vbl_cursor_cnt = CURSOR_DRAW_DELAY; +} + +static void sgiarcs_putcs(struct vc_data *vc, const unsigned short *s, + int count, int ypos, int xpos) +{ + int redraw_cursor = 0; + int charattr; + struct sgi_gfxbitmap bm; + unsigned char *p; + int line, bite, i, j; + USHORT m[16 * 16]; /* 32 chars */ + unsigned long flags; + + if ((cursor_y == ypos) && (xpos <= cursor_x) && + (cursor_x < (xpos + count))) { + cursor_undrawn(); + redraw_cursor = 1; + } + + xpos <<= 3; + ypos <<= 4; + charattr = (scr_readw(s) >> 8) & 0xff; + if (!logo_active) + sgiarcs_clear_screen(xpos, ypos, xpos + count * 8 - 1, ypos + 15, (charattr & 0xf0) >> 4); + while (count > 0) { + bite = count > 32 ? 32 : count; + line = (bite + 1) & ~1; + for (i = 0; i < bite; i++) { + p = &font_data[vc->vc_num][(scr_readw(s++) & 0xff) << 4]; + for (j = 15 * line; j >= 0; j -= line) + *((unsigned char *)m + j + i) = *p++; + } + bm.bitmap = m; + bm.width = bite * 8; + bm.height = 16; + bm.offx = bm.offy = bm.movex = bm.movey = 0; + bm.shortsperline = line / 2; + SGIARCS_START(flags); + SGIARCS_CALL1(SetColor, charattr & 0x0f); + SGIARCS_CALL2(SetPos, xpos, sgi_promgfx->height - 16 - ypos); + SGIARCS_CALL1(DrawBitmap, &bm); + SGIARCS_END(flags); + xpos += bite * 8; + count -= bite; + } + if (redraw_cursor) + vbl_cursor_cnt = CURSOR_DRAW_DELAY; +} + +static void sgiarcs_cursor_revc(struct vc_data *vc, int x, int y) +{ + unsigned short c = *(unsigned short *)(vc->vc_origin + vc->vc_size_row * y + x * 2); + if (!cursor_drawn) + c ^= 0xff00; + sgiarcs_putc_raw(vc, c, y, x); +} + +static void sgiarcs_cursor(struct vc_data *vc, int mode) +{ + if (cursor_x == vc->vc_x && cursor_y == vc->vc_y && + (mode == CM_ERASE) == !cursor_on) + return; + cursor_on = 0; + if (cursor_drawn) + sgiarcs_cursor_revc(vc, cursor_x, cursor_y); + cursor_x = vc->vc_x; + cursor_y = vc->vc_y; + switch (mode) { + case CM_ERASE: + cursor_drawn = 0; + break; + case CM_MOVE: + case CM_DRAW: + if (cursor_drawn) + sgiarcs_cursor_revc(vc, cursor_x, cursor_y); + vbl_cursor_cnt = CURSOR_DRAW_DELAY; + cursor_on = 1; + break; + } +} + +static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp) +{ + if (!cursor_on) + return; + if (vbl_cursor_cnt && --vbl_cursor_cnt == 0) { + sgiarcs_cursor_revc(vc_cons[fg_console].d, cursor_x, cursor_y); + cursor_drawn ^= 1; + vbl_cursor_cnt = cursor_blink_rate; + } +} + + +static int sgiarcs_switch(struct vc_data *vc) +{ + static int logo_drawn = 0; + + if (!logo_drawn) { + sgiarcs_show_logo(); + logo_drawn = 1; + logo_active = 1; + } + return 1; +} + +static int sgiarcs_blank(struct vc_data *c, int blank) +{ + unsigned long flags; + + SGIARCS_START(flags); + SGIARCS_CALL1(BlankScreen, blank); + SGIARCS_END(flags); + return 1; +} + +static int sgiarcs_set_font(int unit, struct console_font_op *op) +{ + int w = op->width; + int h = op->height; + int size = h * op->charcount; + int i; + unsigned char *new_data, *data = op->data, *p; + + /* ladis: when I grow up, there will be a day... and more sizes will + * be supported ;-) */ + if ((w != 8) || (h != 16) + || (op->charcount != 256 && op->charcount != 512)) + return -EINVAL; + + if (!(new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, + GFP_USER))) return -ENOMEM; + + new_data += FONT_EXTRA_WORDS * sizeof(int); + FNTSIZE(new_data) = size; + FNTCHARCNT(new_data) = op->charcount; + REFCOUNT(new_data) = 0; /* usage counter */ + + p = new_data; + for (i = 0; i < op->charcount; i++) { + memcpy(p, data, h); + data += 32; + p += h; + } + + /* check if font is already used by other console */ + for (i = 0; i < MAX_NR_CONSOLES; i++) { + if (font_data[i] != FONT_DATA + && FNTSIZE(font_data[i]) == size + && !memcmp(font_data[i], new_data, size)) { + kfree(new_data - FONT_EXTRA_WORDS * sizeof(int)); + /* current font is the same as the new one */ + if (i == unit) + return 0; + new_data = font_data[i]; + break; + } + } + /* old font is user font */ + if (font_data[unit] != FONT_DATA) { + if (--REFCOUNT(font_data[unit]) == 0) + kfree(font_data[unit] - + FONT_EXTRA_WORDS * sizeof(int)); + } + REFCOUNT(new_data)++; + font_data[unit] = new_data; + + return 0; +} + +static int sgiarcs_set_def_font(int unit, struct console_font_op *op) +{ + if (font_data[unit] != FONT_DATA) { + if (--REFCOUNT(font_data[unit]) == 0) + kfree(font_data[unit] - + FONT_EXTRA_WORDS * sizeof(int)); + font_data[unit] = FONT_DATA; + } + + return 0; +} + +static int sgiarcs_font_op(struct vc_data *vc, struct console_font_op *op) +{ + int unit = vc->vc_num; + + switch (op->op) { + case KD_FONT_OP_SET: + return sgiarcs_set_font(unit, op); + case KD_FONT_OP_SET_DEFAULT: + return sgiarcs_set_def_font(unit, op); + default: + return -ENOSYS; + } +} + +static int sgiarcs_set_palette(struct vc_data *vc, unsigned char *table) +{ + return -EINVAL; +} + +static int sgiarcs_scrolldelta(struct vc_data *vc, int lines) +{ + /* there is (nearly) no off-screen memory, so we can't scroll back */ + return 0; +} + +static int sgiarcs_scroll(struct vc_data *vc, int t, int b, int dir, + int lines) +{ + int count, x, y; + unsigned short *s, *d; + unsigned short chattr; + + sgiarcs_cursor(vc, CM_ERASE); + + if (logo_active) { + logo_active = 0; + sgiarcs_clear_screen(sgi_promgfx->width - LOGO_W, 0, sgi_promgfx->width - 1, LOGO_H - 1, 0); + } + count = (b - t - lines) * vc->vc_cols; + if (dir == SM_UP) { + x = 0; + y = t; + s = (unsigned short *) (vc->vc_origin + + vc->vc_size_row * (t + lines)); + d = (unsigned short *) (vc->vc_origin + + vc->vc_size_row * t); + while (count--) { + chattr = scr_readw(s++); + if (chattr != scr_readw(d)) { + sgiarcs_putc(vc, chattr, y, x); + scr_writew(chattr, d); + } + d++; + if (++x == vc->vc_cols) { + x = 0; + y++; + } + } + d = (unsigned short *) (vc->vc_origin + + vc->vc_size_row * (b - lines)); + x = 0; + y = b - lines; + for (count = 0; count < (lines * vc->vc_cols); count++) { + if (scr_readw(d) != vc->vc_video_erase_char) { + sgiarcs_putc(vc, vc->vc_video_erase_char, + y, x); + scr_writew(vc->vc_video_erase_char, d); + } + d++; + if (++x == vc->vc_cols) { + x = 0; + y++; + } + } + } else { + x = vc->vc_cols - 1; + y = b - 1; + s = (unsigned short *) (vc->vc_origin + + vc->vc_size_row * (b - lines) - 2); + d = (unsigned short *) (vc->vc_origin + + vc->vc_size_row * b - 2); + while (count--) { + chattr = scr_readw(s--); + if (chattr != scr_readw(d)) { + sgiarcs_putc(vc, chattr, y, x); + scr_writew(chattr, d); + } + d--; + if (x-- == 0) { + x = vc->vc_cols - 1; + y--; + } + } + d = (unsigned short *) (vc->vc_origin + + vc->vc_size_row * t); + x = 0; + y = t; + for (count = 0; count < (lines * vc->vc_cols); count++) { + if (scr_readw(d) != vc->vc_video_erase_char) { + sgiarcs_putc(vc, vc->vc_video_erase_char, + y, x); + scr_writew(vc->vc_video_erase_char, d); + } + d++; + if (++x == vc->vc_cols) { + x = 0; + y++; + } + } + } + return 1; +} + +static void sgiarcs_bmove(struct vc_data *vc, int sy, int sx, int dy, + int dx, int h, int w) +{ + if (sy != dy) + panic("sgiarcs_bmove width sy != dy"); + + if (((sy <= cursor_y) && (cursor_y < sy+h) && + (sx <= cursor_x) && (cursor_x < sx+w)) || + ((dy <= cursor_y) && (cursor_y < dy+h) && + (dx <= cursor_x) && (cursor_x < dx+w))) + sgiarcs_cursor(vc, CM_ERASE); + + while (h-- > 0) { + unsigned short *d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * dy + dx * 2); + unsigned short *s = d + (dx - sx); + unsigned short *start = d; + unsigned short *ls = d; + unsigned short *le = d + w; + unsigned short c; + int x = dx; + unsigned short attr = 1; + + do { + c = scr_readw(d); + if (attr != (c & 0xff00)) { + attr = c & 0xff00; + if (d > start) { + sgiarcs_putcs(vc, start, d - start, dy, x); + x += d - start; + start = d; + } + } + if (s >= ls && s < le && c == scr_readw(s)) { + if (d > start) { + sgiarcs_putcs(vc, start, d - start, dy, x); + x += d - start + 1; + start = d + 1; + } else { + x++; + start++; + } + } + s++; + d++; + } while (d < le); + if (d > start) + sgiarcs_putcs(vc, start, d - start, dy, x); + sy++; + dy++; + } +} + +static int sgiarcs_dummy(struct vc_data *c) +{ + return 0; +} + +#define DUMMY (void *) sgiarcs_dummy + +const struct consw sgiarcs_con = { + con_startup: sgiarcs_startup, + con_init: sgiarcs_init, + con_deinit: DUMMY, + con_clear: sgiarcs_clear, + con_putc: sgiarcs_putc, + con_putcs: sgiarcs_putcs, + con_cursor: sgiarcs_cursor, + con_scroll: sgiarcs_scroll, + con_bmove: sgiarcs_bmove, + con_switch: sgiarcs_switch, + con_blank: sgiarcs_blank, + con_font_op: sgiarcs_font_op, + con_set_palette: sgiarcs_set_palette, + con_scrolldelta: sgiarcs_scrolldelta, + con_set_origin: DUMMY, + con_save_screen: DUMMY +}; + +#ifdef MODULE +int init_module(void) +{ + if (!sgiarcs_startup()) + printk("Error loading SGIARCS Console driver\n"); + else + printk("Loading SGIARCS Console Driver\n"); + take_over_console(&sgiarcs_con, 0, MAX_NR_CONSOLES - 1, 1); + + return 0; +} + +int cleanup_module(void) +{ + int i; + + printk("Unloading SGIARCS Console Driver\n"); + /* free memory used by user font */ + for (i = 0; i < MAX_NR_CONSOLES; i++) + sgiarcs_set_def_font(i, NULL); + + return 0; +} +#endif --- ./include/asm-mips/sgi/sgimc.h.orig 2002-05-13 23:09:29.000000000 +0200 +++ ./include/asm-mips/sgi/sgimc.h 2002-05-13 23:09:43.000000000 +0200 @@ -224,5 +224,6 @@ #define SGIMC_SEG1_SIZE_IP26_IP28 0x20000000 /* 512MB */ extern void sgimc_init(void); +extern void sgimc_exp064(void); #endif /* _ASM_SGI_SGIMC_H */ --- ./include/asm-mips/sgiarcs.h.orig 2002-05-11 16:31:51.000000000 +0200 +++ ./include/asm-mips/sgiarcs.h 2002-05-11 20:29:08.000000000 +0200 @@ -360,6 +360,58 @@ int smax; /* Max # of symbols. */ }; +struct sgi_pvector { + LONG ioctl; + LONG get_nvram_tab; + LONG load_abs; + LONG invoke_abs; + LONG exec_abs; + LONG fs_register; + LONG fs_unregister; + LONG signal; + LONG get_promgfx; +}; + +struct sgi_promgfx { + LONG gfxvector; + LONG gfxaddr; + LONG unknown1[8]; + LONG width; + LONG height; + LONG unknown2[10]; + LONG state; +}; + +struct sgi_promgfxinfo { + int addr; + int width; + int height; +}; + +struct sgi_gfxvector { + LONG BlankScreen; + LONG SetColor; + LONG SetCmap; + LONG DrawBlock; + LONG DrawPixel; + LONG SetPos; + LONG DrawBitmap; + LONG MoveBlock; + LONG InitScreen; + LONG SetCursor; +}; + +struct sgi_gfxbitmap { + USHORT * bitmap; + USHORT width; + USHORT height; + SHORT offx; + SHORT offy; + SHORT movex; + SHORT movey; + USHORT shortsperline; +}; + /* * Macros for calling a 32-bit ARC implementation from 64-bit code */ @@ -370,9 +422,9 @@ "$2","$3","$4","$5","$6","$7","$8","$9","$10","$11", \ "$12","$13","$14","$15","$16","$24","25","$31" -#define ARC_CALL0(dest) \ +#define ARC_CALL0_VEC(vec,dest) \ ({ long __res; \ - long __vec = (long) romvec->dest; \ + long __vec = (long) (vec)->dest; \ __asm__ __volatile__( \ "dsubu\t$29, 32\n\t" \ "jalr\t%1\n\t" \ @@ -384,10 +436,10 @@ (unsigned long) __res; \ }) -#define ARC_CALL1(dest,a1) \ +#define ARC_CALL1_VEC(vec,dest,a1) \ ({ long __res; \ register signed int __a1 __asm__("$4") = (int) (long) (a1); \ - long __vec = (long) romvec->dest; \ + long __vec = (long) (vec)->dest; \ __asm__ __volatile__( \ "dsubu\t$29, 32\n\t" \ "jalr\t%1\n\t" \ @@ -399,11 +451,11 @@ (unsigned long) __res; \ }) -#define ARC_CALL2(dest,a1,a2) \ +#define ARC_CALL2_VEC(vec,dest,a1,a2) \ ({ long __res; \ register signed int __a1 __asm__("$4") = (int) (long) (a1); \ register signed int __a2 __asm__("$5") = (int) (long) (a2); \ - long __vec = (long) romvec->dest; \ + long __vec = (long) (vec)->dest; \ __asm__ __volatile__( \ "dsubu\t$29, 32\n\t" \ "jalr\t%1\n\t" \ @@ -415,12 +467,12 @@ __res; \ }) -#define ARC_CALL3(dest,a1,a2,a3) \ +#define ARC_CALL3_VEC(vec,dest,a1,a2,a3) \ ({ long __res; \ register signed int __a1 __asm__("$4") = (int) (long) (a1); \ register signed int __a2 __asm__("$5") = (int) (long) (a2); \ register signed int __a3 __asm__("$6") = (int) (long) (a3); \ - long __vec = (long) romvec->dest; \ + long __vec = (long) (vec)->dest; \ __asm__ __volatile__( \ "dsubu\t$29, 32\n\t" \ "jalr\t%1\n\t" \ @@ -432,13 +484,13 @@ __res; \ }) -#define ARC_CALL4(dest,a1,a2,a3,a4) \ +#define ARC_CALL4_VEC(vec,dest,a1,a2,a3,a4) \ ({ long __res; \ register signed int __a1 __asm__("$4") = (int) (long) (a1); \ register signed int __a2 __asm__("$5") = (int) (long) (a2); \ register signed int __a3 __asm__("$6") = (int) (long) (a3); \ register signed int __a4 __asm__("$7") = (int) (long) (a4); \ - long __vec = (long) romvec->dest; \ + long __vec = (long) (vec)->dest; \ __asm__ __volatile__( \ "dsubu\t$29, 32\n\t" \ "jalr\t%1\n\t" \ @@ -451,14 +503,14 @@ __res; \ }) -#define ARC_CALL5(dest,a1,a2,a3,a4,a5) \ +#define ARC_CALL5_VEC(vec,dest,a1,a2,a3,a4,a5) \ ({ long __res; \ register signed int __a1 __asm__("$4") = (int) (long) (a1); \ register signed int __a2 __asm__("$5") = (int) (long) (a2); \ register signed int __a3 __asm__("$6") = (int) (long) (a3); \ register signed int __a4 __asm__("$7") = (int) (long) (a4); \ register signed int __a5 = (a5); \ - long __vec = (long) romvec->dest; \ + long __vec = (long) (vec)->dest; \ __asm__ __volatile__( \ "dsubu\t$29, 32\n\t" \ "sw\t%6, 16($29)\n\t" \ @@ -478,57 +530,57 @@ #if (defined(CONFIG_MIPS32) && defined(CONFIG_ARC32)) || \ (defined(CONFIG_MIPS64) && defined(CONFIG_ARC32)) -#define ARC_CALL0(dest) \ +#define ARC_CALL0_VEC(vec,dest) \ ({ long __res; \ - long (*__vec)(void) = (void *) romvec->dest; \ + long (*__vec)(void) = (void *) (vec)->dest; \ \ __res = __vec(); \ __res; \ }) -#define ARC_CALL1(dest,a1) \ +#define ARC_CALL1_VEC(vec,dest,a1) \ ({ long __res; \ long __a1 = (long) (a1); \ - long (*__vec)(long) = (void *) romvec->dest; \ + long (*__vec)(long) = (void *) (vec)->dest; \ \ __res = __vec(__a1); \ __res; \ }) -#define ARC_CALL2(dest,a1,a2) \ +#define ARC_CALL2_VEC(vec,dest,a1,a2) \ ({ long __res; \ long __a1 = (long) (a1); \ long __a2 = (long) (a2); \ - long (*__vec)(long, long) = (void *) romvec->dest; \ + long (*__vec)(long, long) = (void *) (vec)->dest; \ \ __res = __vec(__a1, __a2); \ __res; \ }) -#define ARC_CALL3(dest,a1,a2,a3) \ +#define ARC_CALL3_VEC(vec,dest,a1,a2,a3) \ ({ long __res; \ long __a1 = (long) (a1); \ long __a2 = (long) (a2); \ long __a3 = (long) (a3); \ - long (*__vec)(long, long, long) = (void *) romvec->dest; \ + long (*__vec)(long, long, long) = (void *) (vec)->dest; \ \ __res = __vec(__a1, __a2, __a3); \ __res; \ }) -#define ARC_CALL4(dest,a1,a2,a3,a4) \ +#define ARC_CALL4_VEC(vec,dest,a1,a2,a3,a4) \ ({ long __res; \ long __a1 = (long) (a1); \ long __a2 = (long) (a2); \ long __a3 = (long) (a3); \ long __a4 = (long) (a4); \ - long (*__vec)(long, long, long, long) = (void *) romvec->dest; \ + long (*__vec)(long, long, long, long) = (void *) (vec)->dest; \ \ __res = __vec(__a1, __a2, __a3, __a4); \ __res; \ }) -#define ARC_CALL5(dest,a1,a2,a3,a4,a5) \ +#define ARC_CALL5_VEC(vec,dest,a1,a2,a3,a4,a5) \ ({ long __res; \ long __a1 = (long) (a1); \ long __a2 = (long) (a2); \ @@ -536,11 +588,18 @@ long __a4 = (long) (a4); \ long __a5 = (long) (a5); \ long (*__vec)(long, long, long, long, long); \ - __vec = (void *) romvec->dest; \ + __vec = (void *) (vec)->dest; \ \ __res = __vec(__a1, __a2, __a3, __a4, __a5); \ __res; \ }) #endif /* both kernel and ARC either 32-bit or 64-bit */ +#define ARC_CALL0(dest) ARC_CALL0_VEC(romvec,dest) +#define ARC_CALL1(dest,a1) ARC_CALL1_VEC(romvec,dest,a1) +#define ARC_CALL2(dest,a1,a2) ARC_CALL2_VEC(romvec,dest,a1,a2) +#define ARC_CALL3(dest,a1,a2,a3) ARC_CALL3_VEC(romvec,dest,a1,a2,a3) +#define ARC_CALL4(dest,a1,a2,a3,a4) ARC_CALL4_VEC(romvec,dest,a1,a2,a3,a4) +#define ARC_CALL5(dest,a1,a2,a3,a4,a5) ARC_CALL5_VEC(romvec,dest,a1,a2,a3,a4,a5) + #endif /* _ASM_SGIARCS_H */