diff --git a/sys/dev/syscons/scvidctl.c b/sys/dev/syscons/scvidctl.c index afb087d92c7e..8af13a0b0719 100644 --- a/sys/dev/syscons/scvidctl.c +++ b/sys/dev/syscons/scvidctl.c @@ -619,6 +619,11 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p) case SW_CG640x350: case SW_ENH_CG640: case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320: case SW_VGA_MODEX: +#ifdef PC98 + /* PC98 GRAPHICS MODES */ + case SW_PC98_EGC640x400: case SW_PC98_PEGC640x400: + case SW_PC98_PEGC640x480: +#endif if (!(adp->va_flags & V_ADP_MODECHANGE)) return ENODEV; return sc_set_graphics_mode(scp, tp, cmd & 0xff); 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 void initialize_gdc(unsigned int, 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 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[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 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, @@ -342,6 +348,22 @@ static video_info_t bios_vmode[] = { #ifdef LINE30 { 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; - gdc_clock = check_gdc_clock(); + int m_mode, s_mode, gdc_clock, hsync_clock; - if (mode == T25_G400){ - m_mode = _25L; - }else{ - m_mode = _30L; + gdc_clock = check_gdc_clock(); + m_mode = (mode == T25_G400) ? _25L : _30L; + s_mode = 2*mode+gdc_clock; + gdc_INFO = m_mode; + + 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 @@ -1003,6 +1171,26 @@ gdc_mmap_buf(video_adapter_t *adp, vm_offset_t offset, int prot) return i386_btop(adp->va_info.vi_window + offset); } +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) { 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 void initialize_gdc(unsigned int, 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 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[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 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, @@ -342,6 +348,22 @@ static video_info_t bios_vmode[] = { #ifdef LINE30 { 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; - gdc_clock = check_gdc_clock(); + int m_mode, s_mode, gdc_clock, hsync_clock; - if (mode == T25_G400){ - m_mode = _25L; - }else{ - m_mode = _30L; + gdc_clock = check_gdc_clock(); + m_mode = (mode == T25_G400) ? _25L : _30L; + s_mode = 2*mode+gdc_clock; + gdc_INFO = m_mode; + + 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 @@ -1003,6 +1171,26 @@ gdc_mmap_buf(video_adapter_t *adp, vm_offset_t offset, int prot) return i386_btop(adp->va_info.vi_window + offset); } +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) { 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); diff --git a/sys/sys/consio.h b/sys/sys/consio.h index 2f5ae3de7d43..7a9fb0241b80 100644 --- a/sys/sys/consio.h +++ b/sys/sys/consio.h @@ -345,8 +345,11 @@ typedef struct vt_mode vtmode_t; #define SW_VGA_CG640 _IO('S', M_VGA_CG640) #define SW_VGA_MODEX _IO('S', M_VGA_MODEX) -#define SW_PC98_80x25 _IO('S', M_PC98_80x25) -#define SW_PC98_80x30 _IO('S', M_PC98_80x30) +#define SW_PC98_80x25 _IO('S', M_PC98_80x25) +#define SW_PC98_80x30 _IO('S', M_PC98_80x30) +#define SW_PC98_EGC640x400 _IO('S', M_PC98_EGC640x400) +#define SW_PC98_PEGC640x400 _IO('S', M_PC98_PEGC640x400) +#define SW_PC98_PEGC640x480 _IO('S', M_PC98_PEGC640x480) #define SW_VGA_C90x25 _IO('S', M_VGA_C90x25) #define SW_VGA_M90x25 _IO('S', M_VGA_M90x25) diff --git a/sys/sys/fbio.h b/sys/sys/fbio.h index f6a969988f4a..1ae1d1378c3d 100644 --- a/sys/sys/fbio.h +++ b/sys/sys/fbio.h @@ -380,8 +380,11 @@ typedef struct video_adapter_info video_adapter_info_t; #define M_ENH_B80x43 0x70 /* ega black & white 80x43 */ #define M_ENH_C80x43 0x71 /* ega color 80x43 */ -#define M_PC98_80x25 98 /* PC98 80x25 */ -#define M_PC98_80x30 99 /* PC98 80x30 */ +#define M_PC98_80x25 98 /* PC98 text 80x25 */ +#define M_PC98_80x30 99 /* PC98 text 80x30 */ +#define M_PC98_EGC640x400 100 /* PC98 graphic 640x400 16 colors */ +#define M_PC98_PEGC640x400 101 /* PC98 graphic 640x400 256 colors */ +#define M_PC98_PEGC640x480 102 /* PC98 graphic 640x480 256 colors */ #define M_HGC_P0 0xe0 /* hercules graphics - page 0 @ B0000 */ #define M_HGC_P1 0xe1 /* hercules graphics - page 1 @ B8000 */