linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHSET 25/25] add support for PC-9800 architecture (video)
@ 2002-10-18 16:56 Osamu Tomita
  0 siblings, 0 replies; only message in thread
From: Osamu Tomita @ 2002-10-18 16:56 UTC (permalink / raw)
  To: LKML; +Cc: Linus Torvalds

This is part 26/26 of patchset for add support NEC PC-9800 architecture,
against 2.5.43.

Summary:
 New driver support for PC-9800 standard text console.

diffstat:
 drivers/video/gdccon.c |  963 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/asm-i386/gdc.h |  225 +++++++++++
 2 files changed, 1188 insertions(+)

patch:
diff -urN linux/drivers/video/gdccon.c linux98/drivers/video/gdccon.c
--- linux/drivers/video/gdccon.c	Thu Jan  1 09:00:00 1970
+++ linux98/drivers/video/gdccon.c	Sun Sep  8 19:09:48 2002
@@ -0,0 +1,963 @@
+/*
+ * linux/drivers/video/gdccon.c
+ * Low level GDC based console driver for NEC PC-9800 series
+ *
+ * Created 24 Dec 1998 by Linux/98 project
+ *
+ * based on:
+ * linux/drivers/video/vgacon.c in Linux 2.1.131 by Geert Uytterhoeven
+ * linux/char/gdc.c in Linux/98 2.1.57 by Linux/98 project
+ * linux/char/console.c in Linux/98 2.1.57 by Linux/98 project
+ */
+
+/*
+#define GDCCON_DEBUG_MEMFUNCS
+#define VRAM_OVERRUN_DEBUG
+*/
+
+#ifdef VRAM_OVERRUN_DEBUG
+# define NEED_UNMAP_PHYSPAGE
+#endif
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/console_struct.h>
+#include <linux/string.h>
+#include <linux/kd.h>
+#include <linux/slab.h>
+#include <linux/vt_kern.h>
+#include <linux/selection.h>
+#include <linux/spinlock.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pc9800.h>
+
+#ifdef VRAM_OVERRUN_DEBUG
+# include <asm/pc9800_debug.h>
+#endif
+
+static spinlock_t gdc_lock = SPIN_LOCK_UNLOCKED;
+
+static struct resource gdc_console_resource[3] = {
+    {"GDC (master)", 0x60, 0x6e, IORESOURCE98_SPARSE},
+    {"crtc", 0x70, 0x7a, IORESOURCE98_SPARSE},
+    {"GDC (slave)", 0xa0, 0xa6, IORESOURCE98_SPARSE},
+};
+
+#define BLANK 0x0020
+#define BLANK_ATTR 0x00e1
+
+/* GDC/GGDC port# */
+#define GDC_COMMAND 0x62
+#define GDC_PARAM 0x60
+#define GDC_STAT 0x60
+#define GDC_DATA 0x62
+
+#define MODE_FF1	(0x0068)	/* mode F/F register 1 */
+
+#define  MODE_FF1_ATR_SEL	(0x00)	/* 0: vertical line 1: 8001 graphic */
+#define  MODE_FF1_GRAPHIC_MODE	(0x02)	/* 0: color 1: mono */
+#define  MODE_FF1_COLUMN_WIDTH	(0x04)	/* 0: 80col 1: 40col */
+#define  MODE_FF1_FONT_SEL	(0x06)	/* 0: 6x8 1: 7x13 */
+#define  MODE_FF1_GRP_MODE	(0x08)	/* 0: display odd-y raster 1: not */
+#define  MODE_FF1_KAC_MODE	(0x0a)	/* 0: code access 1: dot access */
+#define  MODE_FF1_NVMW_PERMIT	(0x0c)	/* 0: protect 1: permit */
+#define  MODE_FF1_DISP_ENABLE	(0x0e)	/* 0: enable 1: disable */
+
+#define GGDC_COMMAND 0xa2
+#define GGDC_PARAM 0xa0
+#define GGDC_STAT 0xa0
+#define GGDC_DATA 0xa2
+
+/* GDC status */
+#define GDC_DATA_READY		(1 << 0)
+#define GDC_FIFO_FULL		(1 << 1)
+#define GDC_FIFO_EMPTY		(1 << 2)
+#define GGDC_FIFO_EMPTY		GDC_FIFO_EMPTY
+#define GDC_DRAWING		(1 << 3)
+#define GDC_DMA_EXECUTE		(1 << 4)	/* nonsense on 98 */
+#define GDC_VERTICAL_SYNC	(1 << 5)
+#define GDC_HORIZONTAL_BLANK	(1 << 6)
+#define GDC_LIGHTPEN_DETECT	(1 << 7)	/* nonsense on 98 */
+
+#define ATTR_G		(1U << 7)
+#define ATTR_R		(1U << 6)
+#define ATTR_B		(1U << 5)
+#define ATTR_GRAPHIC	(1U << 4)
+#define ATTR_VERTBAR	ATTR_GRAPHIC	/* vertical bar */
+#define ATTR_UNDERLINE	(1U << 3)
+#define ATTR_REVERSE	(1U << 2)
+#define ATTR_BLINK	(1U << 1)
+#define ATTR_NOSECRET	(1U << 0)
+#define AMASK_NOCOLOR	(ATTR_GRAPHIC | ATTR_UNDERLINE | ATTR_REVERSE \
+			 | ATTR_BLINK | ATTR_NOSECRET)
+
+/*
+ *  Interface used by the world
+ */
+static const char *gdccon_startup(void);
+static void gdccon_init(struct vc_data *c, int init);
+static void gdccon_deinit(struct vc_data *c);
+static void gdccon_cursor(struct vc_data *c, int mode);
+static int gdccon_switch(struct vc_data *c);
+static int gdccon_blank(struct vc_data *c, int blank);
+static int gdccon_scrolldelta(struct vc_data *c, int lines);
+static int gdccon_set_origin(struct vc_data *c);
+static void gdccon_save_screen(struct vc_data *c);
+static int gdccon_scroll(struct vc_data *c, int t, int b, int dir, int lines);
+static u8 gdccon_build_attr(struct vc_data *c, u8 color, u8 intensity, u8 blink, u8 underline, u8 reverse);
+static void gdccon_invert_region(struct vc_data *c, u16 *p, int count);
+static unsigned long gdccon_uni_pagedir[2];
+
+/* Description of the hardware situation */
+static unsigned long   gdc_vram_base;		/* Base of video memory */
+static unsigned long   gdc_vram_end;		/* End of video memory */
+static unsigned int    gdc_video_num_columns = 80;
+						/* Number of text columns */
+static unsigned int    gdc_video_num_lines = 25;
+						/* Number of text lines */
+static int	       gdc_can_do_color = 1;	/* Do we support colors? */
+static unsigned char   gdc_video_type;		/* Card type */
+static unsigned char   gdc_hardscroll_enabled;
+static unsigned char   gdc_hardscroll_user_enable = 1;
+static int	       gdc_vesa_blanked = 0;
+static unsigned int    gdc_rolled_over = 0;
+
+#define DISP_FREQ_AUTO 0
+#define DISP_FREQ_25k  1
+#define DISP_FREQ_31k  2
+
+static unsigned int    gdc_disp_freq = DISP_FREQ_AUTO;
+
+#define gdc_attr_offset(x) ((typeof(x))((unsigned long)(x)+0x2000))
+
+#define	gdc_outb(val, port)	outb_p((val), (port))
+#define	gdc_inb(port)		inb_p(port)
+
+#define __gdc_write_command(cmd)	gdc_outb((cmd), GDC_COMMAND)
+#define __gdc_write_param(param)	gdc_outb((param), GDC_PARAM)
+
+static const char * __init gdccon_startup(void)
+{
+	const char *display_desc = NULL;
+	unsigned long hdots = gdc_video_num_lines * 16;
+
+	while (!(inb_p(GDC_STAT) & GDC_FIFO_EMPTY));
+	while (!(inb_p(GGDC_STAT) & GDC_FIFO_EMPTY));
+	spin_lock_irq(&gdc_lock);	
+	outb_p(0x0c, GDC_COMMAND);	/* STOP */
+	outb_p(0x0c, GGDC_COMMAND);	/* STOP */
+	if (PC9800_9821_P() && gdc_disp_freq == DISP_FREQ_AUTO) {
+		if (gdc_video_num_lines >= 30 || (inb(0x9a8) & 0x01)) {
+			gdc_disp_freq = DISP_FREQ_31k;
+		}
+	}
+
+	if (PC9800_9821_P() && gdc_disp_freq == DISP_FREQ_31k) {
+		outb_p(0x01, 0x9a8);   /* 31.47KHz */
+		outb_p(0x0e, GDC_COMMAND);  /* SYNC, DE deny */
+		outb_p(0x00, GDC_PARAM);  /* CHR, F, I, D, G, S = 0 */
+		outb_p(0x4e, GDC_PARAM);  /* C/R = 78 (80 chars) */
+		outb_p(0x4b, GDC_PARAM);  /* VSL = 2(3) ; HS = 11 */
+		outb_p(0x0c, GDC_PARAM);  /* HFP = 3    ; VSH = 0(VS=2) */
+		outb_p(0x03, GDC_PARAM);  /* DS, PH = 0 ; HBP = 3 */
+		outb_p(0x06, GDC_PARAM);  /* VH, VL = 0 ; VFP = 6 */
+		outb_p(hdots & 0xff, GDC_PARAM);  /* LFL */
+		outb_p(0x94 | ((hdots >> 8) & 0x03), GDC_PARAM);
+						/* VBP = 37   ; LFH */
+		outb_p(0x47, GDC_COMMAND);  /* PITCH */
+		outb_p(0x50, GDC_PARAM);
+
+		outb_p(0x70, GDC_COMMAND);  /* SCROLL */
+		outb_p(0x00, GDC_PARAM);
+		outb_p(0x00, GDC_PARAM);
+		outb_p((hdots << 4) & 0xf0, GDC_PARAM);  /* SL1=592 (0x250) */
+		outb_p((hdots >> 4) & 0x3f, GDC_PARAM);
+
+		outb_p(0x0e, GGDC_COMMAND);  /* SYNC, DE deny */
+		outb_p(0x00, GGDC_PARAM);  /* CHR, F, I, D, G, S = 0 */
+		outb_p(0x4e, GGDC_PARAM);  /* C/R = 78 (80 chars) */
+		outb_p(0x4b, GGDC_PARAM);  /* VSL = 2(3) ; HS = 11 */
+		outb_p(0x0c, GGDC_PARAM);  /* HFP = 3    ; VSH = 0(VS=2) */
+		outb_p(0x03, GGDC_PARAM);  /* DS, PH = 0 ; HBP = 3 */
+		outb_p(0x06, GGDC_PARAM);  /* VH, VL = 0 ; VFP = 6 */
+		outb_p(hdots & 0xff, GGDC_PARAM);  /* LFL */
+		outb_p(0x94 | ((hdots >> 8) & 0x03), GGDC_PARAM);
+						/* VBP = 37   ; LFH */
+	} else {
+		outb_p(0x00, 0x9a8);   /* 24.83 KHz */
+		outb_p(0x0e, GDC_COMMAND);  /* SYNC, DE deny */
+		outb_p(0x00, GDC_PARAM);  /* CHR, F, I, D, G, S = 0 */
+		outb_p(0x4e, GDC_PARAM);  /* C/R = 78 (80 chars) */
+		outb_p(0x07, GDC_PARAM);  /* VSL = 0(3) ; HS = 7 */
+		outb_p(0x25, GDC_PARAM);  /* HFP = 9    ; VSH = 1(VS=8) */
+		outb_p(0x07, GDC_PARAM);  /* DS, PH = 0 ; HBP = 7 */
+		outb_p(0x07, GDC_PARAM);  /* VH, VL = 0 ; VFP = 7 */
+		outb_p(hdots & 0xff, GDC_PARAM);  /* LFL */
+		outb_p(0x64 | ((hdots >> 8) & 0x03), GDC_PARAM);
+						/* VBP = 25   ; LFH */
+		outb_p(0x47, GDC_COMMAND);  /* PITCH */
+		outb_p(0x50, GDC_PARAM);
+
+		outb_p(0x70, GDC_COMMAND);  /* SCROLL */
+		outb_p(0x00, GDC_PARAM);
+		outb_p(0x00, GDC_PARAM);
+		outb_p((hdots << 4) & 0xf0, GDC_PARAM);  /* SL1=592 (0x250) */
+		outb_p((hdots >> 4) & 0x3f, GDC_PARAM);
+
+		outb_p(0x0e, GGDC_COMMAND);  /* SYNC */
+		outb_p(0x00, GGDC_PARAM);
+		outb_p(0x4e, GGDC_PARAM);
+		outb_p(0x07, GGDC_PARAM);
+		outb_p(0x25, GGDC_PARAM);
+		outb_p(0x07, GGDC_PARAM);
+		outb_p(0x07, GGDC_PARAM);
+		outb_p(hdots & 0xff, GGDC_PARAM);  /* LFL */
+		outb_p(0x64 | ((hdots >> 8) & 0x03), GGDC_PARAM);
+						/* VBP = 25   ; LFH */
+	}
+
+	outb_p(0x47, GGDC_COMMAND);  /* PITCH */ 
+	outb_p(0x28, GGDC_PARAM);
+
+	outb_p(0x0d, GDC_COMMAND);	/* START */
+	outb_p(0x0d, GGDC_COMMAND);	/* START */
+	spin_unlock_irq(&gdc_lock);	
+
+	gdc_vram_base = (unsigned long)phys_to_virt(0xa0000);
+	/* Last few bytes of text VRAM area are for NVRAM. */
+	gdc_vram_end = gdc_vram_base + 0x1fe0;
+
+	if (!PC9800_HIGHRESO_P()) {
+		gdc_video_type = VIDEO_TYPE_98NORMAL;
+		display_desc = "NEC PC-9800 Normal";
+	} else {
+		gdc_video_type = VIDEO_TYPE_98HIRESO;
+		display_desc = "NEC PC-9800 High Resolution";
+	}
+
+	gdc_hardscroll_enabled = gdc_hardscroll_user_enable;
+	
+	request_resource(&ioport_resource, &gdc_console_resource[0]);
+	request_resource(&ioport_resource, &gdc_console_resource[1]);
+	request_resource(&ioport_resource, &gdc_console_resource[2]);
+
+	return display_desc;
+}
+
+#ifdef VRAM_OVERRUN_DEBUG
+static int __init gdccon_setup_trap(void)
+{
+	/*
+	 * Trap scr_mem{move,set,...} overrun by unmapping memory page.
+	 * If kernel hits these pages, page fault are triggered and
+	 * then kernel forces oops.
+	 */
+	unmap_physpage(GDC_MAP_MEM(0x9f000));
+	unmap_physpage(GDC_MAP_MEM(0xa6000));
+
+	printk(KERN_DEBUG "gdccon: overrun trap code activated\n");
+	return 0;
+}
+
+/*
+ * Call gdccon_setup_trap() while normal driver setup, as gdccon_startup()
+ * may be called while bootup temporary page table is in use. (Is this true?)
+ */
+__initcall (gdccon_setup_trap);
+#endif
+
+static void gdccon_init(struct vc_data *c, int init)
+{
+	unsigned long p;
+	
+	/* We cannot be loaded as a module, therefore init is always 1 */
+	c->vc_can_do_color = gdc_can_do_color;
+	c->vc_cols = gdc_video_num_columns;
+	c->vc_rows = gdc_video_num_lines;
+	c->vc_complement_mask = ATTR_REVERSE;
+	p = *c->vc_uni_pagedir_loc;
+	if (c->vc_uni_pagedir_loc == &c->vc_uni_pagedir
+	    || !--c->vc_uni_pagedir_loc[1])
+		con_free_unimap(c->vc_num);
+
+	c->vc_uni_pagedir_loc = gdccon_uni_pagedir;
+#ifdef PC9800_GDCCON_DEBUG
+	printk(KERN_DEBUG "%s: #%u: %scolor, %ux%u, uni %p\n",
+		__FUNCTION__, c->vc_num, "!" + !!c->vc_can_do_color,
+		c->vc_cols, c->vc_rows, c->vc_uni_pagedir_loc);
+#endif
+	gdccon_uni_pagedir[1]++;
+	if (!gdccon_uni_pagedir[0] && p)
+		con_set_default_unimap(c->vc_num);
+}
+
+static inline void gdc_set_mem_top(struct vc_data *c)
+{
+	unsigned long flags;
+	unsigned long origin = (c->vc_visible_origin - gdc_vram_base) / 2;
+
+	spin_lock_irqsave(&gdc_lock, flags);
+	while (!(inb_p(GDC_STAT) & GDC_FIFO_EMPTY));
+	__gdc_write_command(0x70);			/* SCROLL */
+	__gdc_write_param(origin);			/* SAD1 (L) */
+	__gdc_write_param((origin >> 8) & 0x1f);	/* SAD1 (H) */
+	spin_unlock_irqrestore(&gdc_lock, flags);
+}
+
+static void gdccon_deinit(struct vc_data *c)
+{
+	/* When closing the last console, reset video origin */
+	if (!--gdccon_uni_pagedir[1]) {
+		c->vc_visible_origin = gdc_vram_base;
+		gdc_set_mem_top(c);
+		con_free_unimap(c->vc_num);
+	}
+
+	c->vc_uni_pagedir_loc = &c->vc_uni_pagedir;
+	con_set_default_unimap(c->vc_num);
+}
+
+#if 0
+/* Translate ANSI terminal color code to GDC color code.  */
+#define BGR_TO_GRB(bgr)	((((bgr) & 4) >> 2) | (((bgr) & 3) << 1))
+#else
+#define RGB_TO_GRB(rgb)	((((rgb) & 4) >> 1) | (((rgb) & 2) << 1) | ((rgb) & 1))
+#endif
+
+static const u8 gdccon_color_table[] = {
+#define C(color)	((RGB_TO_GRB (color) << 5) | ATTR_NOSECRET)
+	C(0), C(1), C(2), C(3), C(4), C(5), C(6), C(7)
+#undef C
+};
+
+static u8 gdccon_build_attr(struct vc_data *c, u8 color, u8 intensity, u8 blink, u8 underline, u8 reverse)
+{
+	u8 attr = gdccon_color_table[color & 0x07];
+
+	if (!gdc_can_do_color)
+		attr = (intensity == 0 ? 0x61
+			: intensity == 2 ? 0xe1 : 0xa1);
+
+	if (underline)
+		attr |= 0x08;
+
+	/* ignore intensity */
+#if 0
+	if(intensity == 0)
+		;
+	else if (intensity == 2)
+		attr |= 0x10; /* virtical line */
+#else
+	if (intensity == 0) {
+		if (attr == c->vc_def_attr)
+			attr = c->vc_half_attr;
+		else
+			attr |= c->vc_half_attr & AMASK_NOCOLOR;
+	} else if (intensity == 2) {
+		if (attr == c->vc_def_attr)
+			attr = c->vc_bold_attr;
+		else
+			attr |= c->vc_bold_attr & AMASK_NOCOLOR;
+	}
+#endif
+	if (reverse)
+		attr |= ATTR_REVERSE;
+
+	if ((color & 0x07) == 0) {	/* foreground color == black */
+		/* Fake background color by reversed character
+		   as GDC cannot set background color.  */
+		attr |= gdccon_color_table[(color >> 4) & 0x07];
+		attr ^= ATTR_REVERSE;
+	}
+
+	if (blink)
+		attr |= ATTR_BLINK;
+
+	return attr;
+}
+
+static void gdccon_invert_region(struct vc_data *c, u16 *p, int count)
+{
+	while (count--) {
+		u16 a = scr_readw(gdc_attr_offset(p));
+
+		a ^= ATTR_REVERSE;
+		scr_writew(a, gdc_attr_offset(p));
+		p++;
+	}
+}
+
+static u8 gdc_csrform_lr = 15;			/* Lines/Row */
+static u16 gdc_csrform_bl_bd = ((12 << 6)	/* BLinking Rate */
+				| (0 << 5));	/* Blinking Disable */
+
+static inline void gdc_hide_cursor(void)
+{
+    __gdc_write_command(0x4b);		/* CSRFORM */
+    __gdc_write_param(gdc_csrform_lr);	/* CS = 0, CE = 0, L/R = ? */
+}
+
+static inline void gdc_show_cursor(int cursor_start, int cursor_finish)
+{
+    __gdc_write_command(0x4b);		/* CSRFORM */
+    __gdc_write_param(0x80 | gdc_csrform_lr);		/* CS = 1 */
+    __gdc_write_param(cursor_start | gdc_csrform_bl_bd);
+    __gdc_write_param((cursor_finish << 3) | (gdc_csrform_bl_bd >> 8));
+}
+
+static void gdccon_cursor(struct vc_data *c, int mode)
+{
+    unsigned long flags;
+    u16 ead;
+
+    if (c->vc_origin != c->vc_visible_origin)
+	gdccon_scrolldelta(c, 0);
+
+    spin_lock_irqsave(&gdc_lock, flags);
+    while (!(inb_p(GDC_STAT) & GDC_FIFO_EMPTY));
+    spin_unlock_irqrestore(&gdc_lock, flags);
+    switch (mode) {
+	case CM_ERASE:
+	    gdc_hide_cursor();
+	    break;
+
+	case CM_MOVE:
+	case CM_DRAW:
+	    switch (c->vc_cursor_type & 0x0f) {
+		case CUR_UNDERLINE:
+		    gdc_show_cursor(14, 15);	/* XXX font height */
+		    break;
+
+		case CUR_TWO_THIRDS:
+		    gdc_show_cursor(5, 15);	/* XXX */
+		    break;
+
+		case CUR_LOWER_THIRD:
+		    gdc_show_cursor(11, 15);	/* XXX */
+		    break;
+
+		case CUR_LOWER_HALF:
+		    gdc_show_cursor(8, 15);	/* XXX */
+		    break;
+
+		case CUR_NONE:
+		    gdc_hide_cursor();
+		    break;
+
+          	default:
+		    gdc_show_cursor(0, 15);	/* XXX */
+		    break;
+	    }
+
+	    spin_lock_irqsave(&gdc_lock, flags);
+	    __gdc_write_command(0x49);		/* CSRW */
+	    ead = (c->vc_pos - gdc_vram_base) >> 1;
+	    __gdc_write_param(ead);
+	    __gdc_write_param((ead >> 8) & 0x1f);
+	    spin_unlock_irqrestore(&gdc_lock, flags);
+	    break;
+    }
+
+}
+
+static int gdccon_switch(struct vc_data *c)
+{
+	/*
+	 * We need to save screen size here as it's the only way
+	 * we can spot the screen has been resized and we need to
+	 * set size of freshly allocated screens ourselves.
+	 */
+	gdc_video_num_columns = c->vc_cols;
+	gdc_video_num_lines = c->vc_rows;
+#if 0
+	printk(KERN_DEBUG
+		"%s: c=%p {origin=%#x, screenbuf=%#x, screenbuf_size=%u\n",
+		__FUNCTION__, c,
+		c->vc_origin, c->vc_screenbuf, c->vc_screenbuf_size);
+#endif
+	if (c->vc_origin != (unsigned long)c->vc_screenbuf
+	    && gdc_vram_base <= c->vc_origin && c->vc_origin < gdc_vram_end) {
+		scr_memcpyw_to((u16 *)c->vc_origin,
+				(u16 *)c->vc_screenbuf,
+				c->vc_screenbuf_size);
+		scr_memcpyw_to((u16 *)gdc_attr_offset(c->vc_origin),
+				(u16 *)((char *)c->vc_screenbuf
+					 + c->vc_screenbuf_size),
+				c->vc_screenbuf_size);
+	} else
+		printk(KERN_WARNING
+			"gdccon: switch (vc #%d) called on origin=%lx\n",
+			c->vc_num, c->vc_origin);
+
+	return 0;	/* Redrawing not needed */
+}
+
+static int gdccon_set_palette(struct vc_data *c, unsigned char *table)
+{
+	return -EINVAL;
+}
+
+#define RELAY0		0x01
+#define RELAY0_GDC	0x00
+#define RELAY0_ACCEL	0x01
+#define RELAY1		0x02
+#define RELAY1_INTERNAL	0x00
+#define RELAY1_EXTERNAL	0x02
+#define IO_RELAY	0x0fac
+#define IO_DPMS		0x09a2
+static unsigned char relay_mode = RELAY0_GDC | RELAY1_INTERNAL;
+
+static void gdc_vesa_blank(int mode)
+{
+    unsigned char stat;
+
+    spin_lock_irq(&gdc_lock);
+
+    relay_mode = inb_p(IO_RELAY);
+    if ((relay_mode & (RELAY0 | RELAY1)) != (RELAY0_GDC | RELAY1_INTERNAL)) {
+#ifdef CONFIG_DONTTOUCHRELAY
+	spin_unlock_irq(&gdc_lock);
+	return;
+#else
+	outb_p((relay_mode & ~(RELAY0 | RELAY1)) |
+	       RELAY0_GDC | RELAY1_INTERNAL , IO_RELAY);
+#endif
+    }
+
+    if (mode & VESA_VSYNC_SUSPEND) {
+	stat = inb_p(IO_DPMS);
+	outb_p(stat | 0x80, IO_DPMS);
+    }
+    if (mode & VESA_HSYNC_SUSPEND) {
+	stat = inb_p(IO_DPMS);
+	outb_p(stat | 0x40, IO_DPMS);
+    }
+
+    spin_unlock_irq(&gdc_lock);
+}
+
+static void gdc_vesa_unblank(void)
+{
+    unsigned char stat;
+
+#ifdef CONFIG_DONTTOUCHRELAY
+    if (relay_mode & (RELAY0 | RELAY1))
+	return;
+#endif
+
+    spin_lock_irq(&gdc_lock);
+
+    stat = inb_p(0x09a2);
+    outb_p(stat & ~0xc0, IO_DPMS);
+    if (relay_mode & (RELAY0 | RELAY1))
+	outb_p(relay_mode, IO_RELAY);
+
+    spin_unlock_irq(&gdc_lock);
+}
+
+static int gdccon_blank(struct vc_data *c, int blank)
+{
+	switch (blank) {
+	case 0:				/* Unblank */
+		if (gdc_vesa_blanked) {
+			gdc_vesa_unblank();
+			gdc_vesa_blanked = 0;
+		}
+
+		outb(MODE_FF1_DISP_ENABLE | 1, MODE_FF1);
+
+		/* Tell console.c that it need not to restore the screen */
+		return 0;
+
+	case 1:				/* Normal blanking */
+		/* Disable displaying */
+		outb(MODE_FF1_DISP_ENABLE | 0, MODE_FF1);
+
+		/* Tell console.c that it need not to reset origin */
+		return 0;
+
+	case -1:			/* Entering graphic mode */
+		return 1;
+
+	default:			/* VESA blanking */
+		if (gdc_video_type == VIDEO_TYPE_98NORMAL
+		    || gdc_video_type == VIDEO_TYPE_9840
+		    || gdc_video_type == VIDEO_TYPE_98HIRESO) {
+			gdc_vesa_blank(blank - 1);
+			gdc_vesa_blanked = blank;
+		}
+
+		return 0;
+	}
+}
+
+static int gdccon_font_op(struct vc_data *c, struct console_font_op *op)
+{
+	return -ENOSYS;
+}
+
+/*
+#define PC9800_GDCCON_DEBUG 1
+*/
+
+static int gdccon_scrolldelta(struct vc_data *c, int lines)
+{
+#ifdef PC9800_GDCCON_DEBUG
+	printk("gdccon_scrolldelta: lines=%d", lines);
+#endif
+
+	if (!lines)			/* Turn scrollback off */
+		c->vc_visible_origin = c->vc_origin;
+	else {
+		int vram_size = gdc_vram_end - gdc_vram_base;
+		int margin = c->vc_size_row /* * 4 */;
+		int ul, we, p, st;
+
+#ifdef PC9800_GDCCON_DEBUG
+		printk(", gdc_vram_base=0x%lx, gdc_vram_end=0x%lx",
+			__pa(gdc_vram_base), __pa(gdc_vram_end));
+		printk(", vram_size=%d, margin=%d", vram_size, margin);
+		printk(", c->vc_origin=0x%lx, c->vc_visible_origin=0x%lx, "
+			"c->vc_scr_end=0x%lx", __pa(c->vc_origin),
+			__pa(c->vc_visible_origin), __pa(c->vc_scr_end));
+		printk(", c->vc_size_row=%u, gdc_rolled_over=%u",
+			c->vc_size_row, gdc_rolled_over);
+#endif
+		if (gdc_rolled_over > c->vc_scr_end - gdc_vram_base + margin) {
+			ul = c->vc_scr_end - gdc_vram_base;
+			we = gdc_rolled_over + c->vc_size_row;
+		} else {
+			ul = 0;
+			we = vram_size;
+		}
+
+		p = (c->vc_visible_origin - gdc_vram_base - ul + we)
+			% we + lines * c->vc_size_row;
+		st = (c->vc_origin - gdc_vram_base - ul + we) % we;
+#ifdef PC9800_GDCCON_DEBUG
+		printk(", ul=%d, we=%d", ul, we);
+		printk(", p=%d, st=%d", p, st);
+#endif
+		if (p < margin)
+			p = 0;
+
+		if (p > st - margin)
+			p = st;
+#ifdef PC9800_GDCCON_DEBUG
+		printk(", p(new)=%d", p);
+#endif
+		c->vc_visible_origin = gdc_vram_base + (p + ul) % we;
+	}
+
+	gdc_set_mem_top(c);
+#ifdef PC9800_GDCCON_DEBUG
+	printk(", c->vc_visible_origin(new)=0x%lx, done.\n",
+		__pa(c->vc_visible_origin));
+#endif
+	return 1;
+}
+
+#undef PC9800_GDCCON_DEBUG
+
+static int gdccon_set_origin(struct vc_data *c)
+{
+#ifdef PC9800_GDCCON_DEBUG
+	printk(KERN_DEBUG "%s: c=%p, console_blanked=%d\n",
+		__FUNCTION__, c, console_blanked);
+#endif
+#if 0 /* It is now Ok to write to blanked screens,
+	 since output from video controller is cut off */
+	if (console_blanked)	/* We are writing to blanked screens */
+		return 0;
+#endif
+
+	c->vc_origin = c->vc_visible_origin = gdc_vram_base;
+	gdc_set_mem_top(c);
+	gdc_rolled_over = 0;
+	return 1;
+}
+
+static void gdccon_save_screen(struct vc_data *c)
+{
+	static int gdc_bootup_console = 0;
+
+	if (!gdc_bootup_console) {
+		/* This is a gross hack, but here is the only place we can
+		 * set bootup console parameters without messing up generic
+		 * console initialization routines.
+		 */
+		gdc_bootup_console = 1;
+		c->vc_x = ORIG_X;
+		c->vc_y = ORIG_Y;
+	}
+
+	scr_memcpyw_from((u16 *)c->vc_screenbuf,
+				(u16 *)c->vc_origin, c->vc_screenbuf_size);
+	scr_memcpyw_from((u16 *)((char *)c->vc_screenbuf + c->vc_screenbuf_size), (u16 *)gdc_attr_offset(c->vc_origin), c->vc_screenbuf_size);
+}
+
+static int gdccon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
+{
+	unsigned long oldo;
+	unsigned int delta;
+
+	if (t || b != c->vc_rows)
+		return 0;
+
+	if (c->vc_origin != c->vc_visible_origin)
+		gdccon_scrolldelta(c, 0);
+
+	if (!gdc_hardscroll_enabled || lines >= c->vc_rows / 2)
+		return 0;
+
+	oldo = c->vc_origin;
+	delta = lines * c->vc_size_row;
+	if (dir == SM_UP) {
+		if (c->vc_scr_end + delta >= gdc_vram_end) {
+			scr_memcpyw((u16 *)gdc_vram_base,
+				    (u16 *)(oldo + delta),
+				    c->vc_screenbuf_size - delta);
+			scr_memcpyw((u16 *)gdc_attr_offset(gdc_vram_base),
+				    (u16 *)gdc_attr_offset(oldo + delta),
+				    c->vc_screenbuf_size - delta);
+			c->vc_origin = gdc_vram_base;
+			gdc_rolled_over = oldo - gdc_vram_base;
+		} else
+			c->vc_origin += delta;
+
+		scr_memsetw((u16 *)(c->vc_origin + c->vc_screenbuf_size - delta), c->vc_video_erase_char, delta);
+		scr_memsetw((u16 *)gdc_attr_offset(c->vc_origin + c->vc_screenbuf_size - delta), c->vc_video_erase_attr, delta);
+	} else {
+		if (oldo - delta < gdc_vram_base) {
+#if 0
+			printk(KERN_DEBUG
+				"gdc_vram_base = %#lx, gdc_vram_end = %#lx\n",
+				gdc_vram_base, gdc_vram_end);
+#endif
+			scr_memmovew((u16 *)(gdc_vram_end - c->vc_screenbuf_size + delta),
+				     (u16 *)oldo,
+				     c->vc_screenbuf_size - delta);
+			scr_memmovew((u16 *)gdc_attr_offset(gdc_vram_end - c->vc_screenbuf_size + delta),
+				     (u16 *)gdc_attr_offset(oldo),
+				     c->vc_screenbuf_size - delta);
+			c->vc_origin = gdc_vram_end - c->vc_screenbuf_size;
+			gdc_rolled_over = 0;
+		} else
+			c->vc_origin -= delta;
+
+		c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
+#if 0
+		printk(KERN_DEBUG "scr_memsetw(%p, %#x, %u)\n",
+			c->vc_origin, c->vc_video_erase_char, delta);
+#endif
+		scr_memsetw((u16 *)(c->vc_origin), c->vc_video_erase_char,
+				delta);
+#if 0
+		printk(KERN_DEBUG "scr_memsetw(%p, %#x, %u)\n",
+			gdc_attr_offset(c->vc_origin), c->vc_video_erase_attr,
+			delta);
+#endif
+		scr_memsetw((u16 *)gdc_attr_offset(c->vc_origin),
+				c->vc_video_erase_attr, delta);
+	}
+
+	c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
+	c->vc_visible_origin = c->vc_origin;
+	gdc_set_mem_top(c);
+	c->vc_pos = (c->vc_pos - oldo) + c->vc_origin;
+	return 1;
+}
+
+static int gdccon_setterm_command(struct vc_data *c)
+{
+	switch (c->vc_par[0]) {
+	case 1: /* set attr for underline mode */
+		if (c->vc_npar < 2) {
+			if (c->vc_par[1] < 16)
+				c->vc_ul_attr = gdccon_color_table[color_table[c->vc_par[1]] & 7];
+		} else {
+			if (c->vc_par[2] < 256)
+				c->vc_ul_attr = c->vc_par[2];
+		}
+
+		if (c->vc_underline)
+			goto update_attr;
+
+		return 1;
+
+	case 2:	/* set attr for half intensity mode */
+		if (c->vc_npar < 2) {
+			if (c->vc_par[1] < 16)
+				c->vc_half_attr = gdccon_color_table[color_table[c->vc_par[1]] & 7];
+		}
+		else {
+			if (c->vc_par[2] < 256)
+				c->vc_half_attr = c->vc_par[2];
+		}
+
+		if (c->vc_intensity == 0)
+			goto update_attr;
+
+		return 1;
+
+	case 3: /* set color for bold mode */
+		if (c->vc_npar < 2) {
+			if (c->vc_par[1] < 16)
+				c->vc_bold_attr = gdccon_color_table[color_table[c->vc_par[1]] & 7];
+		} else {
+			if (c->vc_par[2] < 256)
+				c->vc_bold_attr = c->vc_par[2];
+		}
+
+		if (c->vc_intensity == 2)
+			goto update_attr;
+
+		return 1;
+	}
+
+	return 0;
+
+update_attr:
+	c->vc_attr = gdccon_build_attr(c,
+					c->vc_color, c->vc_intensity,
+					c->vc_blink, c->vc_underline,
+					c->vc_reverse);
+	return 1;
+}
+
+/*
+ *  The console `switch' structure for the GDC based console
+ */
+
+static int gdccon_dummy(struct vc_data *c)
+{
+	return 0;
+}
+
+#define DUMMY (void *) gdccon_dummy
+
+const struct consw gdc_con = {
+	.con_startup =		gdccon_startup,
+	.con_init =		gdccon_init,
+	.con_deinit =		gdccon_deinit,
+	.con_clear =		DUMMY,
+	.con_putc =		DUMMY,
+	.con_putcs =		DUMMY,
+	.con_cursor =		gdccon_cursor,
+	.con_scroll =		gdccon_scroll,
+	.con_bmove =		DUMMY,
+	.con_switch =		gdccon_switch,
+	.con_blank =		gdccon_blank,
+	.con_font_op =		gdccon_font_op,
+	.con_set_palette =	gdccon_set_palette,
+	.con_scrolldelta =	gdccon_scrolldelta,
+	.con_set_origin =	gdccon_set_origin,
+	.con_save_screen =	gdccon_save_screen,
+	.con_build_attr =	gdccon_build_attr,
+	.con_invert_region =	gdccon_invert_region,
+	.con_setterm_command =	gdccon_setterm_command
+};
+
+#ifdef GDCCON_DEBUG_MEMFUNCS
+void gdccon_check_address(const void *start, size_t len,
+			   const char *name, const char *function,
+			   const char *file, unsigned int lineno)
+{
+	int i;
+	static int inhibit;
+
+	if (inhibit)
+		return;
+
+	if (gdc_vram_base <= (unsigned long)start
+	    && (unsigned long)start + len <= gdc_vram_end + 0x2000)
+		return;
+
+	for (i = 0; i < MAX_NR_CONSOLES; i++)
+		if (vc_cons[i].d
+		    && (void *)vc_cons[i].d->vc_screenbuf <= start
+		    && start + len <= ((void *)vc_cons[i].d->vc_screenbuf
+				       + vc_cons[i].d->vc_screenbuf_size * 2))
+			return;
+
+	inhibit = 1;
+	if (function)
+		printk(KERN_WARNING "gdccon: In function `%s'\n", function);
+
+	if (file)
+		printk(KERN_WARNING "gdccon: %s:%u", file, lineno);
+	else
+		printk(KERN_WARNING "gdccon");
+
+	printk(": %s address out of range (%p+%u)\nStack: ",
+		name, start, len);
+	show_stack(NULL);
+	printk("\n");
+	inhibit = 0;
+}
+#endif
+
+static int __init gdc_setup(char *str)
+{
+	unsigned long tmp_ulong;
+	char *opt, *orig_opt, *endp;
+
+	while ((opt = strsep(&str, ",")) != NULL) {
+		int force = 0;
+
+		orig_opt = opt;
+		if (!strncmp(opt, "force", 5)) {
+			force = 1;
+			opt += 5;
+		}
+
+		if (!strcmp(opt, "mono"))
+			gdc_can_do_color = 0;
+		else if ((tmp_ulong = simple_strtoul(opt, &endp, 0)) > 0) {
+			if (!strcmp(endp, "lines")
+			    || (!strcmp(endp, "linesforce") && (force == 1))) {
+				if (!force
+				    && (tmp_ulong < 20
+					|| (!PC9800_9821_P()
+					    && 25 < tmp_ulong)
+					|| 37 < tmp_ulong))
+					printk(KERN_ERR
+						"gdccon: %d is out of bound"
+						" for number of lines\n",
+						(int)tmp_ulong);
+				else
+					gdc_video_num_lines = tmp_ulong;
+			} else if (!strcmp(endp, "kHz")) {
+				if (tmp_ulong == 24 || tmp_ulong == 25)
+					gdc_disp_freq = DISP_FREQ_25k;
+				else
+					printk(KERN_ERR "gdccon: `%s' ignored\n",
+						orig_opt);
+			} else
+				printk(KERN_ERR "gdccon: unknown option `%s'\n",
+					orig_opt);
+		} else
+			printk(KERN_ERR "gdccon: unknown option `%s'\n",
+				orig_opt);
+	}
+
+	return 1; 
+}
+
+__setup("gdccon=", gdc_setup);
+\f
+/*
+ * We will follow Linus's indenting style...
+ *
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -urN linux/include/asm-i386/gdc.h linux98/include/asm-i386/gdc.h
--- linux/include/asm-i386/gdc.h	Thu Jan  1 09:00:00 1970
+++ linux98/include/asm-i386/gdc.h	Sun Aug 19 14:13:09 2001
@@ -0,0 +1,225 @@
+/*
+ *  gdc.h - macro & inline functions for accessing GDC text-VRAM
+ *
+ *  Copyright (C) 1997-2000   KITAGAWA Takurou,
+ *			      UGAWA Tomoharu,
+ *			      TAKAI Kosuke
+ *			      (Linux/98 Project)
+ */
+#ifndef _LINUX_ASM_GDC_H_
+#define _LINUX_ASM_GDC_H_
+
+#include <linux/config.h>
+
+#define GDC_MAP_MEM(x) (unsigned long)phys_to_virt(x)
+
+#define gdc_readb(x) (*(x))
+#define gdc_writeb(x,y) (*(y) = (x))
+
+#define VT_BUF_HAVE_RW
+#define scr_writew(val, addr)	(*(volatile __u16 *)(addr) = (val))
+#define scr_readw(addr)		(*(volatile __u16 *)(addr))
+
+#define VT_BUF_HAVE_MEMSETW
+extern inline void
+scr_memsetw(u16 *s, u16 c, unsigned int count)
+{
+#ifdef CONFIG_GDC_32BITACCESS
+	__asm__ __volatile__ ("shr%L1 %1
+	jz 2f
+" /*	cld	kernel code now assumes DF = 0 any time */ "\
+	test%L0 %3,%0
+	jz 1f
+	stos%W2
+	dec%L1 %1
+1:	shr%L1 %1
+	rep
+	stos%L2
+	jnc 2f
+	stos%W2
+	rep
+	stos%W2
+2:"
+			      : "=D"(s), "=c"(count)
+			      : "a"((((u32) c) << 16) | c), "g"(2),
+			        "0"(s), "1"(count));
+#else
+	__asm__ __volatile__ ("rep\n\tstosw"
+			      : "=D"(s), "=c"(count)
+			      : "0"(s), "1"(count / 2), "a"(c));
+#endif	
+}
+
+#define VT_BUF_HAVE_MEMCPYW
+extern inline void
+scr_memcpyw(u16 *d, u16 *s, unsigned int count)
+{
+#if 1 /* def CONFIG_GDC_32BITACCESS */
+	__asm__ __volatile__ ("shr%L2 %2
+	jz 2f
+" /*	cld	*/ "\
+	test%L0 %3,%0
+	jz 1f
+	movs%W0
+	dec%L2 %2
+1:	shr%L2 %2
+	rep
+	movs%L0
+	jnc 2f
+	movs%W0
+2:"
+			      : "=D"(d), "=S"(s), "=c"(count)
+			      : "g"(2), "0"(d), "1"(s), "2"(count));
+#else
+	__asm__ __volatile__ ("rep\n\tmovsw"
+			      : "=D"(d), "=S"(s), "=c"(count)
+			      : "0"(d), "1"(s), "2"(count / 2));
+#endif
+}
+
+extern inline void
+scr_memrcpyw(u16 *d, u16 *s, unsigned int count)
+{
+#if 1 /* def CONFIG_GDC_32BITACCESS */
+	u16 tmp;
+
+	__asm__ __volatile__ ("shr%L3 %3
+	jz 2f
+	std
+	lea%L1 -4(%1,%3,2),%1
+	lea%L2 -4(%2,%3,2),%2
+	test%L1 %4,%1
+	jz 1f
+	mov%W0 2(%2),%0
+	sub%L2 %4,%2
+	dec%L3 %3
+	mov%W0 %0,2(%1)
+	sub%L1 %4,%1
+1:	shr%L3 %3
+	rep
+	movs%L0
+	jnc 3f
+	mov%W0 2(%2),%0
+	mov%W0 %0,2(%1)
+3:	cld
+2:"
+			      : "=r"(tmp), "=D"(d), "=S"(s), "=c"(count)
+			      : "g"(2), "1"(d), "2"(s), "3"(count));
+#else
+	__asm__ __volatile__ ("std\n\trep\n\tmovsw\n\tcld"
+			      : "=D"(d), "=S"(s), "=c"(count)
+			      : "0"((void *) d + count - 2),
+			        "1"((void *) s + count - 2), "2"(count / 2));
+#endif	
+}
+
+#define VT_BUF_HAVE_MEMMOVEW
+extern inline void
+scr_memmovew(u16 *d, u16 *s, unsigned int count)
+{
+	if (d > s)
+		scr_memrcpyw(d, s, count);
+	else
+		scr_memcpyw(d, s, count);
+}	
+
+#define VT_BUF_HAVE_MEMCPYF
+extern inline void
+scr_memcpyw_from(u16 *d, u16 *s, unsigned int count)
+{
+#ifdef CONFIG_GDC_32BITACCESS
+	/* VRAM is quite slow, so we align source pointer (%esi)
+	   to double-word alignment. */
+	__asm__ __volatile__ ("shr%L2 %2
+	jz 2f
+" /*	cld	*/ "\
+	test%L0 %3,%0
+	jz 1f
+	movs%W0
+	dec%L2 %2
+1:	shr%L2 %2
+	rep
+	movs%L0
+	jnc 2f
+	movs%W0
+2:"
+			      : "=D"(d), "=S"(s), "=c"(count)
+			      : "g"(2), "0"(d), "1"(s), "2"(count));
+#else
+	__asm__ __volatile__ ("rep\n\tmovsw"
+			      : "=D"(d), "=S"(s), "=c"(count)
+			      : "0"(d), "1"(s), "2"(count / 2));
+#endif
+}
+
+#ifdef CONFIG_GDC_32BITACCESS
+# define scr_memcpyw_to	scr_memcpyw
+#else
+# define scr_memcpyw_to scr_memcpyw_from
+#endif
+
+/* #define GDCCON_DEBUG_MEMFUNCS */
+#ifdef GDCCON_DEBUG_MEMFUNCS
+
+extern void gdccon_check_address(const void *, size_t, const char *,
+				  const char *, const char *, unsigned int);
+
+#undef scr_writew
+#define scr_writew(val, addr)	({					\
+	__u16 *_p_ = (void *)(addr);					\
+	gdccon_check_address(_p_, 2, "destination",			\
+			      "scr_writew", __FILE__, __LINE__);	\
+	*(volatile __u16 *)_p_ = (val);					\
+})
+
+#undef scr_readw
+#define scr_readw(addr)	({					\
+	__u16 *_p_ = (void *)(addr);				\
+	gdccon_check_address(_p_, 2, "source",			\
+			      "scr_readw", __FILE__, __LINE__);	\
+	*(volatile __u16 *)_p_;					\
+})
+
+#define scr_memsetw(dest, ch, count)	({				\
+	__u16 *_dest_ = (dest);						\
+	size_t _count_ = (count);					\
+	gdccon_check_address(_dest_, _count_, "destitnation",		\
+			      "scr_memsetw", __FILE__, __LINE__);	\
+	scr_memsetw(_dest_, (ch), _count_);				\
+})
+
+#define scr_memcpyw(dest, src, count)	({				\
+	__u16 *_dest_ = (dest);						\
+	__u16 *_src_ = (src);						\
+	size_t _count_ = (count);					\
+	gdccon_check_address(_dest_, _count_, "destitnation",		\
+			      "scr_memcpyw", __FILE__, __LINE__);	\
+	gdccon_check_address(_src_, _count_, "source",			\
+			      "scr_memcpyw", __FILE__, __LINE__);	\
+	scr_memcpyw(_dest_, _src_, _count_);				\
+})
+
+#define scr_memmovew(dest, src, count)	({				\
+	__u16 *_dest_ = (dest);						\
+	__u16 *_src_ = (src);						\
+	size_t _count_ = (count);					\
+	gdccon_check_address(_dest_, _count_, "destitnation",		\
+			      "scr_memmovew", __FILE__, __LINE__);	\
+	gdccon_check_address(_src_, _count_, "source",			\
+			      "scr_memmovew", __FILE__, __LINE__);	\
+	scr_memmovew(_dest_, _src_, _count_);				\
+})
+
+#define scr_memcpyw_from(dest, src, count)	({			\
+	__u16 *_dest_ = (dest);						\
+	__u16 *_src_ = (src);						\
+	size_t _count_ = (count);					\
+	gdccon_check_address(_dest_, _count_, "destitnation",		\
+			      "scr_memcpyw_from", __FILE__, __LINE__);	\
+	gdccon_check_address(_src_, _count_, "source",			\
+			      "scr_memcpyw_from", __FILE__, __LINE__);	\
+	scr_memcpyw_from(_dest_, _src_, _count_);			\
+})
+#endif /* GDCCON_DEBUG_MEMFUNCS */
+
+#endif /* _LINUX_ASM_GDC_H_ */

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2002-10-18 17:27 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-10-18 16:56 [PATCHSET 25/25] add support for PC-9800 architecture (video) Osamu Tomita

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).