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:
parent
0fe90303e0
commit
1835ec2219
@ -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
|
||||
|
@ -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
859
sys/pc98/cbus/gdc.c
Normal 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
983
sys/pc98/cbus/pckbd.c
Normal 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 */
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
859
sys/pc98/pc98/pc98gdc.c
Normal 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
983
sys/pc98/pc98/pc98kbd.c
Normal 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 */
|
@ -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
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user