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>
This commit is contained in:
Yoshihiro Takahashi 2000-04-27 13:34:32 +00:00
parent cd6f7fcd8d
commit d3331668b3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=59689
9 changed files with 570 additions and 166 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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)
{

View File

@ -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;

View File

@ -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

View File

@ -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)
{

View File

@ -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);

View File

@ -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)

View File

@ -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 */