Switched to new syscons driver.

Submitted by:	NOKUBI Hirotaka <hnokubi@yyy.or.jp> and
             	Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
This commit is contained in:
kato 1999-01-18 08:38:08 +00:00
parent 42d7787d25
commit 05d57904bd
13 changed files with 4618 additions and 1547 deletions

View File

@ -3,7 +3,7 @@
#
# modified for PC-9801
#
# $Id: files.pc98,v 1.78 1998/12/31 11:38:52 kato Exp $
# $Id: files.pc98,v 1.79 1999/01/04 08:07:47 kato Exp $
#
# The long compile-with and dependency lines are required because of
# limitations in config: backslash-newline doesn't work in strings, and
@ -26,6 +26,11 @@ font8x16.o optional std8x16font \
no-implicit-rule before-depend \
clean "${STD8X16FONT}-8x16 font8x16.c"
#
dev/fb/fb.c optional fb device-driver
dev/fb/fb.c optional gdc device-driver
dev/fb/splash.c optional splash
dev/kbd/kbd.c optional kbd device-driver
dev/kbd/kbd.c optional pckbd device-driver
i386/apm/apm.c optional apm device-driver
i386/apm/apm_setup.s optional apm
i386/eisa/dpt_eisa.c optional eisa dpt device-driver
@ -141,15 +146,14 @@ i386/isa/intr_machdep.c standard
pc98/pc98/pc98.c optional isa device-driver
i386/isa/istallion.c optional stli device-driver
i386/isa/joy.c optional joy device-driver
i386/isa/kbdio.c optional psm device-driver
i386/isa/kbdio.c optional sc device-driver
i386/isa/kbdio.c optional vt device-driver
pc98/pc98/pc98kbd.c optional pckbd device-driver
i386/isa/loran.c optional loran device-driver
pc98/pc98/lpt.c optional lpt device-driver
i386/isa/labpc.c optional labpc device-driver
i386/isa/mcd.c optional mcd device-driver
pc98/pc98/mse.c optional mse device-driver
pc98/pc98/npx.c mandatory npx device-driver
pc98/pc98/pc98gdc.c optional gdc device-driver
pc98/pc98/pcaudio.c optional pca device-driver
i386/isa/matcd/matcd.c optional matcd device-driver
i386/isa/pcibus.c optional pci device-driver

View File

@ -1,4 +1,4 @@
# $Id: options.pc98,v 1.76 1998/12/30 08:03:03 kato Exp $
# $Id: options.pc98,v 1.77 1999/01/04 08:09:15 kato Exp $
DISABLE_PSE
IDE_DELAY
@ -64,27 +64,29 @@ I486_CPU opt_global.h
I586_CPU opt_global.h
I686_CPU opt_global.h
SC_SPLASH_SCREEN opt_syscons.h
MAXCONS opt_syscons.h
SLOW_VGA opt_syscons.h
STD8X16FONT opt_syscons.h
SC_HISTORY_SIZE opt_syscons.h
SC_DISABLE_REBOOT opt_syscons.h
SC_MOUSE_CHAR opt_syscons.h
SC_ALT_SEQACCESS opt_syscons.h
FB_INSTALL_CDEV opt_fb.h
VESA opt_vesa.h
GDC opt_gdc.h
PSM_HOOKAPM opt_psm.h
PSM_RESETAFTERSUSPEND opt_psm.h
PSM_DEBUG opt_psm.h
PCIC_RESUME_RESET opt_pcic.h
KBD_RESETDELAY opt_kbdio.h
KBD_MAXRETRY opt_kbdio.h
KBD_MAXWAIT opt_kbdio.h
KBDIO_DEBUG opt_kbdio.h
KBD_INSTALL_CDEV opt_kbd.h
KBD_MAXRETRY opt_kbd.h
KBD_MAXWAIT opt_kbd.h
KBD_RESETDELAY opt_kbd.h
KBDIO_DEBUG opt_kbd.h
ATAPI opt_atapi.h
ATAPI_STATIC opt_atapi.h

859
sys/pc98/cbus/gdc.c Normal file
View File

@ -0,0 +1,859 @@
#define TEXT_GDC IO_GDC1 /* 0x60 */
#define ROW 25
#define COL 80
/*-
* $Id$
*/
#include "gdc.h"
#include "opt_gdc.h"
#include "opt_fb.h"
#include "opt_syscons.h"
#if NGDC > 0
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/malloc.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/console.h>
#include <machine/md_var.h>
#include <machine/pc/bios.h>
#include <dev/fb/fbreg.h>
#include <pc98/pc98/pc98.h>
#include <pc98/pc98/pc98_machdep.h>
#include <i386/isa/isa_device.h>
#define DRIVER_NAME "gdc"
/* cdev driver declaration */
#define GDC_UNIT(dev) minor(dev)
#define GDC_MKMINOR(unit) (unit)
static int gdcprobe(struct isa_device *dev);
static int gdc_attach(struct isa_device *dev);
static void gdc_drvinit(void *unused);
struct isa_driver gdcdriver = {
gdcprobe,
gdc_attach,
DRIVER_NAME,
0,
};
typedef struct gdc_softc {
video_adapter_t *adp;
} gdc_softc_t;
static int gdc_probe_unit(int unit, gdc_softc_t *sc, int flags);
static int gdc_attach_unit(int unit, gdc_softc_t *sc, int flags);
#define GDC_SOFTC(unit) (gdc_softc[unit])
static gdc_softc_t *gdc_softc[NGDC];
#if FB_INSTALL_CDEV
static d_open_t gdcopen;
static d_close_t gdcclose;
static d_read_t gdcread;
static d_ioctl_t gdcioctl;
static struct cdevsw vga_cdevsw = {
gdcopen, gdcclose, noread, nowrite, /* ?? */
gdcioctl, nostop, nullreset, nodevtotty,
seltrue, nommap, NULL, DRIVER_NAME,
NULL, -1, nodump, nopsize,
};
#endif /* FB_INSTALL_CDEV */
static int
gdcprobe(struct isa_device *dev)
{
gdc_softc_t *sc;
int error;
if (dev->id_unit >= sizeof(gdc_softc)/sizeof(gdc_softc[0]))
return 0;
sc = gdc_softc[dev->id_unit]
= malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT);
if (sc == NULL)
return 0;
error = gdc_probe_unit(dev->id_unit, sc, dev->id_flags);
if (error) {
gdc_softc[dev->id_unit] = NULL;
free(sc, M_DEVBUF);
return 0;
}
dev->id_iobase = sc->adp->va_io_base;
dev->id_maddr = (caddr_t)BIOS_PADDRTOVADDR(sc->adp->va_mem_base);
dev->id_msize = sc->adp->va_mem_size;
return sc->adp->va_io_size;
}
static int
gdc_attach(struct isa_device *dev)
{
gdc_softc_t *sc;
if (dev->id_unit >= sizeof(gdc_softc)/sizeof(gdc_softc[0]))
return 0;
sc = gdc_softc[dev->id_unit];
if (sc == NULL)
return 0;
return ((gdc_attach_unit(dev->id_unit, sc, dev->id_flags)) ? 0 : 1);
}
static int
gdc_probe_unit(int unit, gdc_softc_t *sc, int flags)
{
video_switch_t *sw;
bzero(sc, sizeof(*sc));
sw = vid_get_switch(DRIVER_NAME);
if (sw == NULL)
return 0;
return (*sw->probe)(unit, &sc->adp, NULL, flags);
}
static int
gdc_attach_unit(int unit, gdc_softc_t *sc, int flags)
{
video_switch_t *sw;
int error;
sw = vid_get_switch(DRIVER_NAME);
if (sw == NULL)
return ENXIO;
error = (*sw->init)(unit, sc->adp, flags);
if (error)
return ENXIO;
#ifdef FB_INSTALL_CDEV
/* attach a virtual frame buffer device */
error = fb_attach(makedev(0, GDC_MKMINOR(unit)), scp->adp,
&vga_cdevsw);
if (error)
return error;
#endif /* FB_INSTALL_CDEV */
if (bootverbose)
(*sw->diag)(sc->adp, bootverbose);
return 0;
}
/* LOW-LEVEL */
#include <machine/clock.h>
#include <pc98/pc98/30line.h>
#define TEXT_BUF_BASE 0x000a0000
#define TEXT_BUF_SIZE 0x00008000
#define GRAPHICS_BUF_BASE 0x000a8000
#define GRAPHICS_BUF_SIZE 0x00040000
#define VIDEO_BUF_BASE 0x000a0000
#define VIDEO_BUF_SIZE 0x00048000
#define probe_done(adp) ((adp)->va_flags & V_ADP_PROBED)
#define init_done(adp) ((adp)->va_flags & V_ADP_INITIALIZED)
#define config_done(adp) ((adp)->va_flags & V_ADP_REGISTERED)
/*
* NOTE: `va_window' should have a virtual address, but is initialized
* with a physical address in the following table, they will be
* converted at run-time.
*/
static video_adapter_t adapter_init_value[] = {
{ 0,
KD_PC98, "gdc", /* va_type, va_name */
0, 0, /* va_unit, va_minor */
V_ADP_COLOR | V_ADP_MODECHANGE | V_ADP_BORDER,
IO_GDC1, 16, TEXT_GDC, /* va_io*, XXX */
VIDEO_BUF_BASE, VIDEO_BUF_SIZE, /* va_mem* */
TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, /* va_window* */
0, 0, /* va_buffer, va_buffer_size */
0, M_PC98_80x25, 0, 0, /* va_*mode* */
NULL },
};
static video_adapter_t biosadapter[1];
/* video driver declarations */
static int gdc_configure(int flags);
static int gdc_nop(void);
static vi_probe_t gdc_probe;
static vi_init_t gdc_init;
static vi_get_info_t gdc_get_info;
static vi_query_mode_t gdc_query_mode;
static vi_set_mode_t gdc_set_mode;
static vi_set_border_t gdc_set_border;
static vi_save_state_t gdc_save_state;
static vi_load_state_t gdc_load_state;
static vi_read_hw_cursor_t gdc_read_hw_cursor;
static vi_set_hw_cursor_t gdc_set_hw_cursor;
static vi_set_hw_cursor_shape_t gdc_set_hw_cursor_shape;
static vi_mmap_t gdc_mmap;
static vi_diag_t gdc_diag;
static int gdc_err(video_adapter_t *adp, ...);
static video_switch_t gdcvidsw = {
gdc_probe,
gdc_init,
gdc_get_info,
gdc_query_mode,
gdc_set_mode,
(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_set_border,
gdc_save_state,
gdc_load_state,
(vi_set_win_org_t *)gdc_err,
gdc_read_hw_cursor,
gdc_set_hw_cursor,
gdc_set_hw_cursor_shape,
(vi_blank_display_t *)gdc_nop,
gdc_mmap,
gdc_diag,
};
VIDEO_DRIVER(gdc, gdcvidsw, gdc_configure);
/* GDC BIOS standard video modes */
#define EOT (-1)
#define NA (-2)
static video_info_t bios_vmode[] = {
{ M_PC98_80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1,
TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, 0, 0 },
#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 },
#endif
{ EOT },
};
static int init_done = FALSE;
/* local functions */
static int map_gen_mode_num(int type, int color, int mode);
static int probe_adapters(void);
static void dump_buffer(u_char *buf, size_t len);
#define prologue(adp, flag, err) \
if (!init_done || !((adp)->va_flags & (flag))) \
return (err)
/* a backdoor for the console driver */
static int
gdc_configure(int flags)
{
probe_adapters();
biosadapter[0].va_flags |= V_ADP_INITIALIZED;
if (!config_done(&biosadapter[0])) {
if (vid_register(&biosadapter[0]) < 0)
return 1;
biosadapter[0].va_flags |= V_ADP_REGISTERED;
}
return 1;
}
/* local subroutines */
/* map a generic video mode to a known mode number */
static int
map_gen_mode_num(int type, int color, int mode)
{
static struct {
int from;
int to;
} mode_map[] = {
{ M_TEXT_80x25, M_PC98_80x25, },
#ifdef LINE30
{ M_TEXT_80x30, M_PC98_80x30, },
#endif
};
int i;
for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
if (mode_map[i].from == mode)
return mode_map[i].to;
}
return mode;
}
/* probe video adapters and return the number of detected adapters */
static int
probe_adapters(void)
{
video_info_t info;
/* do this test only once */
if (init_done)
return 1;
init_done = TRUE;
biosadapter[0] = adapter_init_value[0];
biosadapter[0].va_flags |= V_ADP_PROBED;
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);
biosadapter[0].va_mode_flags = info.vi_flags;
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;
biosadapter[0].va_buffer = 0;
biosadapter[0].va_buffer_size = 0;
return 1;
}
static void master_gdc_cmd(unsigned int cmd)
{
while ( (inb(IO_GDC1) & 2) != 0);
outb(IO_GDC1+2, cmd);
}
static void master_gdc_prm(unsigned int pmtr)
{
while ( (inb(IO_GDC1) & 2) != 0);
outb(IO_GDC1, pmtr);
}
static void master_gdc_word_prm(unsigned int wpmtr)
{
master_gdc_prm(wpmtr & 0x00ff);
master_gdc_prm((wpmtr >> 8) & 0x00ff);
}
static void master_gdc_fifo_empty(void)
{
while ( (inb(IO_GDC1) & 4) == 0);
}
static void master_gdc_wait_vsync(void)
{
while ( (inb(IO_GDC1) & 0x20) != 0);
while ( (inb(IO_GDC1) & 0x20) == 0);
}
static void gdc_cmd(unsigned int cmd)
{
while ( (inb(IO_GDC2) & 2) != 0);
outb( IO_GDC2+2, cmd);
}
static void gdc_prm(unsigned int pmtr)
{
while ( (inb(IO_GDC2) & 2) != 0);
outb( IO_GDC2, pmtr);
}
static void gdc_word_prm(unsigned int wpmtr)
{
gdc_prm(wpmtr & 0x00ff);
gdc_prm((wpmtr >> 8) & 0x00ff);
}
static void gdc_fifo_empty(void)
{
while ( (inb(IO_GDC2) & 0x04) == 0);
}
static void gdc_wait_vsync(void)
{
while ( (inb(IO_GDC2) & 0x20) != 0);
while ( (inb(IO_GDC2) & 0x20) == 0);
}
static int check_gdc_clock(void)
{
if ((inb(IO_SYSPORT) & 0x80) == 0){
return _5MHZ;
} else {
return _2_5MHZ;
}
}
static void initialize_gdc(unsigned int mode)
{
/* start 30line initialize */
int m_mode,s_mode,gdc_clock;
gdc_clock = check_gdc_clock();
if (mode == T25_G400){
m_mode = _25L;
}else{
m_mode = _30L;
}
s_mode = 2*mode+gdc_clock;
gdc_INFO = m_mode;
master_gdc_cmd(_GDC_RESET);
master_gdc_cmd(_GDC_MASTER);
gdc_cmd(_GDC_RESET);
gdc_cmd(_GDC_SLAVE);
/* 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_fifo_empty();
master_gdc_cmd(_GDC_PITCH);
master_gdc_prm(MasterPCH);
master_gdc_fifo_empty();
/* 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_fifo_empty();
gdc_cmd(_GDC_PITCH);
gdc_prm(SlavePCH[gdc_clock]);
gdc_fifo_empty();
/* set Master GDC scroll param */
master_gdc_wait_vsync();
master_gdc_wait_vsync();
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_fifo_empty();
/* set Slave GDC scroll param */
gdc_wait_vsync();
gdc_cmd(_GDC_SCROLL);
gdc_word_prm(0);
if (gdc_clock == _5MHZ){
gdc_word_prm((SlaveScrlLF[mode] << 4) | 0x4000);
}else{
gdc_word_prm(SlaveScrlLF[mode] << 4);
}
gdc_fifo_empty();
gdc_word_prm(0);
if (gdc_clock == _5MHZ){
gdc_word_prm((SlaveScrlLF[mode] << 4) | 0x4000);
}else{
gdc_word_prm(SlaveScrlLF[mode] << 4);
}
gdc_fifo_empty();
/* sync start */
gdc_cmd(_GDC_STOP);
gdc_wait_vsync();
gdc_wait_vsync();
gdc_wait_vsync();
master_gdc_cmd(_GDC_START);
}
/* entry points */
static int
gdc_nop(void)
{
return 0;
}
static int
gdc_probe(int unit, video_adapter_t **adpp, void *arg, int flags)
{
probe_adapters();
if (unit >= 1)
return ENXIO;
*adpp = &biosadapter[unit];
return 0;
}
static int
gdc_init(int unit, video_adapter_t *adp, int flags)
{
if ((unit >= 1) || (adp == NULL) || !probe_done(adp))
return ENXIO;
if (!init_done(adp)) {
/* nothing to do really... */
adp->va_flags |= V_ADP_INITIALIZED;
}
if (!config_done(adp)) {
if (vid_register(adp) < 0)
return ENXIO;
adp->va_flags |= V_ADP_REGISTERED;
}
return 0;
}
/*
* get_info():
* Return the video_info structure of the requested video mode.
*/
static int
gdc_get_info(video_adapter_t *adp, int mode, video_info_t *info)
{
int i;
if (!init_done)
return 1;
mode = map_gen_mode_num(adp->va_type, adp->va_flags & V_ADP_COLOR, mode);
for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
if (bios_vmode[i].vi_mode == NA)
continue;
if (mode == bios_vmode[i].vi_mode) {
*info = bios_vmode[i];
return 0;
}
}
return 1;
}
/*
* query_mode():
* Find a video mode matching the requested parameters.
* Fields filled with 0 are considered "don't care" fields and
* match any modes.
*/
static int
gdc_query_mode(video_adapter_t *adp, video_info_t *info)
{
video_info_t buf;
int i;
if (!init_done)
return -1;
for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
if (bios_vmode[i].vi_mode == NA)
continue;
if ((info->vi_width != 0)
&& (info->vi_width != bios_vmode[i].vi_width))
continue;
if ((info->vi_height != 0)
&& (info->vi_height != bios_vmode[i].vi_height))
continue;
if ((info->vi_cwidth != 0)
&& (info->vi_cwidth != bios_vmode[i].vi_cwidth))
continue;
if ((info->vi_cheight != 0)
&& (info->vi_cheight != bios_vmode[i].vi_cheight))
continue;
if ((info->vi_depth != 0)
&& (info->vi_depth != bios_vmode[i].vi_depth))
continue;
if ((info->vi_planes != 0)
&& (info->vi_planes != bios_vmode[i].vi_planes))
continue;
/* XXX: should check pixel format, memory model */
if ((info->vi_flags != 0)
&& (info->vi_flags != bios_vmode[i].vi_flags))
continue;
/* verify if this mode is supported on this adapter */
if (gdc_get_info(adp, bios_vmode[i].vi_mode, &buf))
continue;
return bios_vmode[i].vi_mode;
}
return -1;
}
/*
* set_mode():
* Change the video mode.
*/
static int
gdc_set_mode(video_adapter_t *adp, int mode)
{
video_info_t info;
prologue(adp, V_ADP_MODECHANGE, 1);
mode = map_gen_mode_num(adp->va_type,
adp->va_flags & V_ADP_COLOR, mode);
if (gdc_get_info(adp, mode, &info))
return 1;
#ifdef LINE30
switch (scp->mode) {
case M_PC98_80x25: /* VGA TEXT MODES */
initialize_gdc(T25_G400);
break;
case M_PC98_80x30:
initialize_gdc(T30_G400);
break;
default:
break;
}
#endif
adp->va_mode = mode;
adp->va_mode_flags = info.vi_flags;
adp->va_flags &= ~V_ADP_COLOR;
adp->va_flags |=
(info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0;
#if 0
adp->va_crtc_addr =
(adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC;
#endif
adp->va_window = BIOS_PADDRTOVADDR(info.vi_window);
adp->va_window_size = info.vi_window_size;
adp->va_window_gran = info.vi_window_gran;
if (info.vi_buffer_size == 0) {
adp->va_buffer = 0;
adp->va_buffer_size = 0;
} else {
adp->va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer);
adp->va_buffer_size = info.vi_buffer_size;
}
/* move hardware cursor out of the way */
(*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1);
return 0;
}
/*
* set_border():
* Change the border color.
*/
static int
gdc_set_border(video_adapter_t *adp, int color)
{
outb(0x6c, color << 4);
return 0;
}
/*
* save_state():
* Read video card register values.
*/
static int
gdc_save_state(video_adapter_t *adp, void *p, size_t size)
{
return 1;
}
/*
* load_state():
* Set video card registers at once.
*/
static int
gdc_load_state(video_adapter_t *adp, void *p)
{
return 1;
}
/*
* read_hw_cursor():
* Read the position of the hardware text cursor.
*/
static int
gdc_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
{
video_info_t info;
u_int16_t off;
int s;
if (!init_done)
return 1;
(*vidsw[adp->va_index]->get_info)(adp, adp->va_mode, &info);
if (info.vi_flags & V_INFO_GRAPHICS)
return 1;
s = spltty();
master_gdc_cmd(0xe0); /* _GDC_CSRR */
while((inb(TEXT_GDC + 0) & 0x1) == 0) {} /* GDC wait */
off = inb(TEXT_GDC + 2); /* EADl */
off |= (inb(TEXT_GDC + 2) << 8); /* EADh */
inb(TEXT_GDC + 2); /* dummy */
inb(TEXT_GDC + 2); /* dummy */
inb(TEXT_GDC + 2); /* dummy */
splx(s);
if (off >= ROW*COL)
off = 0;
*row = off / info.vi_width;
*col = off % info.vi_width;
return 0;
}
/*
* set_hw_cursor():
* Move the hardware text cursor. If col and row are both -1,
* the cursor won't be shown.
*/
static int
gdc_set_hw_cursor(video_adapter_t *adp, int col, int row)
{
video_info_t info;
u_int16_t off;
int s;
if (!init_done)
return 1;
if ((col == -1) && (row == -1)) {
off = -1;
} else {
(*vidsw[adp->va_index]->get_info)(adp, adp->va_mode, &info);
if (info.vi_flags & V_INFO_GRAPHICS)
return 1;
off = row*info.vi_width + col;
}
s = spltty();
master_gdc_cmd(0x49); /* _GDC_CSRW */
master_gdc_word_prm(off);
splx(s);
return 0;
}
/*
* set_hw_cursor_shape():
* Change the shape of the hardware text cursor. If the height is zero
* or negative, the cursor won't be shown.
*/
static int
gdc_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
int celsize, int blink)
{
int start;
int end;
int s;
start = celsize - (base + height);
end = celsize - base - 1;
/*
* muPD7220 GDC has anomaly that if end == celsize - 1 then start
* must be 0, otherwise the cursor won't be correctly shown
* in the first row in the screen. We shall set end to celsize - 2;
* if end == celsize -1 && start > 0. XXX
*/
if ((end == celsize - 1) && (start > 0))
--end;
s = spltty();
master_gdc_cmd(0x4b); /* _GDC_CSRFORM */
master_gdc_prm(((height > 0) ? 0x80 : 0) /* cursor on/off */
| (celsize - 1) & 0x1f); /* cel size */
master_gdc_word_prm(((end & 0x1f) << 11) /* end line */
| (12 << 6) /* blink rate */
| (blink ? 0x20 : 0) /* blink on/off */
| (start & 0x1f)); /* start line */
splx(s);
return 1;
}
static void
dump_buffer(u_char *buf, size_t len)
{
int i;
for(i = 0; i < len;) {
printf("%02x ", buf[i]);
if ((++i % 16) == 0)
printf("\n");
}
}
/*
* mmap():
* Mmap frame buffer.
*/
static int
gdc_mmap(video_adapter_t *adp, vm_offset_t offset)
{
if (offset > 0x48000 - PAGE_SIZE)
return -1;
return i386_btop((VIDEO_BUF_BASE + offset));
}
/*
* diag():
* Print some information about the video adapter and video modes,
* with requested level of details.
*/
static int
gdc_diag(video_adapter_t *adp, int level)
{
video_info_t info;
int i;
if (!init_done)
return 1;
fb_dump_adp_info(DRIVER_NAME, adp, level);
#if FB_DEBUG > 1
for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
if (bios_vmode[i].vi_mode == NA)
continue;
if (get_mode_param(bios_vmode[i].vi_mode) == NULL)
continue;
fb_dump_mode_info(DRIVER_NAME, adp, &bios_vmode[i], level);
}
#endif
return 0;
}
static int
gdc_err(video_adapter_t *adp, ...)
{
return 0;
}
#endif /* NGDC > 0 */

983
sys/pc98/cbus/pckbd.c Normal file
View File

@ -0,0 +1,983 @@
/*-
* $Id$
*/
#include "pckbd.h"
#include "opt_kbd.h"
#include "opt_devfs.h"
#if NPCKBD > 0
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/conf.h>
#include <sys/proc.h>
#include <sys/tty.h>
#include <sys/fcntl.h>
#include <sys/bus.h>
#include <sys/malloc.h>
#include <machine/resource.h>
#include <dev/kbd/kbdreg.h>
#include <pc98/pc98/pc98.h>
#include <pc98/pc98/pc98_machdep.h>
#ifdef __i386__
#include <i386/isa/isa_device.h>
#endif
#define DRIVER_NAME "pckbd"
/* device configuration flags */
#define KB_CONF_FAIL_IF_NO_KBD (1 << 0) /* don't install if no kbd is found */
/* some macros */
#define PC98KBD_UNIT(dev) minor(dev)
#define PC98KBD_MKMINOR(unit) (unit)
/* cdev driver declaration */
typedef struct pckbd_softc {
short flags;
#define PC98KBD_ATTACHED (1 << 0)
keyboard_t *kbd;
#ifdef KBD_INSTALL_CDEV
genkbd_softc_t gensc;
#endif
} pckbd_softc_t;
#define PC98KBD_SOFTC(unit) pckbd_softc[(unit)]
static pckbd_softc_t *pckbd_softc[NPCKBD];
static int pckbdprobe(struct isa_device *dev);
static int pckbdattach(struct isa_device *dev);
static ointhand2_t pckbd_isa_intr;
/* driver declaration for isa_devtab_tty[] */
struct isa_driver pckbddriver = {
pckbdprobe,
pckbdattach,
DRIVER_NAME,
0,
};
static int pckbd_probe_unit(int unit, pckbd_softc_t *sc,
int port, int irq, int flags);
static int pckbd_attach_unit(int unit, pckbd_softc_t *sc);
static timeout_t pckbd_timeout;
#ifdef KBD_INSTALL_CDEV
static d_open_t pckbdopen;
static d_close_t pckbdclose;
static d_read_t pckbdread;
static d_ioctl_t pckbdioctl;
static d_poll_t pckbdpoll;
static struct cdevsw pckbd_cdevsw = {
pckbdopen, pckbdclose, pckbdread, nowrite,
pckbdioctl, nostop, nullreset, nodevtotty,
pckbdpoll, nommap, NULL, DRIVER_NAME,
NULL, -1,
};
#endif /* KBD_INSTALL_CDEV */
static int
pckbdprobe(struct isa_device *dev)
{
pckbd_softc_t *sc;
int error;
if (dev->id_unit >= sizeof(pckbd_softc)/sizeof(pckbd_softc[0]))
return 0;
sc = pckbd_softc[dev->id_unit];
if (sc == NULL) {
sc = pckbd_softc[dev->id_unit]
= malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT);
if (sc == NULL)
return 0;
bzero(sc, sizeof(*sc));
}
/* try to find a keyboard */
error = pckbd_probe_unit(dev->id_unit, sc, dev->id_iobase,
dev->id_irq, dev->id_flags);
if (error)
return 0;
/* declare our interrupt handler */
dev->id_ointr = pckbd_isa_intr;
return IO_KBDSIZE;
}
static int
pckbdattach(struct isa_device *dev)
{
pckbd_softc_t *sc;
if (dev->id_unit >= sizeof(pckbd_softc)/sizeof(pckbd_softc[0]))
return 0;
sc = pckbd_softc[dev->id_unit];
if (sc == NULL)
return 0;
return ((pckbd_attach_unit(dev->id_unit, sc)) ? 0 : 1);
}
static void
pckbd_isa_intr(int unit)
{
keyboard_t *kbd;
kbd = pckbd_softc[unit]->kbd;
(*kbdsw[kbd->kb_index]->intr)(kbd, NULL);
}
static int
pckbd_probe_unit(int unit, pckbd_softc_t *sc, int port, int irq, int flags)
{
keyboard_switch_t *sw;
int args[2];
if (sc->flags & PC98KBD_ATTACHED)
return 0;
sw = kbd_get_switch(DRIVER_NAME);
if (sw == NULL)
return ENXIO;
args[0] = port;
args[1] = irq;
return (*sw->probe)(unit, &sc->kbd, args, flags);
}
static int
pckbd_attach_unit(int unit, pckbd_softc_t *sc)
{
keyboard_switch_t *sw;
int error;
if (sc->flags & PC98KBD_ATTACHED)
return 0;
sw = kbd_get_switch(DRIVER_NAME);
if (sw == NULL)
return ENXIO;
/* reset, initialize and enable the device */
error = (*sw->init)(sc->kbd);
if (error)
return ENXIO;
(*sw->enable)(sc->kbd);
#ifdef KBD_INSTALL_CDEV
/* attach a virtual keyboard cdev */
error = kbd_attach(makedev(0, PC98KBD_MKMINOR(unit)), sc->kbd,
&pckbd_cdevsw);
if (error)
return error;
#endif /* KBD_INSTALL_CDEV */
/*
* This is a kludge to compensate for lost keyboard interrupts.
* A similar code used to be in syscons. See below. XXX
*/
pckbd_timeout(sc->kbd);
if (bootverbose)
(*sw->diag)(sc->kbd, bootverbose);
sc->flags |= PC98KBD_ATTACHED;
return 0;
}
static void
pckbd_timeout(void *arg)
{
keyboard_t *kbd;
int s;
/* The following comments are extracted from syscons.c (1.287) */
/*
* With release 2.1 of the Xaccel server, the keyboard is left
* hanging pretty often. Apparently an interrupt from the
* keyboard is lost, and I don't know why (yet).
* This ugly hack calls scintr if input is ready for the keyboard
* and conveniently hides the problem. XXX
*/
/*
* Try removing anything stuck in the keyboard controller; whether
* it's a keyboard scan code or mouse data. `scintr()' doesn't
* read the mouse data directly, but `kbdio' routines will, as a
* side effect.
*/
s = spltty();
kbd = (keyboard_t *)arg;
if ((*kbdsw[kbd->kb_index]->lock)(kbd, TRUE)) {
/*
* We have seen the lock flag is not set. Let's reset
* the flag early, otherwise the LED update routine fails
* which may want the lock during the interrupt routine.
*/
(*kbdsw[kbd->kb_index]->lock)(kbd, FALSE);
if ((*kbdsw[kbd->kb_index]->check_char)(kbd))
(*kbdsw[kbd->kb_index]->intr)(kbd, NULL);
}
splx(s);
timeout(pckbd_timeout, arg, hz/10);
}
/* cdev driver functions */
#ifdef KBD_INSTALL_CDEV
static int
pckbdopen(dev_t dev, int flag, int mode, struct proc *p)
{
pckbd_softc_t *sc;
int unit;
unit = PC98KBD_UNIT(dev);
if ((unit >= NPCKBD) || ((sc = PC98KBD_SOFTC(unit)) == NULL))
return ENXIO;
if (mode & (FWRITE | O_CREAT | O_APPEND | O_TRUNC))
return ENODEV;
/* FIXME: set the initial input mode (K_XLATE?) and lock state? */
return genkbdopen(&sc->gensc, sc->kbd, flag, mode, p);
}
static int
pckbdclose(dev_t dev, int flag, int mode, struct proc *p)
{
pckbd_softc_t *sc;
sc = PC98KBD_SOFTC(PC98KBD_UNIT(dev));
return genkbdclose(&sc->gensc, sc->kbd, flag, mode, p);
}
static int
pckbdread(dev_t dev, struct uio *uio, int flag)
{
pckbd_softc_t *sc;
sc = PC98KBD_SOFTC(PC98KBD_UNIT(dev));
return genkbdread(&sc->gensc, sc->kbd, uio, flag);
}
static int
pckbdioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
{
pckbd_softc_t *sc;
sc = PC98KBD_SOFTC(PC98KBD_UNIT(dev));
return genkbdioctl(&sc->gensc, sc->kbd, cmd, arg, flag, p);
}
static int
pckbdpoll(dev_t dev, int event, struct proc *p)
{
pckbd_softc_t *sc;
sc = PC98KBD_SOFTC(PC98KBD_UNIT(dev));
return genkbdpoll(&sc->gensc, sc->kbd, event, p);
}
#endif /* KBD_INSTALL_CDEV */
/* LOW-LEVEL */
#include <machine/limits.h>
#include <machine/console.h>
#include <machine/clock.h>
#define PC98KBD_DEFAULT 0
typedef caddr_t KBDC;
typedef struct pckbd_state {
KBDC kbdc; /* keyboard controller */
int ks_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */
int ks_flags; /* flags */
#define COMPOSE (1 << 0)
int ks_state; /* shift/lock key state */
int ks_accents; /* accent key index (> 0) */
u_int ks_composed_char; /* composed char code (> 0) */
} pckbd_state_t;
/* keyboard driver declaration */
static int pckbd_configure(int flags);
static kbd_probe_t pckbd_probe;
static kbd_init_t pckbd_init;
static kbd_term_t pckbd_term;
static kbd_intr_t pckbd_intr;
static kbd_test_if_t pckbd_test_if;
static kbd_enable_t pckbd_enable;
static kbd_disable_t pckbd_disable;
static kbd_read_t pckbd_read;
static kbd_check_t pckbd_check;
static kbd_read_char_t pckbd_read_char;
static kbd_check_char_t pckbd_check_char;
static kbd_ioctl_t pckbd_ioctl;
static kbd_lock_t pckbd_lock;
static kbd_clear_state_t pckbd_clear_state;
static kbd_get_state_t pckbd_get_state;
static kbd_set_state_t pckbd_set_state;
keyboard_switch_t pckbdsw = {
pckbd_probe,
pckbd_init,
pckbd_term,
pckbd_intr,
pckbd_test_if,
pckbd_enable,
pckbd_disable,
pckbd_read,
pckbd_check,
pckbd_read_char,
pckbd_check_char,
pckbd_ioctl,
pckbd_lock,
pckbd_clear_state,
pckbd_get_state,
pckbd_set_state,
genkbd_get_fkeystr,
genkbd_diag,
};
KEYBOARD_DRIVER(pckbd, pckbdsw, pckbd_configure);
struct kbdc_softc {
int port; /* base port address */
int lock; /* FIXME: XXX not quite a semaphore... */
};
/* local functions */
static int probe_keyboard(KBDC kbdc, int flags);
static int init_keyboard(KBDC kbdc, int *type, int flags);
static KBDC kbdc_open(int port);
static int kbdc_lock(KBDC kbdc, int lock);
static int kbdc_data_ready(KBDC kbdc);
static int read_kbd_data(KBDC kbdc);
static int read_kbd_data_no_wait(KBDC kbdc);
static int wait_for_kbd_data(struct kbdc_softc *kbdc);
/* local variables */
/* the initial key map, accent map and fkey strings */
#include <i386/isa/kbdtables.h>
/* structures for the default keyboard */
static keyboard_t default_kbd;
static pckbd_state_t default_kbd_state;
static keymap_t default_keymap;
static accentmap_t default_accentmap;
static fkeytab_t default_fkeytab[NUM_FKEYS];
/*
* The back door to the keyboard driver!
* This function is called by the console driver, via the kbdio module,
* to tickle keyboard drivers when the low-level console is being initialized.
* Almost nothing in the kernel has been initialied yet. Try to probe
* keyboards if possible.
* NOTE: because of the way the low-level conole is initialized, this routine
* may be called more than once!!
*/
static int
pckbd_configure(int flags)
{
keyboard_t *kbd;
KBDC kbdc;
int arg[2];
struct isa_device *dev;
/* XXX: a kludge to obtain the device configuration flags */
dev = find_isadev(isa_devtab_tty, &pckbddriver, 0);
if (dev != NULL)
flags |= dev->id_flags;
/* probe the default keyboard */
arg[0] = -1;
arg[1] = -1;
if (pckbd_probe(PC98KBD_DEFAULT, &kbd, arg, flags))
return 0;
/* initialize it */
kbdc = ((pckbd_state_t *)kbd->kb_data)->kbdc;
if (!(flags & KB_CONF_PROBE_ONLY) && !KBD_IS_PROBED(kbd)) {
if (KBD_HAS_DEVICE(kbd)
&& init_keyboard(kbdc, &kbd->kb_type, flags)
&& (flags & KB_CONF_FAIL_IF_NO_KBD))
return 0;
KBD_INIT_DONE(kbd);
}
/* and register */
if (!KBD_IS_CONFIGURED(kbd)) {
if (kbd_register(kbd) < 0)
return 0;
KBD_CONFIG_DONE(kbd);
}
return 1; /* return the number of found keyboards */
}
/* low-level functions */
/* initialize the keyboard_t structure and try to detect a keyboard */
static int
pckbd_probe(int unit, keyboard_t **kbdp, void *arg, int flags)
{
keyboard_t *kbd;
pckbd_state_t *state;
keymap_t *keymap;
accentmap_t *accmap;
fkeytab_t *fkeymap;
int fkeymap_size;
KBDC kbdc;
int *data = (int *)arg;
if (unit != PC98KBD_DEFAULT)
return ENXIO;
*kbdp = kbd = &default_kbd;
if (KBD_IS_PROBED(kbd))
return 0;
state = &default_kbd_state;
keymap = &default_keymap;
accmap = &default_accentmap;
fkeymap = default_fkeytab;
fkeymap_size = sizeof(default_fkeytab)/sizeof(default_fkeytab[0]);
state->kbdc = kbdc = kbdc_open(data[0]);
if (kbdc == NULL)
return ENXIO;
kbd_init_struct(kbd, DRIVER_NAME, KB_OTHER, unit, flags, data[0],
IO_KBDSIZE);
bcopy(&key_map, keymap, sizeof(key_map));
bcopy(&accent_map, accmap, sizeof(accent_map));
bcopy(fkey_tab, fkeymap,
imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
kbd->kb_data = (void *)state;
if (probe_keyboard(kbdc, flags)) {
if (flags & KB_CONF_FAIL_IF_NO_KBD)
return ENXIO;
} else {
KBD_FOUND_DEVICE(kbd);
}
pckbd_clear_state(kbd);
state->ks_mode = K_XLATE;
KBD_PROBE_DONE(kbd);
return 0;
}
/* reset and initialize the device */
static int
pckbd_init(keyboard_t *kbd)
{
KBDC kbdc;
if ((kbd == NULL) || !KBD_IS_PROBED(kbd))
return ENXIO; /* shouldn't happen */
kbdc = ((pckbd_state_t *)kbd->kb_data)->kbdc;
if (kbdc == NULL)
return ENXIO; /* shouldn't happen */
if (!KBD_IS_INITIALIZED(kbd)) {
if (KBD_HAS_DEVICE(kbd)
&& init_keyboard(kbdc, &kbd->kb_type, kbd->kb_config)
&& (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD))
return ENXIO;
pckbd_ioctl(kbd, KDSETLED,
(caddr_t)&((pckbd_state_t *)(kbd->kb_data))->ks_state);
KBD_INIT_DONE(kbd);
}
if (!KBD_IS_CONFIGURED(kbd)) {
if (kbd_register(kbd) < 0)
return ENXIO;
KBD_CONFIG_DONE(kbd);
}
return 0;
}
/* finish using this keyboard */
static int
pckbd_term(keyboard_t *kbd)
{
kbd_unregister(kbd);
return 0;
}
/* keyboard interrupt routine */
static int
pckbd_intr(keyboard_t *kbd, void *arg)
{
int c;
if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
/* let the callback function to process the input */
(*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
kbd->kb_callback.kc_arg);
} else {
/* read and discard the input; no one is waiting for input */
do {
c = pckbd_read_char(kbd, FALSE);
} while (c != NOKEY);
}
return 0;
}
/* test the interface to the device */
static int
pckbd_test_if(keyboard_t *kbd)
{
return 0;
}
/*
* Enable the access to the device; until this function is called,
* the client cannot read from the keyboard.
*/
static int
pckbd_enable(keyboard_t *kbd)
{
int s;
s = spltty();
KBD_ACTIVATE(kbd);
splx(s);
return 0;
}
/* disallow the access to the device */
static int
pckbd_disable(keyboard_t *kbd)
{
int s;
s = spltty();
KBD_DEACTIVATE(kbd);
splx(s);
return 0;
}
/* read one byte from the keyboard if it's allowed */
static int
pckbd_read(keyboard_t *kbd, int wait)
{
int c;
if (wait)
c = read_kbd_data(((pckbd_state_t *)kbd->kb_data)->kbdc);
else
c = read_kbd_data_no_wait(((pckbd_state_t *)kbd->kb_data)->kbdc);
return (KBD_IS_ACTIVE(kbd) ? c : -1);
}
/* check if data is waiting */
static int
pckbd_check(keyboard_t *kbd)
{
if (!KBD_IS_ACTIVE(kbd))
return FALSE;
return kbdc_data_ready(((pckbd_state_t *)kbd->kb_data)->kbdc);
}
/* read char from the keyboard */
static u_int
pckbd_read_char(keyboard_t *kbd, int wait)
{
pckbd_state_t *state;
u_int action;
int scancode;
int keycode;
state = (pckbd_state_t *)kbd->kb_data;
next_code:
/* do we have a composed char to return? */
if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
action = state->ks_composed_char;
state->ks_composed_char = 0;
if (action > UCHAR_MAX)
return ERRKEY;
return action;
}
/* see if there is something in the keyboard port */
if (wait) {
do {
scancode = read_kbd_data(state->kbdc);
} while (scancode == -1);
} else {
scancode = read_kbd_data_no_wait(state->kbdc);
if (scancode == -1)
return NOKEY;
}
/* return the byte as is for the K_RAW mode */
if (state->ks_mode == K_RAW)
return scancode;
/* translate the scan code into a keycode */
keycode = scancode & 0x7F;
switch(scancode) {
case 0xF3: /* GRPH (compose key) released */
if (state->ks_flags & COMPOSE) {
state->ks_flags &= ~COMPOSE;
if (state->ks_composed_char > UCHAR_MAX)
state->ks_composed_char = 0;
}
break;
case 0x73: /* GRPH (compose key) pressed */
if (!(state->ks_flags & COMPOSE)) {
state->ks_flags |= COMPOSE;
state->ks_composed_char = 0;
}
break;
}
/* return the key code in the K_CODE mode */
if (state->ks_mode == K_CODE)
return (keycode | (scancode & 0x80));
/* compose a character code */
if (state->ks_flags & COMPOSE) {
switch (scancode) {
/* key pressed, process it */
case 0x42: case 0x43: case 0x44: /* keypad 7,8,9 */
state->ks_composed_char *= 10;
state->ks_composed_char += scancode - 0x3B;
if (state->ks_composed_char > UCHAR_MAX)
return ERRKEY;
goto next_code;
case 0x46: case 0x47: case 0x48: /* keypad 4,5,6 */
state->ks_composed_char *= 10;
state->ks_composed_char += scancode - 0x42;
if (state->ks_composed_char > UCHAR_MAX)
return ERRKEY;
goto next_code;
case 0x4A: case 0x4B: case 0x4C: /* keypad 1,2,3 */
state->ks_composed_char *= 10;
state->ks_composed_char += scancode - 0x49;
if (state->ks_composed_char > UCHAR_MAX)
return ERRKEY;
goto next_code;
case 0x4E: /* keypad 0 */
state->ks_composed_char *= 10;
if (state->ks_composed_char > UCHAR_MAX)
return ERRKEY;
goto next_code;
/* key released, no interest here */
case 0xC2: case 0xC3: case 0xC4: /* keypad 7,8,9 */
case 0xC6: case 0xC7: case 0xC8: /* keypad 4,5,6 */
case 0xCA: case 0xCB: case 0xCC: /* keypad 1,2,3 */
case 0xCE: /* keypad 0 */
goto next_code;
case 0x73: /* GRPH key */
break;
default:
if (state->ks_composed_char > 0) {
state->ks_flags &= ~COMPOSE;
state->ks_composed_char = 0;
return ERRKEY;
}
break;
}
}
/* keycode to key action */
action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
&state->ks_state, &state->ks_accents);
if (action == NOKEY)
goto next_code;
else
return action;
}
/* check if char is waiting */
static int
pckbd_check_char(keyboard_t *kbd)
{
pckbd_state_t *state;
if (!KBD_IS_ACTIVE(kbd))
return FALSE;
state = (pckbd_state_t *)kbd->kb_data;
if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0))
return TRUE;
return kbdc_data_ready(state->kbdc);
}
/* some useful control functions */
static int
pckbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
{
pckbd_state_t *state = kbd->kb_data;
int s;
int i;
s = spltty();
switch (cmd) {
case KDGKBMODE: /* get keyboard mode */
*(int *)arg = state->ks_mode;
break;
case KDSKBMODE: /* set keyboard mode */
switch (*(int *)arg) {
case K_XLATE:
if (state->ks_mode != K_XLATE) {
/* make lock key state and LED state match */
state->ks_state &= ~LOCK_MASK;
state->ks_state |= KBD_LED_VAL(kbd);
}
/* FALL THROUGH */
case K_RAW:
case K_CODE:
if (state->ks_mode != *(int *)arg) {
pckbd_clear_state(kbd);
state->ks_mode = *(int *)arg;
}
break;
default:
splx(s);
return EINVAL;
}
break;
case KDGETLED: /* get keyboard LED */
*(int *)arg = KBD_LED_VAL(kbd);
break;
case KDSETLED: /* set keyboard LED */
/* NOTE: lock key state in ks_state won't be changed */
if (*(int *)arg & ~LOCK_MASK) {
splx(s);
return EINVAL;
}
i = *(int *)arg;
/* replace CAPS LED with ALTGR LED for ALTGR keyboards */
if (kbd->kb_keymap->n_keys > ALTGR_OFFSET) {
if (i & ALKED)
i |= CLKED;
else
i &= ~CLKED;
}
KBD_LED_VAL(kbd) = *(int *)arg;
break;
case KDGKBSTATE: /* get lock key state */
*(int *)arg = state->ks_state & LOCK_MASK;
break;
case KDSKBSTATE: /* set lock key state */
if (*(int *)arg & ~LOCK_MASK) {
splx(s);
return EINVAL;
}
state->ks_state &= ~LOCK_MASK;
state->ks_state |= *(int *)arg;
splx(s);
/* set LEDs and quit */
return pckbd_ioctl(kbd, KDSETLED, arg);
case KDSETRAD: /* set keyboard repeat rate */
break;
case PIO_KEYMAP: /* set keyboard translation table */
case PIO_KEYMAPENT: /* set keyboard translation table entry */
case PIO_DEADKEYMAP: /* set accent key translation table */
state->ks_accents = 0;
/* FALL THROUGH */
default:
splx(s);
return genkbd_commonioctl(kbd, cmd, arg);
}
splx(s);
return 0;
}
/* lock the access to the keyboard */
static int
pckbd_lock(keyboard_t *kbd, int lock)
{
return kbdc_lock(((pckbd_state_t *)kbd->kb_data)->kbdc, lock);
}
/* clear the internal state of the keyboard */
static void
pckbd_clear_state(keyboard_t *kbd)
{
pckbd_state_t *state;
state = (pckbd_state_t *)kbd->kb_data;
state->ks_flags = 0;
state->ks_state &= LOCK_MASK; /* preserve locking key state */
state->ks_accents = 0;
state->ks_composed_char = 0;
}
/* save the internal state */
static int
pckbd_get_state(keyboard_t *kbd, void *buf, size_t len)
{
if (len == 0)
return sizeof(pckbd_state_t);
if (len < sizeof(pckbd_state_t))
return -1;
bcopy(kbd->kb_data, buf, sizeof(pckbd_state_t));
return 0;
}
/* set the internal state */
static int
pckbd_set_state(keyboard_t *kbd, void *buf, size_t len)
{
if (len < sizeof(pckbd_state_t))
return ENOMEM;
if (((pckbd_state_t *)kbd->kb_data)->kbdc
!= ((pckbd_state_t *)buf)->kbdc)
return ENOMEM;
bcopy(buf, kbd->kb_data, sizeof(pckbd_state_t));
return 0;
}
/* local functions */
static int
probe_keyboard(KBDC kbdc, int flags)
{
return 0;
}
static int
init_keyboard(KBDC kbdc, int *type, int flags)
{
*type = KB_OTHER;
return 0;
}
/* keyboard I/O routines */
/* retry count */
#ifndef KBD_MAXRETRY
#define KBD_MAXRETRY 3
#endif
/* timing parameters */
#ifndef KBD_RESETDELAY
#define KBD_RESETDELAY 200 /* wait 200msec after kbd/mouse reset */
#endif
#ifndef KBD_MAXWAIT
#define KBD_MAXWAIT 5 /* wait 5 times at most after reset */
#endif
/* I/O recovery time */
#define KBDC_DELAYTIME 37
#define KBDD_DELAYTIME 37
/* I/O ports */
#define KBD_STATUS_PORT 2 /* status port, read */
#define KBD_DATA_PORT 0 /* data port, read */
/* status bits (KBD_STATUS_PORT) */
#define KBDS_BUFFER_FULL 0x0002
/* macros */
#define kbdcp(p) ((struct kbdc_softc *)(p))
/* local variables */
static struct kbdc_softc kbdc_softc[NPCKBD] = { { 0 }, };
/* associate a port number with a KBDC */
static KBDC
kbdc_open(int port)
{
if (port <= 0)
port = IO_KBD;
if (NPCKBD) {
/* PC-98 has only one keyboard I/F */
kbdc_softc[0].port = port;
kbdc_softc[0].lock = FALSE;
return (KBDC)&kbdc_softc[0];
}
return NULL; /* You didn't include sc driver in your config file */
}
/* set/reset polling lock */
static int
kbdc_lock(KBDC p, int lock)
{
int prevlock;
prevlock = kbdcp(p)->lock;
kbdcp(p)->lock = lock;
return (prevlock != lock);
}
/* check if any data is waiting to be processed */
static int
kbdc_data_ready(KBDC p)
{
return (inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL);
}
/* wait for data from the keyboard */
static int
wait_for_kbd_data(struct kbdc_softc *kbdc)
{
/* CPU will stay inside the loop for 200msec at most */
int retry = 10000;
int port = kbdc->port;
while (!(inb(port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL)) {
DELAY(KBDD_DELAYTIME);
DELAY(KBDC_DELAYTIME);
if (--retry < 0)
return 0;
}
DELAY(KBDD_DELAYTIME);
return 1;
}
/* read one byte from the keyboard */
static int
read_kbd_data(KBDC p)
{
if (!wait_for_kbd_data(kbdcp(p)))
return -1; /* timeout */
DELAY(KBDC_DELAYTIME);
return inb(kbdcp(p)->port + KBD_DATA_PORT);
}
/* read one byte from the keyboard, but return immediately if
* no data is waiting
*/
static int
read_kbd_data_no_wait(KBDC p)
{
if (inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL) {
DELAY(KBDD_DELAYTIME);
return inb(kbdcp(p)->port + KBD_DATA_PORT);
}
return -1; /* no data */
}
#endif /* NPCKBD > 0 */

View File

@ -11,7 +11,7 @@
# device lines is present in the ./LINT configuration file. If you are
# in doubt as to the purpose or necessity of a line, check first in LINT.
#
# $Id: GENERIC98,v 1.61 1998/12/30 07:46:23 kato Exp $
# $Id: GENERIC98,v 1.62 1999/01/16 13:20:42 kato Exp $
# GENERIC98 -- Generic PC98 machine with WD/SCSI disks
@ -41,7 +41,7 @@ options SCSI_DELAY=15000 #Be pessimistic about Joe SCSI device
options EPSON_BOUNCEDMA #use bounce buufer for 15-16M
#options EPSON_MEMWIN #EPSON memory window support
options UCONSOLE #Allow users to grab the console
options "LINE30"
#options "LINE30"
options FAILSAFE #Be conservative
options USERCONFIG #boot -c editor
options VISUAL_USERCONFIG #visual boot -c editor
@ -126,7 +126,15 @@ device cd0 #Only need one of these, the code dynamically grows
controller matcd0 at isa? port? bio
device sc0 at isa? port IO_KBD tty irq 1
# keyboard driver
device pckbd0 at isa? port IO_KBD tty irq 1
#options KBD_INSTALL_CDEV
device gdc0 at isa?
#pseudo-device splash
device sc0 at isa? tty
device npx0 at isa? port IO_NPX irq 8

View File

@ -11,7 +11,7 @@
# device lines is present in the ./LINT configuration file. If you are
# in doubt as to the purpose or necessity of a line, check first in LINT.
#
# $Id: GENERIC98,v 1.61 1998/12/30 07:46:23 kato Exp $
# $Id: GENERIC98,v 1.62 1999/01/16 13:20:42 kato Exp $
# GENERIC98 -- Generic PC98 machine with WD/SCSI disks
@ -41,7 +41,7 @@ options SCSI_DELAY=15000 #Be pessimistic about Joe SCSI device
options EPSON_BOUNCEDMA #use bounce buufer for 15-16M
#options EPSON_MEMWIN #EPSON memory window support
options UCONSOLE #Allow users to grab the console
options "LINE30"
#options "LINE30"
options FAILSAFE #Be conservative
options USERCONFIG #boot -c editor
options VISUAL_USERCONFIG #visual boot -c editor
@ -126,7 +126,15 @@ device cd0 #Only need one of these, the code dynamically grows
controller matcd0 at isa? port? bio
device sc0 at isa? port IO_KBD tty irq 1
# keyboard driver
device pckbd0 at isa? port IO_KBD tty irq 1
#options KBD_INSTALL_CDEV
device gdc0 at isa?
#pseudo-device splash
device sc0 at isa? tty
device npx0 at isa? port IO_NPX irq 8

View File

@ -3,7 +3,7 @@
#
# modified for PC-9801
#
# $Id: files.pc98,v 1.78 1998/12/31 11:38:52 kato Exp $
# $Id: files.pc98,v 1.79 1999/01/04 08:07:47 kato Exp $
#
# The long compile-with and dependency lines are required because of
# limitations in config: backslash-newline doesn't work in strings, and
@ -26,6 +26,11 @@ font8x16.o optional std8x16font \
no-implicit-rule before-depend \
clean "${STD8X16FONT}-8x16 font8x16.c"
#
dev/fb/fb.c optional fb device-driver
dev/fb/fb.c optional gdc device-driver
dev/fb/splash.c optional splash
dev/kbd/kbd.c optional kbd device-driver
dev/kbd/kbd.c optional pckbd device-driver
i386/apm/apm.c optional apm device-driver
i386/apm/apm_setup.s optional apm
i386/eisa/dpt_eisa.c optional eisa dpt device-driver
@ -141,15 +146,14 @@ i386/isa/intr_machdep.c standard
pc98/pc98/pc98.c optional isa device-driver
i386/isa/istallion.c optional stli device-driver
i386/isa/joy.c optional joy device-driver
i386/isa/kbdio.c optional psm device-driver
i386/isa/kbdio.c optional sc device-driver
i386/isa/kbdio.c optional vt device-driver
pc98/pc98/pc98kbd.c optional pckbd device-driver
i386/isa/loran.c optional loran device-driver
pc98/pc98/lpt.c optional lpt device-driver
i386/isa/labpc.c optional labpc device-driver
i386/isa/mcd.c optional mcd device-driver
pc98/pc98/mse.c optional mse device-driver
pc98/pc98/npx.c mandatory npx device-driver
pc98/pc98/pc98gdc.c optional gdc device-driver
pc98/pc98/pcaudio.c optional pca device-driver
i386/isa/matcd/matcd.c optional matcd device-driver
i386/isa/pcibus.c optional pci device-driver

View File

@ -1,4 +1,4 @@
# $Id: options.pc98,v 1.76 1998/12/30 08:03:03 kato Exp $
# $Id: options.pc98,v 1.77 1999/01/04 08:09:15 kato Exp $
DISABLE_PSE
IDE_DELAY
@ -64,27 +64,29 @@ I486_CPU opt_global.h
I586_CPU opt_global.h
I686_CPU opt_global.h
SC_SPLASH_SCREEN opt_syscons.h
MAXCONS opt_syscons.h
SLOW_VGA opt_syscons.h
STD8X16FONT opt_syscons.h
SC_HISTORY_SIZE opt_syscons.h
SC_DISABLE_REBOOT opt_syscons.h
SC_MOUSE_CHAR opt_syscons.h
SC_ALT_SEQACCESS opt_syscons.h
FB_INSTALL_CDEV opt_fb.h
VESA opt_vesa.h
GDC opt_gdc.h
PSM_HOOKAPM opt_psm.h
PSM_RESETAFTERSUSPEND opt_psm.h
PSM_DEBUG opt_psm.h
PCIC_RESUME_RESET opt_pcic.h
KBD_RESETDELAY opt_kbdio.h
KBD_MAXRETRY opt_kbdio.h
KBD_MAXWAIT opt_kbdio.h
KBDIO_DEBUG opt_kbdio.h
KBD_INSTALL_CDEV opt_kbd.h
KBD_MAXRETRY opt_kbd.h
KBD_MAXWAIT opt_kbd.h
KBD_RESETDELAY opt_kbd.h
KBDIO_DEBUG opt_kbd.h
ATAPI opt_atapi.h
ATAPI_STATIC opt_atapi.h

859
sys/pc98/pc98/pc98gdc.c Normal file
View File

@ -0,0 +1,859 @@
#define TEXT_GDC IO_GDC1 /* 0x60 */
#define ROW 25
#define COL 80
/*-
* $Id$
*/
#include "gdc.h"
#include "opt_gdc.h"
#include "opt_fb.h"
#include "opt_syscons.h"
#if NGDC > 0
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/malloc.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/console.h>
#include <machine/md_var.h>
#include <machine/pc/bios.h>
#include <dev/fb/fbreg.h>
#include <pc98/pc98/pc98.h>
#include <pc98/pc98/pc98_machdep.h>
#include <i386/isa/isa_device.h>
#define DRIVER_NAME "gdc"
/* cdev driver declaration */
#define GDC_UNIT(dev) minor(dev)
#define GDC_MKMINOR(unit) (unit)
static int gdcprobe(struct isa_device *dev);
static int gdc_attach(struct isa_device *dev);
static void gdc_drvinit(void *unused);
struct isa_driver gdcdriver = {
gdcprobe,
gdc_attach,
DRIVER_NAME,
0,
};
typedef struct gdc_softc {
video_adapter_t *adp;
} gdc_softc_t;
static int gdc_probe_unit(int unit, gdc_softc_t *sc, int flags);
static int gdc_attach_unit(int unit, gdc_softc_t *sc, int flags);
#define GDC_SOFTC(unit) (gdc_softc[unit])
static gdc_softc_t *gdc_softc[NGDC];
#if FB_INSTALL_CDEV
static d_open_t gdcopen;
static d_close_t gdcclose;
static d_read_t gdcread;
static d_ioctl_t gdcioctl;
static struct cdevsw vga_cdevsw = {
gdcopen, gdcclose, noread, nowrite, /* ?? */
gdcioctl, nostop, nullreset, nodevtotty,
seltrue, nommap, NULL, DRIVER_NAME,
NULL, -1, nodump, nopsize,
};
#endif /* FB_INSTALL_CDEV */
static int
gdcprobe(struct isa_device *dev)
{
gdc_softc_t *sc;
int error;
if (dev->id_unit >= sizeof(gdc_softc)/sizeof(gdc_softc[0]))
return 0;
sc = gdc_softc[dev->id_unit]
= malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT);
if (sc == NULL)
return 0;
error = gdc_probe_unit(dev->id_unit, sc, dev->id_flags);
if (error) {
gdc_softc[dev->id_unit] = NULL;
free(sc, M_DEVBUF);
return 0;
}
dev->id_iobase = sc->adp->va_io_base;
dev->id_maddr = (caddr_t)BIOS_PADDRTOVADDR(sc->adp->va_mem_base);
dev->id_msize = sc->adp->va_mem_size;
return sc->adp->va_io_size;
}
static int
gdc_attach(struct isa_device *dev)
{
gdc_softc_t *sc;
if (dev->id_unit >= sizeof(gdc_softc)/sizeof(gdc_softc[0]))
return 0;
sc = gdc_softc[dev->id_unit];
if (sc == NULL)
return 0;
return ((gdc_attach_unit(dev->id_unit, sc, dev->id_flags)) ? 0 : 1);
}
static int
gdc_probe_unit(int unit, gdc_softc_t *sc, int flags)
{
video_switch_t *sw;
bzero(sc, sizeof(*sc));
sw = vid_get_switch(DRIVER_NAME);
if (sw == NULL)
return 0;
return (*sw->probe)(unit, &sc->adp, NULL, flags);
}
static int
gdc_attach_unit(int unit, gdc_softc_t *sc, int flags)
{
video_switch_t *sw;
int error;
sw = vid_get_switch(DRIVER_NAME);
if (sw == NULL)
return ENXIO;
error = (*sw->init)(unit, sc->adp, flags);
if (error)
return ENXIO;
#ifdef FB_INSTALL_CDEV
/* attach a virtual frame buffer device */
error = fb_attach(makedev(0, GDC_MKMINOR(unit)), scp->adp,
&vga_cdevsw);
if (error)
return error;
#endif /* FB_INSTALL_CDEV */
if (bootverbose)
(*sw->diag)(sc->adp, bootverbose);
return 0;
}
/* LOW-LEVEL */
#include <machine/clock.h>
#include <pc98/pc98/30line.h>
#define TEXT_BUF_BASE 0x000a0000
#define TEXT_BUF_SIZE 0x00008000
#define GRAPHICS_BUF_BASE 0x000a8000
#define GRAPHICS_BUF_SIZE 0x00040000
#define VIDEO_BUF_BASE 0x000a0000
#define VIDEO_BUF_SIZE 0x00048000
#define probe_done(adp) ((adp)->va_flags & V_ADP_PROBED)
#define init_done(adp) ((adp)->va_flags & V_ADP_INITIALIZED)
#define config_done(adp) ((adp)->va_flags & V_ADP_REGISTERED)
/*
* NOTE: `va_window' should have a virtual address, but is initialized
* with a physical address in the following table, they will be
* converted at run-time.
*/
static video_adapter_t adapter_init_value[] = {
{ 0,
KD_PC98, "gdc", /* va_type, va_name */
0, 0, /* va_unit, va_minor */
V_ADP_COLOR | V_ADP_MODECHANGE | V_ADP_BORDER,
IO_GDC1, 16, TEXT_GDC, /* va_io*, XXX */
VIDEO_BUF_BASE, VIDEO_BUF_SIZE, /* va_mem* */
TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, /* va_window* */
0, 0, /* va_buffer, va_buffer_size */
0, M_PC98_80x25, 0, 0, /* va_*mode* */
NULL },
};
static video_adapter_t biosadapter[1];
/* video driver declarations */
static int gdc_configure(int flags);
static int gdc_nop(void);
static vi_probe_t gdc_probe;
static vi_init_t gdc_init;
static vi_get_info_t gdc_get_info;
static vi_query_mode_t gdc_query_mode;
static vi_set_mode_t gdc_set_mode;
static vi_set_border_t gdc_set_border;
static vi_save_state_t gdc_save_state;
static vi_load_state_t gdc_load_state;
static vi_read_hw_cursor_t gdc_read_hw_cursor;
static vi_set_hw_cursor_t gdc_set_hw_cursor;
static vi_set_hw_cursor_shape_t gdc_set_hw_cursor_shape;
static vi_mmap_t gdc_mmap;
static vi_diag_t gdc_diag;
static int gdc_err(video_adapter_t *adp, ...);
static video_switch_t gdcvidsw = {
gdc_probe,
gdc_init,
gdc_get_info,
gdc_query_mode,
gdc_set_mode,
(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_set_border,
gdc_save_state,
gdc_load_state,
(vi_set_win_org_t *)gdc_err,
gdc_read_hw_cursor,
gdc_set_hw_cursor,
gdc_set_hw_cursor_shape,
(vi_blank_display_t *)gdc_nop,
gdc_mmap,
gdc_diag,
};
VIDEO_DRIVER(gdc, gdcvidsw, gdc_configure);
/* GDC BIOS standard video modes */
#define EOT (-1)
#define NA (-2)
static video_info_t bios_vmode[] = {
{ M_PC98_80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1,
TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, 0, 0 },
#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 },
#endif
{ EOT },
};
static int init_done = FALSE;
/* local functions */
static int map_gen_mode_num(int type, int color, int mode);
static int probe_adapters(void);
static void dump_buffer(u_char *buf, size_t len);
#define prologue(adp, flag, err) \
if (!init_done || !((adp)->va_flags & (flag))) \
return (err)
/* a backdoor for the console driver */
static int
gdc_configure(int flags)
{
probe_adapters();
biosadapter[0].va_flags |= V_ADP_INITIALIZED;
if (!config_done(&biosadapter[0])) {
if (vid_register(&biosadapter[0]) < 0)
return 1;
biosadapter[0].va_flags |= V_ADP_REGISTERED;
}
return 1;
}
/* local subroutines */
/* map a generic video mode to a known mode number */
static int
map_gen_mode_num(int type, int color, int mode)
{
static struct {
int from;
int to;
} mode_map[] = {
{ M_TEXT_80x25, M_PC98_80x25, },
#ifdef LINE30
{ M_TEXT_80x30, M_PC98_80x30, },
#endif
};
int i;
for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
if (mode_map[i].from == mode)
return mode_map[i].to;
}
return mode;
}
/* probe video adapters and return the number of detected adapters */
static int
probe_adapters(void)
{
video_info_t info;
/* do this test only once */
if (init_done)
return 1;
init_done = TRUE;
biosadapter[0] = adapter_init_value[0];
biosadapter[0].va_flags |= V_ADP_PROBED;
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);
biosadapter[0].va_mode_flags = info.vi_flags;
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;
biosadapter[0].va_buffer = 0;
biosadapter[0].va_buffer_size = 0;
return 1;
}
static void master_gdc_cmd(unsigned int cmd)
{
while ( (inb(IO_GDC1) & 2) != 0);
outb(IO_GDC1+2, cmd);
}
static void master_gdc_prm(unsigned int pmtr)
{
while ( (inb(IO_GDC1) & 2) != 0);
outb(IO_GDC1, pmtr);
}
static void master_gdc_word_prm(unsigned int wpmtr)
{
master_gdc_prm(wpmtr & 0x00ff);
master_gdc_prm((wpmtr >> 8) & 0x00ff);
}
static void master_gdc_fifo_empty(void)
{
while ( (inb(IO_GDC1) & 4) == 0);
}
static void master_gdc_wait_vsync(void)
{
while ( (inb(IO_GDC1) & 0x20) != 0);
while ( (inb(IO_GDC1) & 0x20) == 0);
}
static void gdc_cmd(unsigned int cmd)
{
while ( (inb(IO_GDC2) & 2) != 0);
outb( IO_GDC2+2, cmd);
}
static void gdc_prm(unsigned int pmtr)
{
while ( (inb(IO_GDC2) & 2) != 0);
outb( IO_GDC2, pmtr);
}
static void gdc_word_prm(unsigned int wpmtr)
{
gdc_prm(wpmtr & 0x00ff);
gdc_prm((wpmtr >> 8) & 0x00ff);
}
static void gdc_fifo_empty(void)
{
while ( (inb(IO_GDC2) & 0x04) == 0);
}
static void gdc_wait_vsync(void)
{
while ( (inb(IO_GDC2) & 0x20) != 0);
while ( (inb(IO_GDC2) & 0x20) == 0);
}
static int check_gdc_clock(void)
{
if ((inb(IO_SYSPORT) & 0x80) == 0){
return _5MHZ;
} else {
return _2_5MHZ;
}
}
static void initialize_gdc(unsigned int mode)
{
/* start 30line initialize */
int m_mode,s_mode,gdc_clock;
gdc_clock = check_gdc_clock();
if (mode == T25_G400){
m_mode = _25L;
}else{
m_mode = _30L;
}
s_mode = 2*mode+gdc_clock;
gdc_INFO = m_mode;
master_gdc_cmd(_GDC_RESET);
master_gdc_cmd(_GDC_MASTER);
gdc_cmd(_GDC_RESET);
gdc_cmd(_GDC_SLAVE);
/* 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_fifo_empty();
master_gdc_cmd(_GDC_PITCH);
master_gdc_prm(MasterPCH);
master_gdc_fifo_empty();
/* 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_fifo_empty();
gdc_cmd(_GDC_PITCH);
gdc_prm(SlavePCH[gdc_clock]);
gdc_fifo_empty();
/* set Master GDC scroll param */
master_gdc_wait_vsync();
master_gdc_wait_vsync();
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_fifo_empty();
/* set Slave GDC scroll param */
gdc_wait_vsync();
gdc_cmd(_GDC_SCROLL);
gdc_word_prm(0);
if (gdc_clock == _5MHZ){
gdc_word_prm((SlaveScrlLF[mode] << 4) | 0x4000);
}else{
gdc_word_prm(SlaveScrlLF[mode] << 4);
}
gdc_fifo_empty();
gdc_word_prm(0);
if (gdc_clock == _5MHZ){
gdc_word_prm((SlaveScrlLF[mode] << 4) | 0x4000);
}else{
gdc_word_prm(SlaveScrlLF[mode] << 4);
}
gdc_fifo_empty();
/* sync start */
gdc_cmd(_GDC_STOP);
gdc_wait_vsync();
gdc_wait_vsync();
gdc_wait_vsync();
master_gdc_cmd(_GDC_START);
}
/* entry points */
static int
gdc_nop(void)
{
return 0;
}
static int
gdc_probe(int unit, video_adapter_t **adpp, void *arg, int flags)
{
probe_adapters();
if (unit >= 1)
return ENXIO;
*adpp = &biosadapter[unit];
return 0;
}
static int
gdc_init(int unit, video_adapter_t *adp, int flags)
{
if ((unit >= 1) || (adp == NULL) || !probe_done(adp))
return ENXIO;
if (!init_done(adp)) {
/* nothing to do really... */
adp->va_flags |= V_ADP_INITIALIZED;
}
if (!config_done(adp)) {
if (vid_register(adp) < 0)
return ENXIO;
adp->va_flags |= V_ADP_REGISTERED;
}
return 0;
}
/*
* get_info():
* Return the video_info structure of the requested video mode.
*/
static int
gdc_get_info(video_adapter_t *adp, int mode, video_info_t *info)
{
int i;
if (!init_done)
return 1;
mode = map_gen_mode_num(adp->va_type, adp->va_flags & V_ADP_COLOR, mode);
for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
if (bios_vmode[i].vi_mode == NA)
continue;
if (mode == bios_vmode[i].vi_mode) {
*info = bios_vmode[i];
return 0;
}
}
return 1;
}
/*
* query_mode():
* Find a video mode matching the requested parameters.
* Fields filled with 0 are considered "don't care" fields and
* match any modes.
*/
static int
gdc_query_mode(video_adapter_t *adp, video_info_t *info)
{
video_info_t buf;
int i;
if (!init_done)
return -1;
for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
if (bios_vmode[i].vi_mode == NA)
continue;
if ((info->vi_width != 0)
&& (info->vi_width != bios_vmode[i].vi_width))
continue;
if ((info->vi_height != 0)
&& (info->vi_height != bios_vmode[i].vi_height))
continue;
if ((info->vi_cwidth != 0)
&& (info->vi_cwidth != bios_vmode[i].vi_cwidth))
continue;
if ((info->vi_cheight != 0)
&& (info->vi_cheight != bios_vmode[i].vi_cheight))
continue;
if ((info->vi_depth != 0)
&& (info->vi_depth != bios_vmode[i].vi_depth))
continue;
if ((info->vi_planes != 0)
&& (info->vi_planes != bios_vmode[i].vi_planes))
continue;
/* XXX: should check pixel format, memory model */
if ((info->vi_flags != 0)
&& (info->vi_flags != bios_vmode[i].vi_flags))
continue;
/* verify if this mode is supported on this adapter */
if (gdc_get_info(adp, bios_vmode[i].vi_mode, &buf))
continue;
return bios_vmode[i].vi_mode;
}
return -1;
}
/*
* set_mode():
* Change the video mode.
*/
static int
gdc_set_mode(video_adapter_t *adp, int mode)
{
video_info_t info;
prologue(adp, V_ADP_MODECHANGE, 1);
mode = map_gen_mode_num(adp->va_type,
adp->va_flags & V_ADP_COLOR, mode);
if (gdc_get_info(adp, mode, &info))
return 1;
#ifdef LINE30
switch (scp->mode) {
case M_PC98_80x25: /* VGA TEXT MODES */
initialize_gdc(T25_G400);
break;
case M_PC98_80x30:
initialize_gdc(T30_G400);
break;
default:
break;
}
#endif
adp->va_mode = mode;
adp->va_mode_flags = info.vi_flags;
adp->va_flags &= ~V_ADP_COLOR;
adp->va_flags |=
(info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0;
#if 0
adp->va_crtc_addr =
(adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC;
#endif
adp->va_window = BIOS_PADDRTOVADDR(info.vi_window);
adp->va_window_size = info.vi_window_size;
adp->va_window_gran = info.vi_window_gran;
if (info.vi_buffer_size == 0) {
adp->va_buffer = 0;
adp->va_buffer_size = 0;
} else {
adp->va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer);
adp->va_buffer_size = info.vi_buffer_size;
}
/* move hardware cursor out of the way */
(*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1);
return 0;
}
/*
* set_border():
* Change the border color.
*/
static int
gdc_set_border(video_adapter_t *adp, int color)
{
outb(0x6c, color << 4);
return 0;
}
/*
* save_state():
* Read video card register values.
*/
static int
gdc_save_state(video_adapter_t *adp, void *p, size_t size)
{
return 1;
}
/*
* load_state():
* Set video card registers at once.
*/
static int
gdc_load_state(video_adapter_t *adp, void *p)
{
return 1;
}
/*
* read_hw_cursor():
* Read the position of the hardware text cursor.
*/
static int
gdc_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
{
video_info_t info;
u_int16_t off;
int s;
if (!init_done)
return 1;
(*vidsw[adp->va_index]->get_info)(adp, adp->va_mode, &info);
if (info.vi_flags & V_INFO_GRAPHICS)
return 1;
s = spltty();
master_gdc_cmd(0xe0); /* _GDC_CSRR */
while((inb(TEXT_GDC + 0) & 0x1) == 0) {} /* GDC wait */
off = inb(TEXT_GDC + 2); /* EADl */
off |= (inb(TEXT_GDC + 2) << 8); /* EADh */
inb(TEXT_GDC + 2); /* dummy */
inb(TEXT_GDC + 2); /* dummy */
inb(TEXT_GDC + 2); /* dummy */
splx(s);
if (off >= ROW*COL)
off = 0;
*row = off / info.vi_width;
*col = off % info.vi_width;
return 0;
}
/*
* set_hw_cursor():
* Move the hardware text cursor. If col and row are both -1,
* the cursor won't be shown.
*/
static int
gdc_set_hw_cursor(video_adapter_t *adp, int col, int row)
{
video_info_t info;
u_int16_t off;
int s;
if (!init_done)
return 1;
if ((col == -1) && (row == -1)) {
off = -1;
} else {
(*vidsw[adp->va_index]->get_info)(adp, adp->va_mode, &info);
if (info.vi_flags & V_INFO_GRAPHICS)
return 1;
off = row*info.vi_width + col;
}
s = spltty();
master_gdc_cmd(0x49); /* _GDC_CSRW */
master_gdc_word_prm(off);
splx(s);
return 0;
}
/*
* set_hw_cursor_shape():
* Change the shape of the hardware text cursor. If the height is zero
* or negative, the cursor won't be shown.
*/
static int
gdc_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
int celsize, int blink)
{
int start;
int end;
int s;
start = celsize - (base + height);
end = celsize - base - 1;
/*
* muPD7220 GDC has anomaly that if end == celsize - 1 then start
* must be 0, otherwise the cursor won't be correctly shown
* in the first row in the screen. We shall set end to celsize - 2;
* if end == celsize -1 && start > 0. XXX
*/
if ((end == celsize - 1) && (start > 0))
--end;
s = spltty();
master_gdc_cmd(0x4b); /* _GDC_CSRFORM */
master_gdc_prm(((height > 0) ? 0x80 : 0) /* cursor on/off */
| (celsize - 1) & 0x1f); /* cel size */
master_gdc_word_prm(((end & 0x1f) << 11) /* end line */
| (12 << 6) /* blink rate */
| (blink ? 0x20 : 0) /* blink on/off */
| (start & 0x1f)); /* start line */
splx(s);
return 1;
}
static void
dump_buffer(u_char *buf, size_t len)
{
int i;
for(i = 0; i < len;) {
printf("%02x ", buf[i]);
if ((++i % 16) == 0)
printf("\n");
}
}
/*
* mmap():
* Mmap frame buffer.
*/
static int
gdc_mmap(video_adapter_t *adp, vm_offset_t offset)
{
if (offset > 0x48000 - PAGE_SIZE)
return -1;
return i386_btop((VIDEO_BUF_BASE + offset));
}
/*
* diag():
* Print some information about the video adapter and video modes,
* with requested level of details.
*/
static int
gdc_diag(video_adapter_t *adp, int level)
{
video_info_t info;
int i;
if (!init_done)
return 1;
fb_dump_adp_info(DRIVER_NAME, adp, level);
#if FB_DEBUG > 1
for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
if (bios_vmode[i].vi_mode == NA)
continue;
if (get_mode_param(bios_vmode[i].vi_mode) == NULL)
continue;
fb_dump_mode_info(DRIVER_NAME, adp, &bios_vmode[i], level);
}
#endif
return 0;
}
static int
gdc_err(video_adapter_t *adp, ...)
{
return 0;
}
#endif /* NGDC > 0 */

983
sys/pc98/pc98/pc98kbd.c Normal file
View File

@ -0,0 +1,983 @@
/*-
* $Id$
*/
#include "pckbd.h"
#include "opt_kbd.h"
#include "opt_devfs.h"
#if NPCKBD > 0
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/conf.h>
#include <sys/proc.h>
#include <sys/tty.h>
#include <sys/fcntl.h>
#include <sys/bus.h>
#include <sys/malloc.h>
#include <machine/resource.h>
#include <dev/kbd/kbdreg.h>
#include <pc98/pc98/pc98.h>
#include <pc98/pc98/pc98_machdep.h>
#ifdef __i386__
#include <i386/isa/isa_device.h>
#endif
#define DRIVER_NAME "pckbd"
/* device configuration flags */
#define KB_CONF_FAIL_IF_NO_KBD (1 << 0) /* don't install if no kbd is found */
/* some macros */
#define PC98KBD_UNIT(dev) minor(dev)
#define PC98KBD_MKMINOR(unit) (unit)
/* cdev driver declaration */
typedef struct pckbd_softc {
short flags;
#define PC98KBD_ATTACHED (1 << 0)
keyboard_t *kbd;
#ifdef KBD_INSTALL_CDEV
genkbd_softc_t gensc;
#endif
} pckbd_softc_t;
#define PC98KBD_SOFTC(unit) pckbd_softc[(unit)]
static pckbd_softc_t *pckbd_softc[NPCKBD];
static int pckbdprobe(struct isa_device *dev);
static int pckbdattach(struct isa_device *dev);
static ointhand2_t pckbd_isa_intr;
/* driver declaration for isa_devtab_tty[] */
struct isa_driver pckbddriver = {
pckbdprobe,
pckbdattach,
DRIVER_NAME,
0,
};
static int pckbd_probe_unit(int unit, pckbd_softc_t *sc,
int port, int irq, int flags);
static int pckbd_attach_unit(int unit, pckbd_softc_t *sc);
static timeout_t pckbd_timeout;
#ifdef KBD_INSTALL_CDEV
static d_open_t pckbdopen;
static d_close_t pckbdclose;
static d_read_t pckbdread;
static d_ioctl_t pckbdioctl;
static d_poll_t pckbdpoll;
static struct cdevsw pckbd_cdevsw = {
pckbdopen, pckbdclose, pckbdread, nowrite,
pckbdioctl, nostop, nullreset, nodevtotty,
pckbdpoll, nommap, NULL, DRIVER_NAME,
NULL, -1,
};
#endif /* KBD_INSTALL_CDEV */
static int
pckbdprobe(struct isa_device *dev)
{
pckbd_softc_t *sc;
int error;
if (dev->id_unit >= sizeof(pckbd_softc)/sizeof(pckbd_softc[0]))
return 0;
sc = pckbd_softc[dev->id_unit];
if (sc == NULL) {
sc = pckbd_softc[dev->id_unit]
= malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT);
if (sc == NULL)
return 0;
bzero(sc, sizeof(*sc));
}
/* try to find a keyboard */
error = pckbd_probe_unit(dev->id_unit, sc, dev->id_iobase,
dev->id_irq, dev->id_flags);
if (error)
return 0;
/* declare our interrupt handler */
dev->id_ointr = pckbd_isa_intr;
return IO_KBDSIZE;
}
static int
pckbdattach(struct isa_device *dev)
{
pckbd_softc_t *sc;
if (dev->id_unit >= sizeof(pckbd_softc)/sizeof(pckbd_softc[0]))
return 0;
sc = pckbd_softc[dev->id_unit];
if (sc == NULL)
return 0;
return ((pckbd_attach_unit(dev->id_unit, sc)) ? 0 : 1);
}
static void
pckbd_isa_intr(int unit)
{
keyboard_t *kbd;
kbd = pckbd_softc[unit]->kbd;
(*kbdsw[kbd->kb_index]->intr)(kbd, NULL);
}
static int
pckbd_probe_unit(int unit, pckbd_softc_t *sc, int port, int irq, int flags)
{
keyboard_switch_t *sw;
int args[2];
if (sc->flags & PC98KBD_ATTACHED)
return 0;
sw = kbd_get_switch(DRIVER_NAME);
if (sw == NULL)
return ENXIO;
args[0] = port;
args[1] = irq;
return (*sw->probe)(unit, &sc->kbd, args, flags);
}
static int
pckbd_attach_unit(int unit, pckbd_softc_t *sc)
{
keyboard_switch_t *sw;
int error;
if (sc->flags & PC98KBD_ATTACHED)
return 0;
sw = kbd_get_switch(DRIVER_NAME);
if (sw == NULL)
return ENXIO;
/* reset, initialize and enable the device */
error = (*sw->init)(sc->kbd);
if (error)
return ENXIO;
(*sw->enable)(sc->kbd);
#ifdef KBD_INSTALL_CDEV
/* attach a virtual keyboard cdev */
error = kbd_attach(makedev(0, PC98KBD_MKMINOR(unit)), sc->kbd,
&pckbd_cdevsw);
if (error)
return error;
#endif /* KBD_INSTALL_CDEV */
/*
* This is a kludge to compensate for lost keyboard interrupts.
* A similar code used to be in syscons. See below. XXX
*/
pckbd_timeout(sc->kbd);
if (bootverbose)
(*sw->diag)(sc->kbd, bootverbose);
sc->flags |= PC98KBD_ATTACHED;
return 0;
}
static void
pckbd_timeout(void *arg)
{
keyboard_t *kbd;
int s;
/* The following comments are extracted from syscons.c (1.287) */
/*
* With release 2.1 of the Xaccel server, the keyboard is left
* hanging pretty often. Apparently an interrupt from the
* keyboard is lost, and I don't know why (yet).
* This ugly hack calls scintr if input is ready for the keyboard
* and conveniently hides the problem. XXX
*/
/*
* Try removing anything stuck in the keyboard controller; whether
* it's a keyboard scan code or mouse data. `scintr()' doesn't
* read the mouse data directly, but `kbdio' routines will, as a
* side effect.
*/
s = spltty();
kbd = (keyboard_t *)arg;
if ((*kbdsw[kbd->kb_index]->lock)(kbd, TRUE)) {
/*
* We have seen the lock flag is not set. Let's reset
* the flag early, otherwise the LED update routine fails
* which may want the lock during the interrupt routine.
*/
(*kbdsw[kbd->kb_index]->lock)(kbd, FALSE);
if ((*kbdsw[kbd->kb_index]->check_char)(kbd))
(*kbdsw[kbd->kb_index]->intr)(kbd, NULL);
}
splx(s);
timeout(pckbd_timeout, arg, hz/10);
}
/* cdev driver functions */
#ifdef KBD_INSTALL_CDEV
static int
pckbdopen(dev_t dev, int flag, int mode, struct proc *p)
{
pckbd_softc_t *sc;
int unit;
unit = PC98KBD_UNIT(dev);
if ((unit >= NPCKBD) || ((sc = PC98KBD_SOFTC(unit)) == NULL))
return ENXIO;
if (mode & (FWRITE | O_CREAT | O_APPEND | O_TRUNC))
return ENODEV;
/* FIXME: set the initial input mode (K_XLATE?) and lock state? */
return genkbdopen(&sc->gensc, sc->kbd, flag, mode, p);
}
static int
pckbdclose(dev_t dev, int flag, int mode, struct proc *p)
{
pckbd_softc_t *sc;
sc = PC98KBD_SOFTC(PC98KBD_UNIT(dev));
return genkbdclose(&sc->gensc, sc->kbd, flag, mode, p);
}
static int
pckbdread(dev_t dev, struct uio *uio, int flag)
{
pckbd_softc_t *sc;
sc = PC98KBD_SOFTC(PC98KBD_UNIT(dev));
return genkbdread(&sc->gensc, sc->kbd, uio, flag);
}
static int
pckbdioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
{
pckbd_softc_t *sc;
sc = PC98KBD_SOFTC(PC98KBD_UNIT(dev));
return genkbdioctl(&sc->gensc, sc->kbd, cmd, arg, flag, p);
}
static int
pckbdpoll(dev_t dev, int event, struct proc *p)
{
pckbd_softc_t *sc;
sc = PC98KBD_SOFTC(PC98KBD_UNIT(dev));
return genkbdpoll(&sc->gensc, sc->kbd, event, p);
}
#endif /* KBD_INSTALL_CDEV */
/* LOW-LEVEL */
#include <machine/limits.h>
#include <machine/console.h>
#include <machine/clock.h>
#define PC98KBD_DEFAULT 0
typedef caddr_t KBDC;
typedef struct pckbd_state {
KBDC kbdc; /* keyboard controller */
int ks_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */
int ks_flags; /* flags */
#define COMPOSE (1 << 0)
int ks_state; /* shift/lock key state */
int ks_accents; /* accent key index (> 0) */
u_int ks_composed_char; /* composed char code (> 0) */
} pckbd_state_t;
/* keyboard driver declaration */
static int pckbd_configure(int flags);
static kbd_probe_t pckbd_probe;
static kbd_init_t pckbd_init;
static kbd_term_t pckbd_term;
static kbd_intr_t pckbd_intr;
static kbd_test_if_t pckbd_test_if;
static kbd_enable_t pckbd_enable;
static kbd_disable_t pckbd_disable;
static kbd_read_t pckbd_read;
static kbd_check_t pckbd_check;
static kbd_read_char_t pckbd_read_char;
static kbd_check_char_t pckbd_check_char;
static kbd_ioctl_t pckbd_ioctl;
static kbd_lock_t pckbd_lock;
static kbd_clear_state_t pckbd_clear_state;
static kbd_get_state_t pckbd_get_state;
static kbd_set_state_t pckbd_set_state;
keyboard_switch_t pckbdsw = {
pckbd_probe,
pckbd_init,
pckbd_term,
pckbd_intr,
pckbd_test_if,
pckbd_enable,
pckbd_disable,
pckbd_read,
pckbd_check,
pckbd_read_char,
pckbd_check_char,
pckbd_ioctl,
pckbd_lock,
pckbd_clear_state,
pckbd_get_state,
pckbd_set_state,
genkbd_get_fkeystr,
genkbd_diag,
};
KEYBOARD_DRIVER(pckbd, pckbdsw, pckbd_configure);
struct kbdc_softc {
int port; /* base port address */
int lock; /* FIXME: XXX not quite a semaphore... */
};
/* local functions */
static int probe_keyboard(KBDC kbdc, int flags);
static int init_keyboard(KBDC kbdc, int *type, int flags);
static KBDC kbdc_open(int port);
static int kbdc_lock(KBDC kbdc, int lock);
static int kbdc_data_ready(KBDC kbdc);
static int read_kbd_data(KBDC kbdc);
static int read_kbd_data_no_wait(KBDC kbdc);
static int wait_for_kbd_data(struct kbdc_softc *kbdc);
/* local variables */
/* the initial key map, accent map and fkey strings */
#include <i386/isa/kbdtables.h>
/* structures for the default keyboard */
static keyboard_t default_kbd;
static pckbd_state_t default_kbd_state;
static keymap_t default_keymap;
static accentmap_t default_accentmap;
static fkeytab_t default_fkeytab[NUM_FKEYS];
/*
* The back door to the keyboard driver!
* This function is called by the console driver, via the kbdio module,
* to tickle keyboard drivers when the low-level console is being initialized.
* Almost nothing in the kernel has been initialied yet. Try to probe
* keyboards if possible.
* NOTE: because of the way the low-level conole is initialized, this routine
* may be called more than once!!
*/
static int
pckbd_configure(int flags)
{
keyboard_t *kbd;
KBDC kbdc;
int arg[2];
struct isa_device *dev;
/* XXX: a kludge to obtain the device configuration flags */
dev = find_isadev(isa_devtab_tty, &pckbddriver, 0);
if (dev != NULL)
flags |= dev->id_flags;
/* probe the default keyboard */
arg[0] = -1;
arg[1] = -1;
if (pckbd_probe(PC98KBD_DEFAULT, &kbd, arg, flags))
return 0;
/* initialize it */
kbdc = ((pckbd_state_t *)kbd->kb_data)->kbdc;
if (!(flags & KB_CONF_PROBE_ONLY) && !KBD_IS_PROBED(kbd)) {
if (KBD_HAS_DEVICE(kbd)
&& init_keyboard(kbdc, &kbd->kb_type, flags)
&& (flags & KB_CONF_FAIL_IF_NO_KBD))
return 0;
KBD_INIT_DONE(kbd);
}
/* and register */
if (!KBD_IS_CONFIGURED(kbd)) {
if (kbd_register(kbd) < 0)
return 0;
KBD_CONFIG_DONE(kbd);
}
return 1; /* return the number of found keyboards */
}
/* low-level functions */
/* initialize the keyboard_t structure and try to detect a keyboard */
static int
pckbd_probe(int unit, keyboard_t **kbdp, void *arg, int flags)
{
keyboard_t *kbd;
pckbd_state_t *state;
keymap_t *keymap;
accentmap_t *accmap;
fkeytab_t *fkeymap;
int fkeymap_size;
KBDC kbdc;
int *data = (int *)arg;
if (unit != PC98KBD_DEFAULT)
return ENXIO;
*kbdp = kbd = &default_kbd;
if (KBD_IS_PROBED(kbd))
return 0;
state = &default_kbd_state;
keymap = &default_keymap;
accmap = &default_accentmap;
fkeymap = default_fkeytab;
fkeymap_size = sizeof(default_fkeytab)/sizeof(default_fkeytab[0]);
state->kbdc = kbdc = kbdc_open(data[0]);
if (kbdc == NULL)
return ENXIO;
kbd_init_struct(kbd, DRIVER_NAME, KB_OTHER, unit, flags, data[0],
IO_KBDSIZE);
bcopy(&key_map, keymap, sizeof(key_map));
bcopy(&accent_map, accmap, sizeof(accent_map));
bcopy(fkey_tab, fkeymap,
imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
kbd->kb_data = (void *)state;
if (probe_keyboard(kbdc, flags)) {
if (flags & KB_CONF_FAIL_IF_NO_KBD)
return ENXIO;
} else {
KBD_FOUND_DEVICE(kbd);
}
pckbd_clear_state(kbd);
state->ks_mode = K_XLATE;
KBD_PROBE_DONE(kbd);
return 0;
}
/* reset and initialize the device */
static int
pckbd_init(keyboard_t *kbd)
{
KBDC kbdc;
if ((kbd == NULL) || !KBD_IS_PROBED(kbd))
return ENXIO; /* shouldn't happen */
kbdc = ((pckbd_state_t *)kbd->kb_data)->kbdc;
if (kbdc == NULL)
return ENXIO; /* shouldn't happen */
if (!KBD_IS_INITIALIZED(kbd)) {
if (KBD_HAS_DEVICE(kbd)
&& init_keyboard(kbdc, &kbd->kb_type, kbd->kb_config)
&& (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD))
return ENXIO;
pckbd_ioctl(kbd, KDSETLED,
(caddr_t)&((pckbd_state_t *)(kbd->kb_data))->ks_state);
KBD_INIT_DONE(kbd);
}
if (!KBD_IS_CONFIGURED(kbd)) {
if (kbd_register(kbd) < 0)
return ENXIO;
KBD_CONFIG_DONE(kbd);
}
return 0;
}
/* finish using this keyboard */
static int
pckbd_term(keyboard_t *kbd)
{
kbd_unregister(kbd);
return 0;
}
/* keyboard interrupt routine */
static int
pckbd_intr(keyboard_t *kbd, void *arg)
{
int c;
if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
/* let the callback function to process the input */
(*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
kbd->kb_callback.kc_arg);
} else {
/* read and discard the input; no one is waiting for input */
do {
c = pckbd_read_char(kbd, FALSE);
} while (c != NOKEY);
}
return 0;
}
/* test the interface to the device */
static int
pckbd_test_if(keyboard_t *kbd)
{
return 0;
}
/*
* Enable the access to the device; until this function is called,
* the client cannot read from the keyboard.
*/
static int
pckbd_enable(keyboard_t *kbd)
{
int s;
s = spltty();
KBD_ACTIVATE(kbd);
splx(s);
return 0;
}
/* disallow the access to the device */
static int
pckbd_disable(keyboard_t *kbd)
{
int s;
s = spltty();
KBD_DEACTIVATE(kbd);
splx(s);
return 0;
}
/* read one byte from the keyboard if it's allowed */
static int
pckbd_read(keyboard_t *kbd, int wait)
{
int c;
if (wait)
c = read_kbd_data(((pckbd_state_t *)kbd->kb_data)->kbdc);
else
c = read_kbd_data_no_wait(((pckbd_state_t *)kbd->kb_data)->kbdc);
return (KBD_IS_ACTIVE(kbd) ? c : -1);
}
/* check if data is waiting */
static int
pckbd_check(keyboard_t *kbd)
{
if (!KBD_IS_ACTIVE(kbd))
return FALSE;
return kbdc_data_ready(((pckbd_state_t *)kbd->kb_data)->kbdc);
}
/* read char from the keyboard */
static u_int
pckbd_read_char(keyboard_t *kbd, int wait)
{
pckbd_state_t *state;
u_int action;
int scancode;
int keycode;
state = (pckbd_state_t *)kbd->kb_data;
next_code:
/* do we have a composed char to return? */
if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
action = state->ks_composed_char;
state->ks_composed_char = 0;
if (action > UCHAR_MAX)
return ERRKEY;
return action;
}
/* see if there is something in the keyboard port */
if (wait) {
do {
scancode = read_kbd_data(state->kbdc);
} while (scancode == -1);
} else {
scancode = read_kbd_data_no_wait(state->kbdc);
if (scancode == -1)
return NOKEY;
}
/* return the byte as is for the K_RAW mode */
if (state->ks_mode == K_RAW)
return scancode;
/* translate the scan code into a keycode */
keycode = scancode & 0x7F;
switch(scancode) {
case 0xF3: /* GRPH (compose key) released */
if (state->ks_flags & COMPOSE) {
state->ks_flags &= ~COMPOSE;
if (state->ks_composed_char > UCHAR_MAX)
state->ks_composed_char = 0;
}
break;
case 0x73: /* GRPH (compose key) pressed */
if (!(state->ks_flags & COMPOSE)) {
state->ks_flags |= COMPOSE;
state->ks_composed_char = 0;
}
break;
}
/* return the key code in the K_CODE mode */
if (state->ks_mode == K_CODE)
return (keycode | (scancode & 0x80));
/* compose a character code */
if (state->ks_flags & COMPOSE) {
switch (scancode) {
/* key pressed, process it */
case 0x42: case 0x43: case 0x44: /* keypad 7,8,9 */
state->ks_composed_char *= 10;
state->ks_composed_char += scancode - 0x3B;
if (state->ks_composed_char > UCHAR_MAX)
return ERRKEY;
goto next_code;
case 0x46: case 0x47: case 0x48: /* keypad 4,5,6 */
state->ks_composed_char *= 10;
state->ks_composed_char += scancode - 0x42;
if (state->ks_composed_char > UCHAR_MAX)
return ERRKEY;
goto next_code;
case 0x4A: case 0x4B: case 0x4C: /* keypad 1,2,3 */
state->ks_composed_char *= 10;
state->ks_composed_char += scancode - 0x49;
if (state->ks_composed_char > UCHAR_MAX)
return ERRKEY;
goto next_code;
case 0x4E: /* keypad 0 */
state->ks_composed_char *= 10;
if (state->ks_composed_char > UCHAR_MAX)
return ERRKEY;
goto next_code;
/* key released, no interest here */
case 0xC2: case 0xC3: case 0xC4: /* keypad 7,8,9 */
case 0xC6: case 0xC7: case 0xC8: /* keypad 4,5,6 */
case 0xCA: case 0xCB: case 0xCC: /* keypad 1,2,3 */
case 0xCE: /* keypad 0 */
goto next_code;
case 0x73: /* GRPH key */
break;
default:
if (state->ks_composed_char > 0) {
state->ks_flags &= ~COMPOSE;
state->ks_composed_char = 0;
return ERRKEY;
}
break;
}
}
/* keycode to key action */
action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
&state->ks_state, &state->ks_accents);
if (action == NOKEY)
goto next_code;
else
return action;
}
/* check if char is waiting */
static int
pckbd_check_char(keyboard_t *kbd)
{
pckbd_state_t *state;
if (!KBD_IS_ACTIVE(kbd))
return FALSE;
state = (pckbd_state_t *)kbd->kb_data;
if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0))
return TRUE;
return kbdc_data_ready(state->kbdc);
}
/* some useful control functions */
static int
pckbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
{
pckbd_state_t *state = kbd->kb_data;
int s;
int i;
s = spltty();
switch (cmd) {
case KDGKBMODE: /* get keyboard mode */
*(int *)arg = state->ks_mode;
break;
case KDSKBMODE: /* set keyboard mode */
switch (*(int *)arg) {
case K_XLATE:
if (state->ks_mode != K_XLATE) {
/* make lock key state and LED state match */
state->ks_state &= ~LOCK_MASK;
state->ks_state |= KBD_LED_VAL(kbd);
}
/* FALL THROUGH */
case K_RAW:
case K_CODE:
if (state->ks_mode != *(int *)arg) {
pckbd_clear_state(kbd);
state->ks_mode = *(int *)arg;
}
break;
default:
splx(s);
return EINVAL;
}
break;
case KDGETLED: /* get keyboard LED */
*(int *)arg = KBD_LED_VAL(kbd);
break;
case KDSETLED: /* set keyboard LED */
/* NOTE: lock key state in ks_state won't be changed */
if (*(int *)arg & ~LOCK_MASK) {
splx(s);
return EINVAL;
}
i = *(int *)arg;
/* replace CAPS LED with ALTGR LED for ALTGR keyboards */
if (kbd->kb_keymap->n_keys > ALTGR_OFFSET) {
if (i & ALKED)
i |= CLKED;
else
i &= ~CLKED;
}
KBD_LED_VAL(kbd) = *(int *)arg;
break;
case KDGKBSTATE: /* get lock key state */
*(int *)arg = state->ks_state & LOCK_MASK;
break;
case KDSKBSTATE: /* set lock key state */
if (*(int *)arg & ~LOCK_MASK) {
splx(s);
return EINVAL;
}
state->ks_state &= ~LOCK_MASK;
state->ks_state |= *(int *)arg;
splx(s);
/* set LEDs and quit */
return pckbd_ioctl(kbd, KDSETLED, arg);
case KDSETRAD: /* set keyboard repeat rate */
break;
case PIO_KEYMAP: /* set keyboard translation table */
case PIO_KEYMAPENT: /* set keyboard translation table entry */
case PIO_DEADKEYMAP: /* set accent key translation table */
state->ks_accents = 0;
/* FALL THROUGH */
default:
splx(s);
return genkbd_commonioctl(kbd, cmd, arg);
}
splx(s);
return 0;
}
/* lock the access to the keyboard */
static int
pckbd_lock(keyboard_t *kbd, int lock)
{
return kbdc_lock(((pckbd_state_t *)kbd->kb_data)->kbdc, lock);
}
/* clear the internal state of the keyboard */
static void
pckbd_clear_state(keyboard_t *kbd)
{
pckbd_state_t *state;
state = (pckbd_state_t *)kbd->kb_data;
state->ks_flags = 0;
state->ks_state &= LOCK_MASK; /* preserve locking key state */
state->ks_accents = 0;
state->ks_composed_char = 0;
}
/* save the internal state */
static int
pckbd_get_state(keyboard_t *kbd, void *buf, size_t len)
{
if (len == 0)
return sizeof(pckbd_state_t);
if (len < sizeof(pckbd_state_t))
return -1;
bcopy(kbd->kb_data, buf, sizeof(pckbd_state_t));
return 0;
}
/* set the internal state */
static int
pckbd_set_state(keyboard_t *kbd, void *buf, size_t len)
{
if (len < sizeof(pckbd_state_t))
return ENOMEM;
if (((pckbd_state_t *)kbd->kb_data)->kbdc
!= ((pckbd_state_t *)buf)->kbdc)
return ENOMEM;
bcopy(buf, kbd->kb_data, sizeof(pckbd_state_t));
return 0;
}
/* local functions */
static int
probe_keyboard(KBDC kbdc, int flags)
{
return 0;
}
static int
init_keyboard(KBDC kbdc, int *type, int flags)
{
*type = KB_OTHER;
return 0;
}
/* keyboard I/O routines */
/* retry count */
#ifndef KBD_MAXRETRY
#define KBD_MAXRETRY 3
#endif
/* timing parameters */
#ifndef KBD_RESETDELAY
#define KBD_RESETDELAY 200 /* wait 200msec after kbd/mouse reset */
#endif
#ifndef KBD_MAXWAIT
#define KBD_MAXWAIT 5 /* wait 5 times at most after reset */
#endif
/* I/O recovery time */
#define KBDC_DELAYTIME 37
#define KBDD_DELAYTIME 37
/* I/O ports */
#define KBD_STATUS_PORT 2 /* status port, read */
#define KBD_DATA_PORT 0 /* data port, read */
/* status bits (KBD_STATUS_PORT) */
#define KBDS_BUFFER_FULL 0x0002
/* macros */
#define kbdcp(p) ((struct kbdc_softc *)(p))
/* local variables */
static struct kbdc_softc kbdc_softc[NPCKBD] = { { 0 }, };
/* associate a port number with a KBDC */
static KBDC
kbdc_open(int port)
{
if (port <= 0)
port = IO_KBD;
if (NPCKBD) {
/* PC-98 has only one keyboard I/F */
kbdc_softc[0].port = port;
kbdc_softc[0].lock = FALSE;
return (KBDC)&kbdc_softc[0];
}
return NULL; /* You didn't include sc driver in your config file */
}
/* set/reset polling lock */
static int
kbdc_lock(KBDC p, int lock)
{
int prevlock;
prevlock = kbdcp(p)->lock;
kbdcp(p)->lock = lock;
return (prevlock != lock);
}
/* check if any data is waiting to be processed */
static int
kbdc_data_ready(KBDC p)
{
return (inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL);
}
/* wait for data from the keyboard */
static int
wait_for_kbd_data(struct kbdc_softc *kbdc)
{
/* CPU will stay inside the loop for 200msec at most */
int retry = 10000;
int port = kbdc->port;
while (!(inb(port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL)) {
DELAY(KBDD_DELAYTIME);
DELAY(KBDC_DELAYTIME);
if (--retry < 0)
return 0;
}
DELAY(KBDD_DELAYTIME);
return 1;
}
/* read one byte from the keyboard */
static int
read_kbd_data(KBDC p)
{
if (!wait_for_kbd_data(kbdcp(p)))
return -1; /* timeout */
DELAY(KBDC_DELAYTIME);
return inb(kbdcp(p)->port + KBD_DATA_PORT);
}
/* read one byte from the keyboard, but return immediately if
* no data is waiting
*/
static int
read_kbd_data_no_wait(KBDC p)
{
if (inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL) {
DELAY(KBDD_DELAYTIME);
return inb(kbdcp(p)->port + KBD_DATA_PORT);
}
return -1; /* no data */
}
#endif /* NPCKBD > 0 */

View File

@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: scvidctl.c,v 1.5 1998/10/01 11:39:18 yokota Exp $
* $Id: scvidctl.c,v 1.1 1998/12/16 14:57:37 kato Exp $
*/
#include "sc.h"
@ -40,33 +40,53 @@
#include <machine/apm_bios.h>
#include <machine/console.h>
#include <i386/isa/videoio.h>
#include <i386/isa/syscons.h>
#include <dev/fb/fbreg.h>
/* video ioctl */
#include <pc98/pc98/syscons.h>
/* for compatibility with previous versions */
typedef struct old_video_adapter {
int va_index;
int va_type;
int va_flags;
#define V_ADP_COLOR (1<<0)
#define V_ADP_MODECHANGE (1<<1)
#define V_ADP_STATESAVE (1<<2)
#define V_ADP_STATELOAD (1<<3)
#define V_ADP_FONT (1<<4)
#define V_ADP_PALETTE (1<<5)
#define V_ADP_BORDER (1<<6)
#define V_ADP_VESA (1<<7)
int va_crtc_addr;
u_int va_window; /* virtual address */
size_t va_window_size;
size_t va_window_gran;
u_int va_buffer; /* virtual address */
size_t va_buffer_size;
int va_initial_mode;
int va_initial_bios_mode;
int va_mode;
} old_video_adapter_t;
#define OLD_CONS_ADPINFO _IOWR('c', 101, old_video_adapter_t)
/* variables */
extern scr_stat *cur_console;
extern int fonts_loaded;
extern int sc_history_size;
extern u_char palette[];
#ifdef PC98
extern char crtc_type;
#endif /* PC98 */
#ifndef PC98
int
sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
int fontsize)
{
video_adapter_t *adp;
video_info_t info;
int error;
int s;
int i;
if ((*biosvidsw.get_info)(scp->adp, mode, &info))
if ((*vidsw[scp->ad]->get_info)(scp->adp, mode, &info))
return ENODEV;
adp = get_adapter(scp);
/* adjust argument values */
if (fontsize <= 0)
@ -112,12 +132,14 @@ sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
scp->font_size = fontsize;
scp->xsize = xsize;
scp->ysize = ysize;
scp->xoff = 0;
scp->yoff = 0;
scp->xpixel = scp->xsize*8;
scp->ypixel = scp->ysize*fontsize;
/* allocate buffers */
sc_alloc_scr_buffer(scp, TRUE, TRUE);
if (ISMOUSEAVAIL(adp->va_flags))
if (ISMOUSEAVAIL(scp->adp->va_flags))
sc_alloc_cut_buffer(scp, FALSE);
sc_alloc_history_buffer(scp, sc_history_size, i, FALSE);
splx(s);
@ -137,20 +159,16 @@ sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
return 0;
}
#endif /* PC98 */
#ifndef PC98
int
sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode)
{
video_adapter_t *adp;
video_info_t info;
int error;
int s;
if ((*biosvidsw.get_info)(scp->adp, mode, &info))
if ((*vidsw[scp->ad]->get_info)(scp->adp, mode, &info))
return ENODEV;
adp = get_adapter(scp);
/* stop screen saver, etc */
s = spltty();
@ -163,6 +181,8 @@ sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode)
scp->status |= (UNKNOWN_MODE | GRAPHICS_MODE);
scp->status &= ~PIXEL_MODE;
scp->mode = mode;
scp->xoff = 0;
scp->yoff = 0;
scp->xpixel = info.vi_width;
scp->ypixel = info.vi_height;
scp->xsize = info.vi_width/8;
@ -188,22 +208,18 @@ sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode)
return 0;
}
#endif /* PC98 */
#ifndef PC98
int
sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
int fontsize)
{
video_adapter_t *adp;
video_info_t info;
int error;
int s;
int i;
if ((*biosvidsw.get_info)(scp->adp, scp->mode, &info))
if ((*vidsw[scp->ad]->get_info)(scp->adp, scp->mode, &info))
return ENODEV; /* this shouldn't happen */
adp = get_adapter(scp);
#ifdef SC_VIDEO_DEBUG
if (scp->scr_buf != NULL) {
@ -238,7 +254,7 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
printf("set_pixel_mode(): mode:%x, col:%d, row:%d, font:%d\n",
scp->mode, xsize, ysize, fontsize);
printf("set_pixel_mode(): window:%x, %dx%d, xoff:%d, yoff:%d\n",
adp->va_window, info.vi_width, info.vi_height,
scp->adp->va_window, info.vi_width, info.vi_height,
(info.vi_width/8 - xsize)/2,
(info.vi_height/fontsize - ysize)/2);
}
@ -282,7 +298,7 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
/* allocate buffers */
sc_alloc_scr_buffer(scp, TRUE, TRUE);
if (ISMOUSEAVAIL(adp->va_flags))
if (ISMOUSEAVAIL(scp->adp->va_flags))
sc_alloc_cut_buffer(scp, FALSE);
sc_alloc_history_buffer(scp, sc_history_size, i, FALSE);
splx(s);
@ -307,15 +323,11 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
return 0;
}
#endif /* PC98 */
int
sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
{
scr_stat *scp;
#ifndef PC98
video_adapter_t *adp;
#endif
int error;
int s;
@ -324,47 +336,85 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
switch (cmd) {
case CONS_CURRENT: /* get current adapter type */
#ifdef PC98
*(int *)data = crtc_type;
#else /* PC98 */
adp = get_adapter(scp);
*(int *)data = adp->va_type;
#endif /* PC98 */
if (scp->adp == NULL)
return ENODEV;
*(int *)data = scp->adp->va_type;
return 0;
#ifndef PC98
case CONS_CURRENTADP: /* get current adapter index */
*(int *)data = scp->adp;
*(int *)data = scp->ad;
return 0;
case OLD_CONS_ADPINFO: /* adapter information */
if (scp->adp == NULL)
return ENODEV;
((old_video_adapter_t *)data)->va_index = scp->adp->va_index;
((old_video_adapter_t *)data)->va_type = scp->adp->va_type;
((old_video_adapter_t *)data)->va_flags = scp->adp->va_flags;
((old_video_adapter_t *)data)->va_crtc_addr = scp->adp->va_crtc_addr;
((old_video_adapter_t *)data)->va_window = scp->adp->va_window;
((old_video_adapter_t *)data)->va_window_size
= scp->adp->va_window_size;
((old_video_adapter_t *)data)->va_window_gran
= scp->adp->va_window_gran;
((old_video_adapter_t *)data)->va_buffer = scp->adp->va_buffer;
((old_video_adapter_t *)data)->va_buffer_size
= scp->adp->va_buffer_size;
((old_video_adapter_t *)data)->va_mode = scp->adp->va_mode;
((old_video_adapter_t *)data)->va_initial_mode
= scp->adp->va_initial_mode;
((old_video_adapter_t *)data)->va_initial_bios_mode
= scp->adp->va_initial_bios_mode;
return 0;
case CONS_ADPINFO: /* adapter information */
adp = (*biosvidsw.adapter)(((video_adapter_t *)data)->va_index);
if (adp == NULL)
if (scp->adp == NULL)
return ENODEV;
bcopy(adp, data, sizeof(*adp));
((video_adapter_info_t *)data)->va_index = scp->adp->va_index;
((video_adapter_info_t *)data)->va_type = scp->adp->va_type;
bcopy(scp->adp->va_name, ((video_adapter_info_t *)data)->va_name,
imin(strlen(scp->adp->va_name) + 1,
sizeof(((video_adapter_info_t *)data)->va_name)));
((video_adapter_info_t *)data)->va_unit = scp->adp->va_unit;
((video_adapter_info_t *)data)->va_flags = scp->adp->va_flags;
((video_adapter_info_t *)data)->va_io_base = scp->adp->va_io_base;
((video_adapter_info_t *)data)->va_io_size = scp->adp->va_io_size;
((video_adapter_info_t *)data)->va_crtc_addr = scp->adp->va_crtc_addr;
((video_adapter_info_t *)data)->va_mem_base = scp->adp->va_mem_base;
((video_adapter_info_t *)data)->va_mem_size = scp->adp->va_mem_size;
((video_adapter_info_t *)data)->va_window = scp->adp->va_window;
((video_adapter_info_t *)data)->va_window_size
= scp->adp->va_window_size;
((video_adapter_info_t *)data)->va_window_gran
= scp->adp->va_window_gran;
((video_adapter_info_t *)data)->va_buffer = scp->adp->va_buffer;
((video_adapter_info_t *)data)->va_buffer_size
= scp->adp->va_buffer_size;
((video_adapter_info_t *)data)->va_mode = scp->adp->va_mode;
((video_adapter_info_t *)data)->va_mode_flags = scp->adp->va_mode_flags;
((video_adapter_info_t *)data)->va_initial_mode
= scp->adp->va_initial_mode;
((video_adapter_info_t *)data)->va_initial_bios_mode
= scp->adp->va_initial_bios_mode;
return 0;
#endif /* PC98 */
case CONS_GET: /* get current video mode */
*(int *)data = scp->mode;
return 0;
#ifndef PC98
case CONS_MODEINFO: /* get mode information */
return ((*biosvidsw.get_info)(scp->adp,
return ((*vidsw[scp->ad]->get_info)(scp->adp,
((video_info_t *)data)->vi_mode, (video_info_t *)data)
? ENODEV : 0);
case CONS_FINDMODE: /* find a matching video mode */
return ((*biosvidsw.query_mode)(scp->adp, (video_info_t *)data)
return ((*vidsw[scp->ad]->query_mode)(scp->adp, (video_info_t *)data)
? ENODEV : 0);
case CONS_SETWINORG:
return ((*biosvidsw.set_win_org)(scp->adp, *(u_int *)data)
return ((*vidsw[scp->ad]->set_win_org)(scp->adp, *(u_int *)data)
? ENODEV : 0);
#endif /* PC98 */
#ifndef PC98
/* generic text modes */
case SW_TEXT_80x25: case SW_TEXT_80x30:
case SW_TEXT_80x43: case SW_TEXT_80x50:
@ -383,8 +433,13 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
case SW_ENH_B80x25: case SW_ENH_C80x25:
case SW_ENH_B80x43: case SW_ENH_C80x43:
case SW_EGAMONO80x25:
adp = get_adapter(scp);
if (!(adp->va_flags & V_ADP_MODECHANGE))
#ifdef PC98
/* PC98 TEXT MODES */
case SW_PC98_80x25:
case SW_PC98_80x30:
#endif
if (!(scp->adp->va_flags & V_ADP_MODECHANGE))
return ENODEV;
return sc_set_text_mode(scp, tp, cmd & 0xff, 0, 0, 0);
@ -394,15 +449,12 @@ 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:
adp = get_adapter(scp);
if (!(adp->va_flags & V_ADP_MODECHANGE))
if (!(scp->adp->va_flags & V_ADP_MODECHANGE))
return ENODEV;
return sc_set_graphics_mode(scp, tp, cmd & 0xff);
#endif /* PC98 */
case KDSETMODE: /* set current mode of this (virtual) console */
switch (*(int *)data) {
#ifndef PC98
case KD_TEXT: /* switch to TEXT (known) mode */
/*
* If scp->mode is of graphics modes, we don't know which
@ -412,8 +464,7 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
return EINVAL;
/* restore fonts & palette ! */
#if 0
adp = get_adapter(scp);
if (ISFONTAVAIL(adp->va_flags)
if (ISFONTAVAIL(scp->adp->va_flags)
&& !(scp->status & (GRAPHICS_MODE | PIXEL_MODE)))
/*
* FONT KLUDGE
@ -427,13 +478,13 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
copy_font(scp, LOAD, 16, font_16);
}
#endif
load_palette(scp, palette);
load_palette(scp->adp, palette);
/* move hardware cursor out of the way */
(*biosvidsw.set_hw_cursor)(scp->adp, -1, -1);
(*vidsw[scp->ad]->set_hw_cursor)(scp->adp, -1, -1);
/* FALL THROUGH */
#endif
case KD_TEXT1: /* switch to TEXT (known) mode */
/*
* If scp->mode is of graphics modes, we don't know which
@ -446,20 +497,24 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
splx(s);
return error;
}
#ifndef PC98
scp->status |= UNKNOWN_MODE;
splx(s);
/* no restore fonts & palette */
#ifdef PC98
scp->status &= ~UNKNOWN_MODE;
#else
if (scp == cur_console)
#endif
set_mode(scp);
sc_clear_screen(scp);
scp->status &= ~UNKNOWN_MODE;
#else /* PC98 */
scp->status &= ~UNKNOWN_MODE;
/* no restore fonts & palette */
if (scp == cur_console)
set_mode(scp);
sc_clear_screen(scp);
splx(s);
#endif /* PC98 */
return 0;
#ifndef PC98
case KD_PIXEL: /* pixel (raster) display */
if (!(scp->status & (GRAPHICS_MODE | PIXEL_MODE)))
return EINVAL;
@ -475,12 +530,11 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
splx(s);
if (scp == cur_console) {
set_mode(scp);
load_palette(scp, palette);
load_palette(scp->adp, palette);
}
sc_clear_screen(scp);
scp->status &= ~UNKNOWN_MODE;
return 0;
#endif /* PC98 */
case KD_GRAPHICS: /* switch to GRAPHICS (unknown) mode */
s = spltty();
@ -489,10 +543,11 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
return error;
}
scp->status |= UNKNOWN_MODE;
#ifdef PC98
set_mode(scp);
#endif
splx(s);
#ifdef PC98
if (scp == cur_console)
set_mode(scp);
#endif
return 0;
default:
@ -500,13 +555,11 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
}
/* NOT REACHED */
#ifndef PC98
case KDRASTER: /* set pixel (raster) display mode */
if (ISUNKNOWNSC(scp) || ISTEXTSC(scp))
return ENODEV;
return sc_set_pixel_mode(scp, tp, ((int *)data)[0], ((int *)data)[1],
((int *)data)[2]);
#endif /* PC98 */
case KDGETMODE: /* get current mode of this (virtual) console */
/*
@ -519,7 +572,7 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
case KDSBORDER: /* set border color of this (virtual) console */
scp->border = *data;
if (scp == cur_console)
set_border(cur_console, scp->border);
set_border(scp, scp->border);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: syscons.h,v 1.26 1998/12/16 14:57:38 kato Exp $
* $Id: syscons.h,v 1.27 1999/01/17 15:42:27 kato Exp $
*/
#ifndef _PC98_PC98_SYSCONS_H_
@ -57,10 +57,7 @@
}
/* status flags */
#define LOCK_KEY_MASK 0x0000F
#define UNKNOWN_MODE 0x00010
#define KBD_RAW_MODE 0x00020
#define KBD_CODE_MODE 0x00040
#define SWITCH_WAIT_REL 0x00080
#define SWITCH_WAIT_ACQ 0x00100
#define BUFFER_SAVED 0x00200
@ -77,9 +74,12 @@
#define VISUAL_BELL 0x00001
#define BLINK_CURSOR 0x00002
#define CHAR_CURSOR 0x00004
/* these options are now obsolete; use corresponding options for kbd driver */
#if 0
#define DETECT_KBD 0x00008
#define XT_KEYBD 0x00010
#define KBD_NORESET 0x00020
#endif
#define QUIET_BELL 0x00040
#define VESA800X600 0x00080
@ -146,7 +146,8 @@ typedef struct term_stat {
} term_stat;
typedef struct scr_stat {
int adp; /* video adapter index */
int ad; /* video adapter index */
video_adapter_t *adp; /* video adapter structure */
u_short *scr_buf; /* buffer when off screen */
#ifdef PC98
u_short *atr_buf; /* buffer when off screen */
@ -167,6 +168,7 @@ typedef struct scr_stat {
int end; /* modified area end */
term_stat term; /* terminal emulation stuff */
int status; /* status (bitfield) */
int kbd_mode; /* keyboard I/O mode */
u_short *cursor_pos; /* cursor buffer position */
u_short *cursor_oldpos; /* cursor old buffer position */
#ifndef PC98
@ -190,7 +192,6 @@ typedef struct scr_stat {
u_short bell_duration;
u_short bell_pitch;
u_char border; /* border color */
int initial_mode; /* initial mode */
int mode; /* mode */
pid_t pid; /* pid of controlling proc */
struct proc *proc; /* proc* of controlling proc */
@ -207,10 +208,8 @@ typedef struct scr_stat {
#endif
int history_size; /* size of history buffer */
struct apmhook r_hook; /* reconfiguration support */
#ifdef SC_SPLASH_SCREEN
int splash_save_mode; /* saved mode for splash screen */
int splash_save_status; /* saved status for splash screen */
#endif
#ifdef KANJI
u_char kanji_1st_char;
#define KTYPE_ASCII 0
@ -266,13 +265,12 @@ scr_stat *sc_get_scr_stat(dev_t dev);
void copy_font(scr_stat *scp, int operation, int font_size, u_char *font_image);
void set_border(scr_stat *scp, int color);
#define save_palette(scp, pal) (*biosvidsw.save_palette)((scp)->adp, pal)
#define load_palette(scp, pal) (*biosvidsw.load_palette)((scp)->adp, pal)
#define get_adapter(scp) (*biosvidsw.adapter)((scp)->adp)
int add_scrn_saver(void (*this)(int));
int remove_scrn_saver(void (*this)(int));
#define save_palette(adp, pal) \
(*vidsw[(adp)->va_index]->save_palette)((adp), (pal))
#define load_palette(adp, pal) \
(*vidsw[(adp)->va_index]->load_palette)((adp), (pal))
void sc_touch_scrn_saver(void);
void sc_clear_screen(scr_stat *scp);
void sc_move_mouse(scr_stat *scp, int x, int y);
int sc_clean_up(scr_stat *scp);
@ -290,13 +288,6 @@ int sc_set_pixel_mode(scr_stat *scp, struct tty *tp,
int sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag,
struct proc *p);
#ifdef SC_SPLASH_SCREEN
/* splash.c */
void scsplash(int);
int scsplash_load(scr_stat *scp);
int scsplash_unload(scr_stat *scp);
#endif
#ifdef PC98
unsigned int at2pc98(unsigned int attr);
#endif