aboutsummaryrefslogtreecommitdiff
path: root/sys/pc98
diff options
context:
space:
mode:
authorYoshihiro Takahashi <nyan@FreeBSD.org>2000-04-27 13:34:32 +0000
committerYoshihiro Takahashi <nyan@FreeBSD.org>2000-04-27 13:34:32 +0000
commitd3331668b3866c5bdb7f50ac4365a9b9ab9c7b6c (patch)
treeb85b92562f889d8ab8de4c5a89889024c72a1342 /sys/pc98
parentcd6f7fcd8d800a534ea79e149dd1165e1aa576d9 (diff)
downloadsrc-d3331668b3866c5bdb7f50ac4365a9b9ab9c7b6c.tar.gz
src-d3331668b3866c5bdb7f50ac4365a9b9ab9c7b6c.zip
Supported EGC 640x400, PEGC 640x400 and PEGC 640x480 graphics modes.
Submitted by: Chiharu Shibata <chi@bd.mbn.or.jp> and Tomokazu HARADA <tkhara@osk4.3web.ne.jp>
Notes
Notes: svn path=/head/; revision=59689
Diffstat (limited to 'sys/pc98')
-rw-r--r--sys/pc98/cbus/30line.h57
-rw-r--r--sys/pc98/cbus/gdc.c292
-rw-r--r--sys/pc98/pc98/30line.h57
-rw-r--r--sys/pc98/pc98/module.h12
-rw-r--r--sys/pc98/pc98/pc98gdc.c292
-rw-r--r--sys/pc98/pc98/syscons.c11
6 files changed, 557 insertions, 164 deletions
diff --git a/sys/pc98/cbus/30line.h b/sys/pc98/cbus/30line.h
index a6b7b7cc61e8..6aeba8340f90 100644
--- a/sys/pc98/cbus/30line.h
+++ b/sys/pc98/cbus/30line.h
@@ -24,6 +24,8 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
*/
#ifndef __PC98_PC98_30LINE_H__
@@ -37,22 +39,22 @@
#define _CR 80
#ifndef _VS
-#define _VS 7
+#define _VS 2
#endif
#ifndef _HS
-#define _HS 6 + 1
+#define _HS 1 + 1
#endif
#ifndef _HFP
-#define _HFP 10 + 1
+#define _HFP 3 + 1
#endif
#ifndef _HBP
-#define _HBP 7 + 1
+#define _HBP 14 + 1
#endif
#ifndef _VFP
-#define _VFP 7
+#define _VFP 11
#endif
#ifndef _VBP
-#define _VBP 25
+#define _VBP 44
#endif
#define _LF LINE30_ROW*16
@@ -76,6 +78,9 @@
#define GDC_LF 7
+#define _24KHZ 0
+#define _31KHZ 1
+
#define _2_5MHZ 0
#define _5MHZ 1
@@ -101,22 +106,30 @@ static void gdc_wait_vsync(void);
static int check_gdc_clock(void);
static int gdc_INFO = _25L;
-static void initialize_gdc(unsigned int);
-
-static unsigned int master_param[2][8] = {
-{78, 8, 7, 9, 7, 7, 25, 400},
-{_CR-2, _VS, _HS-1, _HFP-1, _HBP-1, _VFP, _VBP, _LF}};
-
-static unsigned int slave_param[6][8] = {
-{38, 8, 3, 4, 3, 7, 25, 400}, /* normal */
-{78, 8, 7, 9, 7, 7, 25, 400},
-{_CR/2-2, _VS, (_HS)/2-1, (_HFP)/2-1, (_HBP)/2-1,
-_VFP+(_LF-400)/2+8, _VBP+(_LF-400)/2-8, 400}, /* 30 & 400 */
-{_CR-2, _VS, _HS-1, _HFP-1, _HBP-1,
-_VFP+(_LF-400)/2+8, _VBP+(_LF-400)/2-8, 400},
-{_CR/2-2, _VS, (_HS)/2-1, (_HFP)/2-1, (_HBP)/2-1,
-_VFP, _VBP, _LF}, /* 30 & 480 */
-{_CR-2, _VS, _HS-1, _HFP-1, _HBP-1, _VFP, _VBP, _LF}};
+static void initialize_gdc(unsigned int, int);
+
+static unsigned int master_param[2][2][8] = {
+{{78, 8, 7, 9, 7, 7, 25, 400}, /* 400/24k */
+ {_CR-2, _VS, _HS-1, _HFP-1, _HBP-1, _VFP, _VBP, _LF}}, /* 480/24k */
+{{78, 2, 7, 3, 7, 13, 34, 400}, /* 400/31k */
+ {78, 2, 11, 3, 3, 6, 37, 480}}}; /* 480/31k */
+
+static unsigned int slave_param[2][6][8] = {
+{{38, 8, 3, 4, 3, 7, 25, 400}, /* normal */
+ {78, 8, 7, 9, 7, 7, 25, 400},
+ {_CR/2-2, _VS, (_HS)/2-1, (_HFP)/2-1, (_HBP)/2-1,
+ _VFP+(_LF-400)/2+8, _VBP+(_LF-400)/2-8, 400}, /* 30 & 400 */
+ {_CR-2, _VS, _HS-1, _HFP-1, _HBP-1,
+ _VFP+(_LF-400)/2+8, _VBP+(_LF-400)/2-8, 400},
+ {_CR/2-2, _VS, (_HS)/2-1, (_HFP)/2-1, (_HBP)/2-1,
+ _VFP, _VBP, _LF}, /* 30 & 480 */
+ {_CR-2, _VS, _HS-1, _HFP-1, _HBP-1, _VFP, _VBP, _LF}},
+{{38, 2, 3, 1, 3, 13, 34, 400}, /* normal */
+ {78, 2, 7, 3, 7, 13, 34, 400},
+ {38, 2, 5, 1, 1, 6+48, 37+32, 400}, /* 30 & 400 */
+ {78, 2, 11, 3, 3, 6+48, 37+32, 400},
+ {38, 2, 5, 1, 1, 6, 37, 480}, /* 30 & 480 */
+ {78, 2, 11, 3, 3, 6, 37, 480}}};
static int SlavePCH[2] = {40,80};
static int MasterPCH = 80;
diff --git a/sys/pc98/cbus/gdc.c b/sys/pc98/cbus/gdc.c
index 504e9fda75ad..a1522e7d6be3 100644
--- a/sys/pc98/cbus/gdc.c
+++ b/sys/pc98/cbus/gdc.c
@@ -99,7 +99,7 @@ static d_write_t gdcwrite;
static d_ioctl_t gdcioctl;
static d_mmap_t gdcmmap;
-static struct cdevsw vga_cdevsw = {
+static struct cdevsw gdc_cdevsw = {
/* open */ gdcopen,
/* close */ gdcclose,
/* read */ gdcread,
@@ -299,7 +299,13 @@ static vi_set_hw_cursor_shape_t gdc_set_hw_cursor_shape;
static vi_blank_display_t gdc_blank_display;
static vi_mmap_t gdc_mmap_buf;
static vi_ioctl_t gdc_dev_ioctl;
+static vi_clear_t gdc_clear;
+static vi_fill_rect_t gdc_fill_rect;
+static vi_bitblt_t gdc_bitblt;
static vi_diag_t gdc_diag;
+static vi_save_palette_t gdc_save_palette;
+static vi_load_palette_t gdc_load_palette;
+static vi_set_win_org_t gdc_set_origin;
static video_switch_t gdcvidsw = {
gdc_probe,
@@ -310,21 +316,21 @@ static video_switch_t gdcvidsw = {
(vi_save_font_t *)gdc_err,
(vi_load_font_t *)gdc_err,
(vi_show_font_t *)gdc_err,
- (vi_save_palette_t *)gdc_err,
- (vi_load_palette_t *)gdc_err,
+ gdc_save_palette,
+ gdc_load_palette,
gdc_set_border,
gdc_save_state,
gdc_load_state,
- (vi_set_win_org_t *)gdc_err,
+ gdc_set_origin,
gdc_read_hw_cursor,
gdc_set_hw_cursor,
gdc_set_hw_cursor_shape,
gdc_blank_display,
gdc_mmap_buf,
gdc_dev_ioctl,
- (vi_clear_t *)gdc_err,
- (vi_fill_rect_t *)gdc_err,
- (vi_bitblt_t *)gdc_err,
+ gdc_clear,
+ gdc_fill_rect,
+ gdc_bitblt,
(int (*)(void))gdc_err,
(int (*)(void))gdc_err,
gdc_diag,
@@ -343,6 +349,22 @@ static video_info_t bios_vmode[] = {
{ M_PC98_80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1,
TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
#endif
+#ifndef GDC_NOGRAPHICS
+ { M_PC98_EGC640x400, V_INFO_COLOR | V_INFO_GRAPHICS,
+ 640, 400, 8, 16, 4, 4,
+ GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0,
+ V_INFO_MM_OTHER },
+ { M_PC98_PEGC640x400, V_INFO_COLOR | V_INFO_GRAPHICS | V_INFO_VESA,
+ 640, 400, 8, 16, 8, 1,
+ GRAPHICS_BUF_BASE, 0x00008000, 0x00008000, 0, 0,
+ V_INFO_MM_PACKED, 1 },
+#ifdef LINE30
+ { M_PC98_PEGC640x480, V_INFO_COLOR | V_INFO_GRAPHICS | V_INFO_VESA,
+ 640, 480, 8, 16, 8, 1,
+ GRAPHICS_BUF_BASE, 0x00008000, 0x00008000, 0, 0,
+ V_INFO_MM_PACKED, 1 },
+#endif
+#endif
{ EOT },
};
@@ -396,6 +418,24 @@ map_gen_mode_num(int type, int color, int mode)
return mode;
}
+static int
+verify_adapter(video_adapter_t *adp)
+{
+#ifndef GDC_NOGRAPHICS
+ int i;
+
+ if (PC98_SYSTEM_PARAMETER(0x45c) & 0x40) { /* PEGC exists */
+ adp->va_flags |= V_ADP_VESA; /* XXX */
+ } else {
+ for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
+ if (bios_vmode[i].vi_flags & V_INFO_VESA)
+ bios_vmode[i].vi_mode = NA;
+ }
+ }
+#endif
+ return 0;
+}
+
/* probe video adapters and return the number of detected adapters */
static int
probe_adapters(void)
@@ -412,12 +452,9 @@ probe_adapters(void)
biosadapter[0].va_mode =
biosadapter[0].va_initial_mode = biosadapter[0].va_initial_bios_mode;
- master_gdc_wait_vsync();
- master_gdc_cmd(_GDC_START); /* text ON */
- gdc_wait_vsync();
- gdc_cmd(_GDC_STOP); /* graphics OFF */
-
gdc_get_info(&biosadapter[0], biosadapter[0].va_initial_mode, &info);
+ initialize_gdc(T25_G400, info.vi_flags & V_INFO_GRAPHICS);
+
biosadapter[0].va_window = BIOS_PADDRTOVADDR(info.vi_window);
biosadapter[0].va_window_size = info.vi_window_size;
biosadapter[0].va_window_gran = info.vi_window_gran;
@@ -444,6 +481,8 @@ probe_adapters(void)
}
bcopy(&info, &biosadapter[0].va_info, sizeof(info));
+ verify_adapter(&biosadapter[0]);
+
return 1;
}
@@ -514,21 +553,33 @@ static int check_gdc_clock(void)
}
}
-static void initialize_gdc(unsigned int mode)
+static void initialize_gdc(unsigned int mode, int isGraph)
{
+#ifdef LINE30
/* start 30line initialize */
- int m_mode,s_mode,gdc_clock;
+ int m_mode, s_mode, gdc_clock, hsync_clock;
+
gdc_clock = check_gdc_clock();
+ m_mode = (mode == T25_G400) ? _25L : _30L;
+ s_mode = 2*mode+gdc_clock;
+ gdc_INFO = m_mode;
- if (mode == T25_G400){
- m_mode = _25L;
- }else{
- m_mode = _30L;
+ if ((PC98_SYSTEM_PARAMETER(0x597) & 0x80) ||
+ (PC98_SYSTEM_PARAMETER(0x458) & 0x80)) {
+ hsync_clock = (inb(0x9a8) & 1) ? _31KHZ : _24KHZ;
+ } else {
+ hsync_clock = _24KHZ;
}
- s_mode = 2*mode+gdc_clock;
+ master_gdc_wait_vsync();
- gdc_INFO = m_mode;
+ if ((gdc_clock == _2_5MHZ) &&
+ (slave_param[hsync_clock][s_mode][GDC_LF] > 400)) {
+ outb(0x6a, 0x83);
+ outb(0x6a, 0x85);
+ gdc_clock = _5MHZ;
+ s_mode = 2*mode+gdc_clock;
+ }
master_gdc_cmd(_GDC_RESET);
master_gdc_cmd(_GDC_MASTER);
@@ -538,14 +589,14 @@ static void initialize_gdc(unsigned int mode)
/* GDC Master */
master_gdc_cmd(_GDC_SYNC);
master_gdc_prm(0x00); /* flush less */ /* text & graph */
- master_gdc_prm(master_param[m_mode][GDC_CR]);
- master_gdc_word_prm(((master_param[m_mode][GDC_HFP] << 10)
- + (master_param[m_mode][GDC_VS] << 5)
- + master_param[m_mode][GDC_HS]));
- master_gdc_prm(master_param[m_mode][GDC_HBP]);
- master_gdc_prm(master_param[m_mode][GDC_VFP]);
- master_gdc_word_prm(((master_param[m_mode][GDC_VBP] << 10)
- + (master_param[m_mode][GDC_LF])));
+ master_gdc_prm(master_param[hsync_clock][m_mode][GDC_CR]);
+ master_gdc_word_prm(((master_param[hsync_clock][m_mode][GDC_HFP] << 10)
+ + (master_param[hsync_clock][m_mode][GDC_VS] << 5)
+ + master_param[hsync_clock][m_mode][GDC_HS]));
+ master_gdc_prm(master_param[hsync_clock][m_mode][GDC_HBP]);
+ master_gdc_prm(master_param[hsync_clock][m_mode][GDC_VFP]);
+ master_gdc_word_prm(((master_param[hsync_clock][m_mode][GDC_VBP] << 10)
+ + (master_param[hsync_clock][m_mode][GDC_LF])));
master_gdc_fifo_empty();
master_gdc_cmd(_GDC_PITCH);
master_gdc_prm(MasterPCH);
@@ -554,14 +605,14 @@ static void initialize_gdc(unsigned int mode)
/* GDC slave */
gdc_cmd(_GDC_SYNC);
gdc_prm(0x06);
- gdc_prm(slave_param[s_mode][GDC_CR]);
- gdc_word_prm((slave_param[s_mode][GDC_HFP] << 10)
- + (slave_param[s_mode][GDC_VS] << 5)
- + (slave_param[s_mode][GDC_HS]));
- gdc_prm(slave_param[s_mode][GDC_HBP]);
- gdc_prm(slave_param[s_mode][GDC_VFP]);
- gdc_word_prm((slave_param[s_mode][GDC_VBP] << 10)
- + (slave_param[s_mode][GDC_LF]));
+ gdc_prm(slave_param[hsync_clock][s_mode][GDC_CR]);
+ gdc_word_prm((slave_param[hsync_clock][s_mode][GDC_HFP] << 10)
+ + (slave_param[hsync_clock][s_mode][GDC_VS] << 5)
+ + (slave_param[hsync_clock][s_mode][GDC_HS]));
+ gdc_prm(slave_param[hsync_clock][s_mode][GDC_HBP]);
+ gdc_prm(slave_param[hsync_clock][s_mode][GDC_VFP]);
+ gdc_word_prm((slave_param[hsync_clock][s_mode][GDC_VBP] << 10)
+ + (slave_param[hsync_clock][s_mode][GDC_LF]));
gdc_fifo_empty();
gdc_cmd(_GDC_PITCH);
gdc_prm(SlavePCH[gdc_clock]);
@@ -573,39 +624,132 @@ static void initialize_gdc(unsigned int mode)
master_gdc_wait_vsync();
master_gdc_cmd(_GDC_SCROLL);
master_gdc_word_prm(0);
- master_gdc_word_prm((master_param[m_mode][GDC_LF] << 4) | 0x0000);
+ master_gdc_word_prm((master_param[hsync_clock][m_mode][GDC_LF] << 4)
+ | 0x0000);
master_gdc_fifo_empty();
/* set Slave GDC scroll param */
gdc_wait_vsync();
gdc_cmd(_GDC_SCROLL);
gdc_word_prm(0);
- if (gdc_clock == _5MHZ){
+ if (gdc_clock == _5MHZ) {
gdc_word_prm((SlaveScrlLF[mode] << 4) | 0x4000);
- }else{
+ } else {
gdc_word_prm(SlaveScrlLF[mode] << 4);
}
gdc_fifo_empty();
gdc_word_prm(0);
- if (gdc_clock == _5MHZ){
+ if (gdc_clock == _5MHZ) {
gdc_word_prm((SlaveScrlLF[mode] << 4) | 0x4000);
- }else{
+ } else {
gdc_word_prm(SlaveScrlLF[mode] << 4);
}
gdc_fifo_empty();
/* sync start */
- gdc_cmd(_GDC_STOP);
+ gdc_cmd(isGraph ? _GDC_START : _GDC_STOP);
gdc_wait_vsync();
gdc_wait_vsync();
gdc_wait_vsync();
- master_gdc_cmd(_GDC_START);
+ master_gdc_cmd(isGraph ? _GDC_STOP : _GDC_START);
+#else
+ master_gdc_wait_vsync();
+ master_gdc_cmd(isGraph ? _GDC_STOP : _GDC_START); /* text */
+ gdc_wait_vsync();
+ gdc_cmd(isGraph ? _GDC_START : _GDC_STOP); /* graphics */
+#endif
}
-/* entry points */
+#ifndef GDC_NOGRAPHICS
+static u_char b_palette[] = {
+ /* R G B */
+ 0x00, 0x00, 0x00, /* 0 */
+ 0x00, 0x00, 0x7f, /* 1 */
+ 0x7f, 0x00, 0x00, /* 2 */
+ 0x7f, 0x00, 0x7f, /* 3 */
+ 0x00, 0x7f, 0x00, /* 4 */
+ 0x00, 0x7f, 0x7f, /* 5 */
+ 0x7f, 0x7f, 0x00, /* 6 */
+ 0x7f, 0x7f, 0x7f, /* 7 */
+ 0x40, 0x40, 0x40, /* 8 */
+ 0x00, 0x00, 0xff, /* 9 */
+ 0xff, 0x00, 0x00, /* 10 */
+ 0xff, 0x00, 0xff, /* 11 */
+ 0x00, 0xff, 0x00, /* 12 */
+ 0x00, 0xff, 0xff, /* 13 */
+ 0xff, 0xff, 0x00, /* 14 */
+ 0xff, 0xff, 0xff, /* 15 */
+};
+#endif
+
+static int
+gdc_load_palette(video_adapter_t *adp, u_char *palette)
+{
+#ifndef GDC_NOGRAPHICS
+ int i;
+
+ if (adp->va_info.vi_flags & V_INFO_VESA) {
+ gdc_wait_vsync();
+ for (i = 0; i < 256; ++i) {
+ outb(0xa8, i);
+ outb(0xac, *palette++); /* R */
+ outb(0xaa, *palette++); /* G */
+ outb(0xae, *palette++); /* B */
+ }
+ } else {
+ /*
+ * XXX - Even though PC-98 text color is independent of palette,
+ * we should set palette in text mode.
+ * Because the background color of text mode is palette 0's one.
+ */
+ outb(0x6a, 1); /* 16 colors mode */
+ bcopy(palette, b_palette, sizeof(b_palette));
+
+ gdc_wait_vsync();
+ for (i = 0; i < 16; ++i) {
+ outb(0xa8, i);
+ outb(0xac, *palette++ >> 4); /* R */
+ outb(0xaa, *palette++ >> 4); /* G */
+ outb(0xae, *palette++ >> 4); /* B */
+ }
+ }
+#endif
+ return 0;
+}
+
+static int
+gdc_save_palette(video_adapter_t *adp, u_char *palette)
+{
+#ifndef GDC_NOGRAPHICS
+ int i;
+
+ if (adp->va_info.vi_flags & V_INFO_VESA) {
+ for (i = 0; i < 256; ++i) {
+ outb(0xa8, i);
+ *palette++ = inb(0xac); /* R */
+ *palette++ = inb(0xaa); /* G */
+ *palette++ = inb(0xae); /* B */
+ }
+ } else {
+ bcopy(b_palette, palette, sizeof(b_palette));
+ }
+#endif
+ return 0;
+}
+
+static int
+gdc_set_origin(video_adapter_t *adp, off_t offset)
+{
+#ifndef GDC_NOGRAPHICS
+ if (adp->va_info.vi_flags & V_INFO_VESA) {
+ writew(BIOS_PADDRTOVADDR(0x000e0004), offset >> 15);
+ }
+#endif
+ return 0;
+}
static int
gdc_nop(void)
@@ -613,6 +757,8 @@ gdc_nop(void)
return 0;
}
+/* entry points */
+
static int
gdc_err(video_adapter_t *adp, ...)
{
@@ -741,16 +887,38 @@ gdc_set_mode(video_adapter_t *adp, int mode)
if (gdc_get_info(adp, mode, &info))
return EINVAL;
-#ifdef LINE30
switch (info.vi_mode) {
- case M_PC98_80x25: /* GDC TEXT MODES */
- initialize_gdc(T25_G400);
- break;
- case M_PC98_80x30:
- initialize_gdc(T30_G400);
- break;
+#ifndef GDC_NOGRAPHICS
+ case M_PC98_PEGC640x480: /* PEGC 640x480 */
+ initialize_gdc(T30_G480, info.vi_flags & V_INFO_GRAPHICS);
+ break;
+ case M_PC98_PEGC640x400: /* PEGC 640x400 */
+ case M_PC98_EGC640x400: /* EGC GRAPHICS */
+#endif
+ case M_PC98_80x25: /* VGA TEXT */
+ initialize_gdc(T25_G400, info.vi_flags & V_INFO_GRAPHICS);
+ break;
+ case M_PC98_80x30: /* VGA TEXT */
+ initialize_gdc(T30_G400, info.vi_flags & V_INFO_GRAPHICS);
+ break;
default:
- break;
+ break;
+ }
+
+#ifndef GDC_NOGRAPHICS
+ if (info.vi_flags & V_INFO_VESA) {
+ outb(0x6a, 0x07); /* enable mode F/F change */
+ outb(0x6a, 0x21); /* enhanced graphics */
+ if (info.vi_height > 400)
+ outb(0x6a, 0x69); /* 800 lines */
+ writeb(BIOS_PADDRTOVADDR(0x000e0100), 0); /* packed pixel */
+ } else {
+ if (adp->va_flags & V_ADP_VESA) {
+ outb(0x6a, 0x07); /* enable mode F/F change */
+ outb(0x6a, 0x20); /* normal graphics */
+ outb(0x6a, 0x68); /* 400 lines */
+ }
+ outb(0x6a, 1); /* 16 colors */
}
#endif
@@ -1004,6 +1172,26 @@ gdc_mmap_buf(video_adapter_t *adp, vm_offset_t offset, int prot)
}
static int
+gdc_clear(video_adapter_t *adp)
+{
+ /* FIXME */
+ return ENODEV;
+}
+
+static int
+gdc_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
+{
+ return ENODEV;
+}
+
+static int
+gdc_bitblt(video_adapter_t *adp,...)
+{
+ /* FIXME */
+ return ENODEV;
+}
+
+static int
gdc_dev_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
{
switch (cmd) {
diff --git a/sys/pc98/pc98/30line.h b/sys/pc98/pc98/30line.h
index a6b7b7cc61e8..6aeba8340f90 100644
--- a/sys/pc98/pc98/30line.h
+++ b/sys/pc98/pc98/30line.h
@@ -24,6 +24,8 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
*/
#ifndef __PC98_PC98_30LINE_H__
@@ -37,22 +39,22 @@
#define _CR 80
#ifndef _VS
-#define _VS 7
+#define _VS 2
#endif
#ifndef _HS
-#define _HS 6 + 1
+#define _HS 1 + 1
#endif
#ifndef _HFP
-#define _HFP 10 + 1
+#define _HFP 3 + 1
#endif
#ifndef _HBP
-#define _HBP 7 + 1
+#define _HBP 14 + 1
#endif
#ifndef _VFP
-#define _VFP 7
+#define _VFP 11
#endif
#ifndef _VBP
-#define _VBP 25
+#define _VBP 44
#endif
#define _LF LINE30_ROW*16
@@ -76,6 +78,9 @@
#define GDC_LF 7
+#define _24KHZ 0
+#define _31KHZ 1
+
#define _2_5MHZ 0
#define _5MHZ 1
@@ -101,22 +106,30 @@ static void gdc_wait_vsync(void);
static int check_gdc_clock(void);
static int gdc_INFO = _25L;
-static void initialize_gdc(unsigned int);
-
-static unsigned int master_param[2][8] = {
-{78, 8, 7, 9, 7, 7, 25, 400},
-{_CR-2, _VS, _HS-1, _HFP-1, _HBP-1, _VFP, _VBP, _LF}};
-
-static unsigned int slave_param[6][8] = {
-{38, 8, 3, 4, 3, 7, 25, 400}, /* normal */
-{78, 8, 7, 9, 7, 7, 25, 400},
-{_CR/2-2, _VS, (_HS)/2-1, (_HFP)/2-1, (_HBP)/2-1,
-_VFP+(_LF-400)/2+8, _VBP+(_LF-400)/2-8, 400}, /* 30 & 400 */
-{_CR-2, _VS, _HS-1, _HFP-1, _HBP-1,
-_VFP+(_LF-400)/2+8, _VBP+(_LF-400)/2-8, 400},
-{_CR/2-2, _VS, (_HS)/2-1, (_HFP)/2-1, (_HBP)/2-1,
-_VFP, _VBP, _LF}, /* 30 & 480 */
-{_CR-2, _VS, _HS-1, _HFP-1, _HBP-1, _VFP, _VBP, _LF}};
+static void initialize_gdc(unsigned int, int);
+
+static unsigned int master_param[2][2][8] = {
+{{78, 8, 7, 9, 7, 7, 25, 400}, /* 400/24k */
+ {_CR-2, _VS, _HS-1, _HFP-1, _HBP-1, _VFP, _VBP, _LF}}, /* 480/24k */
+{{78, 2, 7, 3, 7, 13, 34, 400}, /* 400/31k */
+ {78, 2, 11, 3, 3, 6, 37, 480}}}; /* 480/31k */
+
+static unsigned int slave_param[2][6][8] = {
+{{38, 8, 3, 4, 3, 7, 25, 400}, /* normal */
+ {78, 8, 7, 9, 7, 7, 25, 400},
+ {_CR/2-2, _VS, (_HS)/2-1, (_HFP)/2-1, (_HBP)/2-1,
+ _VFP+(_LF-400)/2+8, _VBP+(_LF-400)/2-8, 400}, /* 30 & 400 */
+ {_CR-2, _VS, _HS-1, _HFP-1, _HBP-1,
+ _VFP+(_LF-400)/2+8, _VBP+(_LF-400)/2-8, 400},
+ {_CR/2-2, _VS, (_HS)/2-1, (_HFP)/2-1, (_HBP)/2-1,
+ _VFP, _VBP, _LF}, /* 30 & 480 */
+ {_CR-2, _VS, _HS-1, _HFP-1, _HBP-1, _VFP, _VBP, _LF}},
+{{38, 2, 3, 1, 3, 13, 34, 400}, /* normal */
+ {78, 2, 7, 3, 7, 13, 34, 400},
+ {38, 2, 5, 1, 1, 6+48, 37+32, 400}, /* 30 & 400 */
+ {78, 2, 11, 3, 3, 6+48, 37+32, 400},
+ {38, 2, 5, 1, 1, 6, 37, 480}, /* 30 & 480 */
+ {78, 2, 11, 3, 3, 6, 37, 480}}};
static int SlavePCH[2] = {40,80};
static int MasterPCH = 80;
diff --git a/sys/pc98/pc98/module.h b/sys/pc98/pc98/module.h
index c3dfbdbfe724..b533b3a0fe36 100644
--- a/sys/pc98/pc98/module.h
+++ b/sys/pc98/pc98/module.h
@@ -1,7 +1,9 @@
+/* $FreeBSD$ */
+
#define LINE30_ROW 30
-#define _HS 0 + 1
-#define _VS 1
+#define _HS 1 + 1
+#define _VS 2
#define _HFP 3 + 1
-#define _HBP 4 + 1
-#define _VFP 2
-#define _VBP 25
+#define _HBP 14 + 1
+#define _VFP 11
+#define _VBP 44
diff --git a/sys/pc98/pc98/pc98gdc.c b/sys/pc98/pc98/pc98gdc.c
index 504e9fda75ad..a1522e7d6be3 100644
--- a/sys/pc98/pc98/pc98gdc.c
+++ b/sys/pc98/pc98/pc98gdc.c
@@ -99,7 +99,7 @@ static d_write_t gdcwrite;
static d_ioctl_t gdcioctl;
static d_mmap_t gdcmmap;
-static struct cdevsw vga_cdevsw = {
+static struct cdevsw gdc_cdevsw = {
/* open */ gdcopen,
/* close */ gdcclose,
/* read */ gdcread,
@@ -299,7 +299,13 @@ static vi_set_hw_cursor_shape_t gdc_set_hw_cursor_shape;
static vi_blank_display_t gdc_blank_display;
static vi_mmap_t gdc_mmap_buf;
static vi_ioctl_t gdc_dev_ioctl;
+static vi_clear_t gdc_clear;
+static vi_fill_rect_t gdc_fill_rect;
+static vi_bitblt_t gdc_bitblt;
static vi_diag_t gdc_diag;
+static vi_save_palette_t gdc_save_palette;
+static vi_load_palette_t gdc_load_palette;
+static vi_set_win_org_t gdc_set_origin;
static video_switch_t gdcvidsw = {
gdc_probe,
@@ -310,21 +316,21 @@ static video_switch_t gdcvidsw = {
(vi_save_font_t *)gdc_err,
(vi_load_font_t *)gdc_err,
(vi_show_font_t *)gdc_err,
- (vi_save_palette_t *)gdc_err,
- (vi_load_palette_t *)gdc_err,
+ gdc_save_palette,
+ gdc_load_palette,
gdc_set_border,
gdc_save_state,
gdc_load_state,
- (vi_set_win_org_t *)gdc_err,
+ gdc_set_origin,
gdc_read_hw_cursor,
gdc_set_hw_cursor,
gdc_set_hw_cursor_shape,
gdc_blank_display,
gdc_mmap_buf,
gdc_dev_ioctl,
- (vi_clear_t *)gdc_err,
- (vi_fill_rect_t *)gdc_err,
- (vi_bitblt_t *)gdc_err,
+ gdc_clear,
+ gdc_fill_rect,
+ gdc_bitblt,
(int (*)(void))gdc_err,
(int (*)(void))gdc_err,
gdc_diag,
@@ -343,6 +349,22 @@ static video_info_t bios_vmode[] = {
{ M_PC98_80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1,
TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
#endif
+#ifndef GDC_NOGRAPHICS
+ { M_PC98_EGC640x400, V_INFO_COLOR | V_INFO_GRAPHICS,
+ 640, 400, 8, 16, 4, 4,
+ GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0,
+ V_INFO_MM_OTHER },
+ { M_PC98_PEGC640x400, V_INFO_COLOR | V_INFO_GRAPHICS | V_INFO_VESA,
+ 640, 400, 8, 16, 8, 1,
+ GRAPHICS_BUF_BASE, 0x00008000, 0x00008000, 0, 0,
+ V_INFO_MM_PACKED, 1 },
+#ifdef LINE30
+ { M_PC98_PEGC640x480, V_INFO_COLOR | V_INFO_GRAPHICS | V_INFO_VESA,
+ 640, 480, 8, 16, 8, 1,
+ GRAPHICS_BUF_BASE, 0x00008000, 0x00008000, 0, 0,
+ V_INFO_MM_PACKED, 1 },
+#endif
+#endif
{ EOT },
};
@@ -396,6 +418,24 @@ map_gen_mode_num(int type, int color, int mode)
return mode;
}
+static int
+verify_adapter(video_adapter_t *adp)
+{
+#ifndef GDC_NOGRAPHICS
+ int i;
+
+ if (PC98_SYSTEM_PARAMETER(0x45c) & 0x40) { /* PEGC exists */
+ adp->va_flags |= V_ADP_VESA; /* XXX */
+ } else {
+ for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
+ if (bios_vmode[i].vi_flags & V_INFO_VESA)
+ bios_vmode[i].vi_mode = NA;
+ }
+ }
+#endif
+ return 0;
+}
+
/* probe video adapters and return the number of detected adapters */
static int
probe_adapters(void)
@@ -412,12 +452,9 @@ probe_adapters(void)
biosadapter[0].va_mode =
biosadapter[0].va_initial_mode = biosadapter[0].va_initial_bios_mode;
- master_gdc_wait_vsync();
- master_gdc_cmd(_GDC_START); /* text ON */
- gdc_wait_vsync();
- gdc_cmd(_GDC_STOP); /* graphics OFF */
-
gdc_get_info(&biosadapter[0], biosadapter[0].va_initial_mode, &info);
+ initialize_gdc(T25_G400, info.vi_flags & V_INFO_GRAPHICS);
+
biosadapter[0].va_window = BIOS_PADDRTOVADDR(info.vi_window);
biosadapter[0].va_window_size = info.vi_window_size;
biosadapter[0].va_window_gran = info.vi_window_gran;
@@ -444,6 +481,8 @@ probe_adapters(void)
}
bcopy(&info, &biosadapter[0].va_info, sizeof(info));
+ verify_adapter(&biosadapter[0]);
+
return 1;
}
@@ -514,21 +553,33 @@ static int check_gdc_clock(void)
}
}
-static void initialize_gdc(unsigned int mode)
+static void initialize_gdc(unsigned int mode, int isGraph)
{
+#ifdef LINE30
/* start 30line initialize */
- int m_mode,s_mode,gdc_clock;
+ int m_mode, s_mode, gdc_clock, hsync_clock;
+
gdc_clock = check_gdc_clock();
+ m_mode = (mode == T25_G400) ? _25L : _30L;
+ s_mode = 2*mode+gdc_clock;
+ gdc_INFO = m_mode;
- if (mode == T25_G400){
- m_mode = _25L;
- }else{
- m_mode = _30L;
+ if ((PC98_SYSTEM_PARAMETER(0x597) & 0x80) ||
+ (PC98_SYSTEM_PARAMETER(0x458) & 0x80)) {
+ hsync_clock = (inb(0x9a8) & 1) ? _31KHZ : _24KHZ;
+ } else {
+ hsync_clock = _24KHZ;
}
- s_mode = 2*mode+gdc_clock;
+ master_gdc_wait_vsync();
- gdc_INFO = m_mode;
+ if ((gdc_clock == _2_5MHZ) &&
+ (slave_param[hsync_clock][s_mode][GDC_LF] > 400)) {
+ outb(0x6a, 0x83);
+ outb(0x6a, 0x85);
+ gdc_clock = _5MHZ;
+ s_mode = 2*mode+gdc_clock;
+ }
master_gdc_cmd(_GDC_RESET);
master_gdc_cmd(_GDC_MASTER);
@@ -538,14 +589,14 @@ static void initialize_gdc(unsigned int mode)
/* GDC Master */
master_gdc_cmd(_GDC_SYNC);
master_gdc_prm(0x00); /* flush less */ /* text & graph */
- master_gdc_prm(master_param[m_mode][GDC_CR]);
- master_gdc_word_prm(((master_param[m_mode][GDC_HFP] << 10)
- + (master_param[m_mode][GDC_VS] << 5)
- + master_param[m_mode][GDC_HS]));
- master_gdc_prm(master_param[m_mode][GDC_HBP]);
- master_gdc_prm(master_param[m_mode][GDC_VFP]);
- master_gdc_word_prm(((master_param[m_mode][GDC_VBP] << 10)
- + (master_param[m_mode][GDC_LF])));
+ master_gdc_prm(master_param[hsync_clock][m_mode][GDC_CR]);
+ master_gdc_word_prm(((master_param[hsync_clock][m_mode][GDC_HFP] << 10)
+ + (master_param[hsync_clock][m_mode][GDC_VS] << 5)
+ + master_param[hsync_clock][m_mode][GDC_HS]));
+ master_gdc_prm(master_param[hsync_clock][m_mode][GDC_HBP]);
+ master_gdc_prm(master_param[hsync_clock][m_mode][GDC_VFP]);
+ master_gdc_word_prm(((master_param[hsync_clock][m_mode][GDC_VBP] << 10)
+ + (master_param[hsync_clock][m_mode][GDC_LF])));
master_gdc_fifo_empty();
master_gdc_cmd(_GDC_PITCH);
master_gdc_prm(MasterPCH);
@@ -554,14 +605,14 @@ static void initialize_gdc(unsigned int mode)
/* GDC slave */
gdc_cmd(_GDC_SYNC);
gdc_prm(0x06);
- gdc_prm(slave_param[s_mode][GDC_CR]);
- gdc_word_prm((slave_param[s_mode][GDC_HFP] << 10)
- + (slave_param[s_mode][GDC_VS] << 5)
- + (slave_param[s_mode][GDC_HS]));
- gdc_prm(slave_param[s_mode][GDC_HBP]);
- gdc_prm(slave_param[s_mode][GDC_VFP]);
- gdc_word_prm((slave_param[s_mode][GDC_VBP] << 10)
- + (slave_param[s_mode][GDC_LF]));
+ gdc_prm(slave_param[hsync_clock][s_mode][GDC_CR]);
+ gdc_word_prm((slave_param[hsync_clock][s_mode][GDC_HFP] << 10)
+ + (slave_param[hsync_clock][s_mode][GDC_VS] << 5)
+ + (slave_param[hsync_clock][s_mode][GDC_HS]));
+ gdc_prm(slave_param[hsync_clock][s_mode][GDC_HBP]);
+ gdc_prm(slave_param[hsync_clock][s_mode][GDC_VFP]);
+ gdc_word_prm((slave_param[hsync_clock][s_mode][GDC_VBP] << 10)
+ + (slave_param[hsync_clock][s_mode][GDC_LF]));
gdc_fifo_empty();
gdc_cmd(_GDC_PITCH);
gdc_prm(SlavePCH[gdc_clock]);
@@ -573,39 +624,132 @@ static void initialize_gdc(unsigned int mode)
master_gdc_wait_vsync();
master_gdc_cmd(_GDC_SCROLL);
master_gdc_word_prm(0);
- master_gdc_word_prm((master_param[m_mode][GDC_LF] << 4) | 0x0000);
+ master_gdc_word_prm((master_param[hsync_clock][m_mode][GDC_LF] << 4)
+ | 0x0000);
master_gdc_fifo_empty();
/* set Slave GDC scroll param */
gdc_wait_vsync();
gdc_cmd(_GDC_SCROLL);
gdc_word_prm(0);
- if (gdc_clock == _5MHZ){
+ if (gdc_clock == _5MHZ) {
gdc_word_prm((SlaveScrlLF[mode] << 4) | 0x4000);
- }else{
+ } else {
gdc_word_prm(SlaveScrlLF[mode] << 4);
}
gdc_fifo_empty();
gdc_word_prm(0);
- if (gdc_clock == _5MHZ){
+ if (gdc_clock == _5MHZ) {
gdc_word_prm((SlaveScrlLF[mode] << 4) | 0x4000);
- }else{
+ } else {
gdc_word_prm(SlaveScrlLF[mode] << 4);
}
gdc_fifo_empty();
/* sync start */
- gdc_cmd(_GDC_STOP);
+ gdc_cmd(isGraph ? _GDC_START : _GDC_STOP);
gdc_wait_vsync();
gdc_wait_vsync();
gdc_wait_vsync();
- master_gdc_cmd(_GDC_START);
+ master_gdc_cmd(isGraph ? _GDC_STOP : _GDC_START);
+#else
+ master_gdc_wait_vsync();
+ master_gdc_cmd(isGraph ? _GDC_STOP : _GDC_START); /* text */
+ gdc_wait_vsync();
+ gdc_cmd(isGraph ? _GDC_START : _GDC_STOP); /* graphics */
+#endif
}
-/* entry points */
+#ifndef GDC_NOGRAPHICS
+static u_char b_palette[] = {
+ /* R G B */
+ 0x00, 0x00, 0x00, /* 0 */
+ 0x00, 0x00, 0x7f, /* 1 */
+ 0x7f, 0x00, 0x00, /* 2 */
+ 0x7f, 0x00, 0x7f, /* 3 */
+ 0x00, 0x7f, 0x00, /* 4 */
+ 0x00, 0x7f, 0x7f, /* 5 */
+ 0x7f, 0x7f, 0x00, /* 6 */
+ 0x7f, 0x7f, 0x7f, /* 7 */
+ 0x40, 0x40, 0x40, /* 8 */
+ 0x00, 0x00, 0xff, /* 9 */
+ 0xff, 0x00, 0x00, /* 10 */
+ 0xff, 0x00, 0xff, /* 11 */
+ 0x00, 0xff, 0x00, /* 12 */
+ 0x00, 0xff, 0xff, /* 13 */
+ 0xff, 0xff, 0x00, /* 14 */
+ 0xff, 0xff, 0xff, /* 15 */
+};
+#endif
+
+static int
+gdc_load_palette(video_adapter_t *adp, u_char *palette)
+{
+#ifndef GDC_NOGRAPHICS
+ int i;
+
+ if (adp->va_info.vi_flags & V_INFO_VESA) {
+ gdc_wait_vsync();
+ for (i = 0; i < 256; ++i) {
+ outb(0xa8, i);
+ outb(0xac, *palette++); /* R */
+ outb(0xaa, *palette++); /* G */
+ outb(0xae, *palette++); /* B */
+ }
+ } else {
+ /*
+ * XXX - Even though PC-98 text color is independent of palette,
+ * we should set palette in text mode.
+ * Because the background color of text mode is palette 0's one.
+ */
+ outb(0x6a, 1); /* 16 colors mode */
+ bcopy(palette, b_palette, sizeof(b_palette));
+
+ gdc_wait_vsync();
+ for (i = 0; i < 16; ++i) {
+ outb(0xa8, i);
+ outb(0xac, *palette++ >> 4); /* R */
+ outb(0xaa, *palette++ >> 4); /* G */
+ outb(0xae, *palette++ >> 4); /* B */
+ }
+ }
+#endif
+ return 0;
+}
+
+static int
+gdc_save_palette(video_adapter_t *adp, u_char *palette)
+{
+#ifndef GDC_NOGRAPHICS
+ int i;
+
+ if (adp->va_info.vi_flags & V_INFO_VESA) {
+ for (i = 0; i < 256; ++i) {
+ outb(0xa8, i);
+ *palette++ = inb(0xac); /* R */
+ *palette++ = inb(0xaa); /* G */
+ *palette++ = inb(0xae); /* B */
+ }
+ } else {
+ bcopy(b_palette, palette, sizeof(b_palette));
+ }
+#endif
+ return 0;
+}
+
+static int
+gdc_set_origin(video_adapter_t *adp, off_t offset)
+{
+#ifndef GDC_NOGRAPHICS
+ if (adp->va_info.vi_flags & V_INFO_VESA) {
+ writew(BIOS_PADDRTOVADDR(0x000e0004), offset >> 15);
+ }
+#endif
+ return 0;
+}
static int
gdc_nop(void)
@@ -613,6 +757,8 @@ gdc_nop(void)
return 0;
}
+/* entry points */
+
static int
gdc_err(video_adapter_t *adp, ...)
{
@@ -741,16 +887,38 @@ gdc_set_mode(video_adapter_t *adp, int mode)
if (gdc_get_info(adp, mode, &info))
return EINVAL;
-#ifdef LINE30
switch (info.vi_mode) {
- case M_PC98_80x25: /* GDC TEXT MODES */
- initialize_gdc(T25_G400);
- break;
- case M_PC98_80x30:
- initialize_gdc(T30_G400);
- break;
+#ifndef GDC_NOGRAPHICS
+ case M_PC98_PEGC640x480: /* PEGC 640x480 */
+ initialize_gdc(T30_G480, info.vi_flags & V_INFO_GRAPHICS);
+ break;
+ case M_PC98_PEGC640x400: /* PEGC 640x400 */
+ case M_PC98_EGC640x400: /* EGC GRAPHICS */
+#endif
+ case M_PC98_80x25: /* VGA TEXT */
+ initialize_gdc(T25_G400, info.vi_flags & V_INFO_GRAPHICS);
+ break;
+ case M_PC98_80x30: /* VGA TEXT */
+ initialize_gdc(T30_G400, info.vi_flags & V_INFO_GRAPHICS);
+ break;
default:
- break;
+ break;
+ }
+
+#ifndef GDC_NOGRAPHICS
+ if (info.vi_flags & V_INFO_VESA) {
+ outb(0x6a, 0x07); /* enable mode F/F change */
+ outb(0x6a, 0x21); /* enhanced graphics */
+ if (info.vi_height > 400)
+ outb(0x6a, 0x69); /* 800 lines */
+ writeb(BIOS_PADDRTOVADDR(0x000e0100), 0); /* packed pixel */
+ } else {
+ if (adp->va_flags & V_ADP_VESA) {
+ outb(0x6a, 0x07); /* enable mode F/F change */
+ outb(0x6a, 0x20); /* normal graphics */
+ outb(0x6a, 0x68); /* 400 lines */
+ }
+ outb(0x6a, 1); /* 16 colors */
}
#endif
@@ -1004,6 +1172,26 @@ gdc_mmap_buf(video_adapter_t *adp, vm_offset_t offset, int prot)
}
static int
+gdc_clear(video_adapter_t *adp)
+{
+ /* FIXME */
+ return ENODEV;
+}
+
+static int
+gdc_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
+{
+ return ENODEV;
+}
+
+static int
+gdc_bitblt(video_adapter_t *adp,...)
+{
+ /* FIXME */
+ return ENODEV;
+}
+
+static int
gdc_dev_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
{
switch (cmd) {
diff --git a/sys/pc98/pc98/syscons.c b/sys/pc98/pc98/syscons.c
index 369dbfdfc24a..ce7ccd91cf00 100644
--- a/sys/pc98/pc98/syscons.c
+++ b/sys/pc98/pc98/syscons.c
@@ -3278,17 +3278,6 @@ set_mode(scr_stat *scp)
/* setup video hardware for the given mode */
(*vidsw[scp->sc->adapter]->set_mode)(scp->sc->adp, scp->mode);
-#ifdef PC98
- if (scp->status & UNKNOWN_MODE) {
- while (!(inb(0x60) & 0x20)) {} /* V-SYNC wait */
- outb(0x62, 0xc); /* text off */
- outb(0xA2, 0xd); /* graphics on */
- } else {
- while (!(inb(0x60) & 0x20)) {} /* V-SYNC wait */
- outb(0x62, 0xd); /* text off */
- outb(0xA2, 0xc); /* graphics on */
- }
-#endif /* PC98 */
sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize,
(void *)scp->sc->adp->va_window, FALSE);