summaryrefslogtreecommitdiffstats
path: root/drivers/sgi/char/cons_newport.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sgi/char/cons_newport.c')
-rw-r--r--drivers/sgi/char/cons_newport.c613
1 files changed, 612 insertions, 1 deletions
diff --git a/drivers/sgi/char/cons_newport.c b/drivers/sgi/char/cons_newport.c
index 91212c0ae..30aa1f3b7 100644
--- a/drivers/sgi/char/cons_newport.c
+++ b/drivers/sgi/char/cons_newport.c
@@ -3,7 +3,618 @@
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
*
- * $Id: cons_newport.c,v 1.5 1997/09/12 01:32:50 ralf Exp $
+ * $Id: cons_newport.c,v 1.1 1997/12/02 02:28:23 ralf Exp $
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/kd.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/major.h>
+#include <linux/mm.h>
+#include <linux/version.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/bitops.h>
+#include <asm/sgialib.h>
+#include <asm/ptrace.h>
+
+#include <linux/kbd_kern.h>
+#include <linux/vt_kern.h>
+#include <linux/consolemap.h>
+#include <linux/selection.h>
+#include <linux/console_struct.h>
+
+#include "gconsole.h"
+#include "newport.h"
+#include "graphics.h" /* Just for now */
+#include <asm/gfx.h>
+#include <asm/ng1.h>
+
+#if 0
+#include "linux_logo.h"
+#endif
+
+#define BMASK(c) (c << 24)
+
+#define RENDER(regs, cp) do { \
+(regs)->go.zpattern = BMASK((cp)[0x0]); (regs)->go.zpattern = BMASK((cp)[0x1]); \
+(regs)->go.zpattern = BMASK((cp)[0x2]); (regs)->go.zpattern = BMASK((cp)[0x3]); \
+(regs)->go.zpattern = BMASK((cp)[0x4]); (regs)->go.zpattern = BMASK((cp)[0x5]); \
+(regs)->go.zpattern = BMASK((cp)[0x6]); (regs)->go.zpattern = BMASK((cp)[0x7]); \
+(regs)->go.zpattern = BMASK((cp)[0x8]); (regs)->go.zpattern = BMASK((cp)[0x9]); \
+(regs)->go.zpattern = BMASK((cp)[0xa]); (regs)->go.zpattern = BMASK((cp)[0xb]); \
+(regs)->go.zpattern = BMASK((cp)[0xc]); (regs)->go.zpattern = BMASK((cp)[0xd]); \
+(regs)->go.zpattern = BMASK((cp)[0xe]); (regs)->go.zpattern = BMASK((cp)[0xf]); \
+} while(0)
+
+#define REVERSE_RENDER(regs, cp) do { \
+(regs)->go.zpattern = BMASK((~(cp)[0x0])); (regs)->go.zpattern = BMASK((~(cp)[0x1])); \
+(regs)->go.zpattern = BMASK((~(cp)[0x2])); (regs)->go.zpattern = BMASK((~(cp)[0x3])); \
+(regs)->go.zpattern = BMASK((~(cp)[0x4])); (regs)->go.zpattern = BMASK((~(cp)[0x5])); \
+(regs)->go.zpattern = BMASK((~(cp)[0x6])); (regs)->go.zpattern = BMASK((~(cp)[0x7])); \
+(regs)->go.zpattern = BMASK((~(cp)[0x8])); (regs)->go.zpattern = BMASK((~(cp)[0x9])); \
+(regs)->go.zpattern = BMASK((~(cp)[0xa])); (regs)->go.zpattern = BMASK((~(cp)[0xb])); \
+(regs)->go.zpattern = BMASK((~(cp)[0xc])); (regs)->go.zpattern = BMASK((~(cp)[0xd])); \
+(regs)->go.zpattern = BMASK((~(cp)[0xe])); (regs)->go.zpattern = BMASK((~(cp)[0xf])); \
+} while(0)
+
+extern int default_red[16], default_grn[16], default_blu[16];
+extern unsigned char video_type;
+
+static int cursor_pos = -1;
+struct newport_regs *npregs;
+
+#define TESTVAL 0xdeadbeef
+#define XSTI_TO_FXSTART(val) (((val) & 0xffff) << 11)
+
+static inline void
+newport_disable_video(void)
+{
+ unsigned short treg;
+
+ treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+ newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_EVIDEO)));
+}
+
+static inline void
+newport_enable_video(void)
+{
+ unsigned short treg;
+
+ treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+ newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_EVIDEO));
+}
+
+static inline void
+newport_disable_cursor(void)
+{
+ unsigned short treg;
+
+ treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+ newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_ECDISP)));
+}
+
+#if 0
+static inline void
+newport_enable_cursor(void)
+{
+ unsigned short treg;
+
+ treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+ newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_ECDISP));
+}
+#endif
+
+static inline void
+newport_init_cmap(void)
+{
+ unsigned short i;
+
+ for(i = 0; i < 16; i++) {
+ newport_bfwait();
+ newport_cmap_setaddr(npregs, color_table[i]);
+ newport_cmap_setrgb(npregs,
+ default_red[i],
+ default_grn[i],
+ default_blu[i]);
+ }
+}
+
+#if 0
+static inline void
+newport_init_cursor(void)
+{
+ unsigned char cursor[256];
+ unsigned short *cookie;
+ int i;
+
+ for(i = 0; i < 256; i++)
+ cursor[i] = 0x0;
+ for(i = 211; i < 256; i+=4) {
+ cursor[i] = 0xff;
+#if 0
+ cursor[(i + 128) << 2] = 0xff;
+ cursor[((i + 128) << 2) + 1] = 0xff;
+#endif
+ }
+
+ /* Load the SRAM on the VC2 for this new GLYPH. */
+ cookie = (unsigned short *) cursor;
+ newport_vc2_set(npregs, VC2_IREG_RADDR, VC2_CGLYPH_ADDR);
+ npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM |
+ NPORT_DMODE_W2 | VC2_PROTOCOL);
+ for(i = 0; i < 128; i++) {
+ newport_bfwait();
+ npregs->set.dcbdata0.hwords.s1 = *cookie++;
+ }
+
+ /* Place the cursor at origin. */
+ newport_vc2_set(npregs, VC2_IREG_CURSX, 0);
+ newport_vc2_set(npregs, VC2_IREG_CURSY, 0);
+ newport_enable_cursor();
+}
+#endif
+
+static inline void
+newport_clear_screen(void)
+{
+ newport_wait();
+ npregs->set.wrmask = 0xffffffff;
+ npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+ NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX |
+ NPORT_DMODE0_STOPY);
+ npregs->set.colori = 0;
+ npregs->set.xystarti = 0;
+ npregs->go.xyendi = (((1280 + 63) << 16)|(1024));
+ newport_bfwait();
+}
+
+static inline void
+newport_render_version(void)
+{
+#if 0
+ unsigned short *ush;
+ int currcons = 0;
+ char *p;
+
+ ush = (unsigned short *) video_mem_base + video_num_columns * 2 + 20;
+ for (p = "SGI/Linux version " UTS_RELEASE; *p; p++, ush++) {
+ *ush = (attr << 8) + *p;
+ newport_blitc (*ush, (unsigned long) ush);
+ }
+#endif
+}
+
+#if 0
+static inline void
+newport_render_logo(void)
+{
+ int i, xpos, ypos;
+ unsigned char *bmap;
+
+ xpos = 8;
+ ypos = 18;
+
+ newport_wait();
+ npregs->set.colori = 9;
+ npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+ NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB |
+ NPORT_DMODE0_L32);
+
+ for(i = 0; i < 80; i+=8) {
+ /* Set coordinates for bitmap operation. */
+ npregs->set.xystarti = ((xpos + i) << 16) | ypos;
+ npregs->set.xyendi = (((xpos + i) + 7) << 16);
+ newport_wait();
+
+ bmap = linux_logo + (i * 80);
+ RENDER(npregs, bmap); bmap += 0x10;
+ RENDER(npregs, bmap); bmap += 0x10;
+ RENDER(npregs, bmap); bmap += 0x10;
+ RENDER(npregs, bmap); bmap += 0x10;
+ RENDER(npregs, bmap);
+ }
+ prom_getchar();
+ prom_imode();
+}
+#endif
+
+static inline void
+newport_render_background(int xpos, int ypos, int ci)
+{
+ newport_wait();
+ npregs->set.wrmask = 0xffffffff;
+ npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+ NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX |
+ NPORT_DMODE0_STOPY);
+ npregs->set.colori = ci;
+ npregs->set.xystarti = (xpos << 16) | ypos;
+ npregs->go.xyendi = ((xpos + 7) << 16) | (ypos + 15);
+}
+
+void
+newport_set_origin(unsigned short offset)
+{
+ /* maybe this works... */
+ __origin = offset;
+}
+
+void
+newport_hide_cursor(void)
+{
+ int xpos, ypos, idx;
+ unsigned long flags;
+
+ if(vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
+ return;
+ save_and_cli(flags);
+
+ idx = cursor_pos;
+ if(idx == -1) {
+ restore_flags(flags);
+ return;
+ }
+ xpos = 8 + ((idx % video_num_columns) << 3);
+ ypos = 18 + ((idx / video_num_columns) << 4);
+ newport_render_background(xpos, ypos, 0);
+ restore_flags(flags);
+}
+
+void
+newport_set_cursor(int currcons)
+{
+ int xpos, ypos, idx, oldpos;
+ unsigned short *sp, *osp, cattr;
+ unsigned long flags;
+ unsigned char *p;
+
+ if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
+ return;
+
+ if (__real_origin != __origin)
+ __set_origin(__real_origin);
+
+ save_and_cli(flags);
+
+ idx = (pos - video_mem_base) >> 1;
+ sp = (unsigned short *) pos;
+ oldpos = cursor_pos;
+ cursor_pos = idx;
+ if(!deccm) {
+ hide_cursor();
+ restore_flags(flags);
+ return;
+ }
+ xpos = 8 + ((idx % video_num_columns) << 3);
+ ypos = 18 + ((idx / video_num_columns) << 4);
+ if(oldpos != -1) {
+ int oxpos, oypos;
+
+ /* Restore old location. */
+ osp = (unsigned short *) ((oldpos << 1) + video_mem_base);
+ oxpos = 8 + ((oldpos % video_num_columns) << 3);
+ oypos = 18 + ((oldpos / video_num_columns) << 4);
+ cattr = *osp;
+ newport_render_background(oxpos, oypos, (cattr & 0xf000) >> 12);
+ p = &vga_font[(cattr & 0xff) << 4];
+ newport_wait();
+ npregs->set.colori = (cattr & 0x0f00) >> 8;
+ npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+ NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB |
+ NPORT_DMODE0_L32);
+ npregs->set.xystarti = (oxpos << 16) | oypos;
+ npregs->set.xyendi = ((oxpos + 7) << 16);
+ newport_wait();
+ RENDER(npregs, p);
+ }
+ cattr = *sp;
+ newport_render_background(xpos, ypos, (cattr & 0xf000) >> 12);
+ p = &vga_font[(cattr & 0xff) << 4];
+ newport_wait();
+ npregs->set.colori = (cattr & 0x0f00) >> 8;
+ npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+ NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB |
+ NPORT_DMODE0_L32);
+ npregs->set.xystarti = (xpos << 16) | ypos;
+ npregs->set.xyendi = ((xpos + 7) << 16);
+ newport_wait();
+ REVERSE_RENDER(npregs, p);
+ restore_flags (flags);
+ return;
+}
+
+void
+newport_get_scrmem(int currcons)
+{
+ memcpyw((unsigned short *)vc_scrbuf[currcons],
+ (unsigned short *)origin, video_screen_size);
+ origin = video_mem_start = (unsigned long)vc_scrbuf[currcons];
+ scr_end = video_mem_end = video_mem_start + video_screen_size;
+ pos = origin + y*video_size_row + (x<<1);
+}
+
+void
+newport_set_scrmem(int currcons, long offset)
+{
+ if (video_mem_term - video_mem_base < offset + video_screen_size)
+ offset = 0;
+ memcpyw((unsigned short *)(video_mem_base + offset),
+ (unsigned short *) origin, video_screen_size);
+ video_mem_start = video_mem_base;
+ video_mem_end = video_mem_term;
+ origin = video_mem_base + offset;
+ scr_end = origin + video_screen_size;
+ pos = origin + y*video_size_row + (x<<1);
+ has_wrapped = 0;
+}
+
+int
+newport_set_get_cmap(unsigned char * arg, int set)
+{
+ unsigned short ent;
+ int i;
+
+ i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, 16*3);
+ if (i)
+ return i;
+
+ for (i=0; i<16; i++) {
+ if (set) {
+ __get_user(default_red[i], arg++);
+ __get_user(default_grn[i], arg++);
+ __get_user(default_blu[i], arg++);
+ } else {
+ __put_user (default_red[i], arg++);
+ __put_user (default_grn[i], arg++);
+ __put_user (default_blu[i], arg++);
+ }
+ }
+ if (set) {
+ for (i=0; i<MAX_NR_CONSOLES; i++) {
+ if (vc_cons_allocated(i)) {
+ int j, k;
+ 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];
+ }
+ }
+ }
+ if(console_blanked || vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
+ return 0;
+ for(ent = 0; ent < 16; ent++) {
+ newport_bfwait();
+ newport_cmap_setaddr(npregs, ent);
+ newport_cmap_setrgb(npregs,
+ default_red[ent],
+ default_grn[ent],
+ default_blu[ent]);
+ }
+ }
+
+ return 0;
+}
+
+void
+newport_blitc(unsigned short charattr, unsigned long addr)
+{
+ int idx, xpos, ypos;
+ unsigned char *p;
+
+ idx = (addr - (video_mem_base + (__origin<<1))) >> 1;
+ xpos = 8 + ((idx % video_num_columns) << 3);
+ ypos = 18 + ((idx / video_num_columns) << 4);
+
+ p = &vga_font[(charattr & 0xff) << 4];
+ charattr = (charattr >> 8) & 0xff;
+
+ newport_render_background(xpos, ypos, (charattr & 0xf0) >> 4);
+
+ /* Set the color and drawing mode. */
+ newport_wait();
+ npregs->set.colori = charattr & 0xf;
+ npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+ NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB |
+ NPORT_DMODE0_L32);
+
+ /* Set coordinates for bitmap operation. */
+ npregs->set.xystarti = (xpos << 16) | ypos;
+ npregs->set.xyendi = ((xpos + 7) << 16);
+ newport_wait();
+
+ /* Go, baby, go... */
+ RENDER(npregs, p);
+}
+
+void
+newport_memsetw(void * s, unsigned short c, unsigned int count)
+{
+ unsigned short * addr = (unsigned short *) s;
+
+ count /= 2;
+ if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS) {
+ while (count) {
+ count--;
+ *addr++ = c;
+ }
+ return;
+ }
+ if ((unsigned long) addr + count > video_mem_term ||
+ (unsigned long) addr < video_mem_base) {
+ if ((unsigned long) addr + count <= video_mem_term ||
+ (unsigned long) addr > video_mem_base) {
+ while (count) {
+ count--;
+ *addr++ = c;
+ }
+ return;
+ } else {
+ while (count) {
+ count--;
+ scr_writew(c, addr++);
+ }
+ }
+ } else {
+ while (count) {
+ count--;
+ if (*addr != c) {
+ newport_blitc(c, (unsigned long)addr);
+ *addr++ = c;
+ } else
+ addr++;
+ }
+ }
+}
+
+void
+newport_memcpyw(unsigned short *to, unsigned short *from, unsigned int count)
+{
+ if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS) {
+ memcpy(to, from, count);
+ return;
+ }
+ if ((unsigned long) to + count > video_mem_term ||
+ (unsigned long) to < video_mem_base) {
+ if ((unsigned long) to + count <= video_mem_term ||
+ (unsigned long) to > video_mem_base)
+ memcpy(to, from, count);
+ else {
+ count /= 2;
+ while (count) {
+ count--;
+ scr_writew(scr_readw(from++), to++);
+ }
+ }
+ } else {
+ count /= 2;
+ while (count) {
+ count--;
+ if (*to != *from) {
+ newport_blitc(*from, (unsigned long)to);
+ *to++ = *from++;
+ } else {
+ from++;
+ to++;
+ }
+ }
+ }
+}
+
+struct console_ops newport_console = {
+ newport_set_origin,
+ newport_hide_cursor,
+ newport_set_cursor,
+ newport_get_scrmem,
+ newport_set_scrmem,
+ newport_set_get_cmap,
+ newport_blitc,
+ newport_memsetw,
+ newport_memcpyw
+};
+
+/* Currently hard-coded values that are the same as those found on my system */
+struct ng1_info newport_board_info = {
+ { "NG1", "" /* what is the label? */, 1280, 1024, sizeof (struct ng1_info) },
+ 6, /* boardrev */
+ 1, /* rex3rev */
+ 0, /* vc2rev */
+ 2, /* monitor type */
+ 0, /* videoinstalled */
+ 3, /* mcrev */
+ 24, /* bitplanes */
+ 0, /* xmap9rev */
+ 2, /* cmaprev */
+ { 256, 1280, 1024, 76}, /* ng1_vof_info */
+ 13, /* paneltype */
+ 0
+};
+
+void
+newport_reset (void)
+{
+ newport_wait();
+ newport_enable_video();
+
+ /* Init the cursor disappear. */
+ newport_wait();
+#if 0
+ newport_init_cursor();
+#else
+ newport_disable_cursor();
+#endif
+
+ newport_init_cmap();
+
+ /* Clear the screen. */
+ newport_clear_screen();
+}
+
+/* right now the newport does not do anything at all */
+struct graphics_ops newport_graphic_ops = {
+ 0, /* owner */
+ 0, /* current user */
+ (void *) &newport_board_info, /* board info */
+ sizeof (struct ng1_info), /* size of our data structure */
+ 0, 0, /* g_regs, g_regs_size */
+ newport_save, newport_restore, /* g_save_context, g_restore_context */
+ newport_reset, newport_ioctl /* g_reset_console, g_ioctl */
+};
+
+struct graphics_ops *
+newport_probe (int slot, const char **name)
+{
+ struct newport_regs *p;
+
+ npregs = (struct newport_regs *) (KSEG1 + 0x1f0f0000);
+
+ p = npregs;
+ p->cset.config = NPORT_CFG_GD0;
+
+ if(newport_wait()) {
+ prom_printf("whoops, timeout, no NEWPORT there?");
+ return 0;
+ }
+
+ p->set.xstarti = TESTVAL; if(p->set._xstart.i != XSTI_TO_FXSTART(TESTVAL)) {
+ prom_printf("newport_probe: read back wrong value ;-(\n");
+ return 0;
+ }
+
+ if (slot == 0){
+ register_gconsole (&newport_console);
+ video_type = VIDEO_TYPE_SGI;
+ can_do_color = 1;
+ *name = "NEWPORT";
+ }
+
+ newport_reset ();
+ newport_render_version();
+#if 0
+ newport_render_logo();
+#endif
+ newport_graphic_ops.g_regs = 0x1f0f0000;
+ newport_graphic_ops.g_regs_size = sizeof (struct newport_regs);
+ return &newport_graphic_ops;
+}
+/*
+ * cons_newport.c: Newport graphics console code for the SGI.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: cons_newport.c,v 1.6 1997/09/21 23:00:01 miguel Exp $
*/
#include <linux/kernel.h>