From 05d57904bd1626f67fe68c0962fa812d4b15b7c6 Mon Sep 17 00:00:00 2001 From: kato Date: Mon, 18 Jan 1999 08:38:08 +0000 Subject: [PATCH] Switched to new syscons driver. Submitted by: NOKUBI Hirotaka and Kazutaka YOKOTA --- sys/conf/files.pc98 | 12 +- sys/conf/options.pc98 | 18 +- sys/pc98/cbus/gdc.c | 859 ++++++++++++++ sys/pc98/cbus/pckbd.c | 983 ++++++++++++++++ sys/pc98/conf/GENERIC | 14 +- sys/pc98/conf/GENERIC98 | 14 +- sys/pc98/conf/files.pc98 | 12 +- sys/pc98/conf/options.pc98 | 18 +- sys/pc98/pc98/pc98gdc.c | 859 ++++++++++++++ sys/pc98/pc98/pc98kbd.c | 983 ++++++++++++++++ sys/pc98/pc98/scvidctl.c | 193 ++-- sys/pc98/pc98/syscons.c | 2167 ++++++++++++------------------------ sys/pc98/pc98/syscons.h | 33 +- 13 files changed, 4618 insertions(+), 1547 deletions(-) create mode 100644 sys/pc98/cbus/gdc.c create mode 100644 sys/pc98/cbus/pckbd.c create mode 100644 sys/pc98/pc98/pc98gdc.c create mode 100644 sys/pc98/pc98/pc98kbd.c diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98 index e5cc7f5d726a..bc9bfa758fec 100644 --- a/sys/conf/files.pc98 +++ b/sys/conf/files.pc98 @@ -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 diff --git a/sys/conf/options.pc98 b/sys/conf/options.pc98 index 7f8e5e24e8f5..22c264c07e3a 100644 --- a/sys/conf/options.pc98 +++ b/sys/conf/options.pc98 @@ -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 diff --git a/sys/pc98/cbus/gdc.c b/sys/pc98/cbus/gdc.c new file mode 100644 index 000000000000..006072b26c20 --- /dev/null +++ b/sys/pc98/cbus/gdc.c @@ -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 +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include + +#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 + +#include + +#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 */ diff --git a/sys/pc98/cbus/pckbd.c b/sys/pc98/cbus/pckbd.c new file mode 100644 index 000000000000..8b1a13cc29d9 --- /dev/null +++ b/sys/pc98/cbus/pckbd.c @@ -0,0 +1,983 @@ +/*- + * $Id$ + */ + +#include "pckbd.h" +#include "opt_kbd.h" +#include "opt_devfs.h" + +#if NPCKBD > 0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#ifdef __i386__ +#include +#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 +#include +#include + +#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 + +/* 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 */ diff --git a/sys/pc98/conf/GENERIC b/sys/pc98/conf/GENERIC index e8d354fe7811..87d05b6cdad8 100644 --- a/sys/pc98/conf/GENERIC +++ b/sys/pc98/conf/GENERIC @@ -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 diff --git a/sys/pc98/conf/GENERIC98 b/sys/pc98/conf/GENERIC98 index e8d354fe7811..87d05b6cdad8 100644 --- a/sys/pc98/conf/GENERIC98 +++ b/sys/pc98/conf/GENERIC98 @@ -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 diff --git a/sys/pc98/conf/files.pc98 b/sys/pc98/conf/files.pc98 index e5cc7f5d726a..bc9bfa758fec 100644 --- a/sys/pc98/conf/files.pc98 +++ b/sys/pc98/conf/files.pc98 @@ -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 diff --git a/sys/pc98/conf/options.pc98 b/sys/pc98/conf/options.pc98 index 7f8e5e24e8f5..22c264c07e3a 100644 --- a/sys/pc98/conf/options.pc98 +++ b/sys/pc98/conf/options.pc98 @@ -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 diff --git a/sys/pc98/pc98/pc98gdc.c b/sys/pc98/pc98/pc98gdc.c new file mode 100644 index 000000000000..006072b26c20 --- /dev/null +++ b/sys/pc98/pc98/pc98gdc.c @@ -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 +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include + +#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 + +#include + +#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 */ diff --git a/sys/pc98/pc98/pc98kbd.c b/sys/pc98/pc98/pc98kbd.c new file mode 100644 index 000000000000..8b1a13cc29d9 --- /dev/null +++ b/sys/pc98/pc98/pc98kbd.c @@ -0,0 +1,983 @@ +/*- + * $Id$ + */ + +#include "pckbd.h" +#include "opt_kbd.h" +#include "opt_devfs.h" + +#if NPCKBD > 0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#ifdef __i386__ +#include +#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 +#include +#include + +#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 + +/* 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 */ diff --git a/sys/pc98/pc98/scvidctl.c b/sys/pc98/pc98/scvidctl.c index 2a5cecc75916..77eba9811ce8 100644 --- a/sys/pc98/pc98/scvidctl.c +++ b/sys/pc98/pc98/scvidctl.c @@ -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 #include -#include -#include +#include -/* video ioctl */ +#include +/* 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; } diff --git a/sys/pc98/pc98/syscons.c b/sys/pc98/pc98/syscons.c index 67742dd208df..c0054c0811d3 100644 --- a/sys/pc98/pc98/syscons.c +++ b/sys/pc98/pc98/syscons.c @@ -25,10 +25,11 @@ * (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.c,v 1.105 1999/01/08 16:09:23 kato Exp $ + * $Id: syscons.c,v 1.106 1999/01/17 15:42:27 kato Exp $ */ #include "sc.h" +#include "splash.h" #include "apm.h" #include "opt_ddb.h" #include "opt_devfs.h" @@ -67,30 +68,25 @@ #include #include +#include +#include +#include + #ifdef PC98 #define KANJI #include #include #include #include -#include -#include -#include #include #else +#include +#include #include #include #include -#include -#include -#include -#include #endif /* PC98 */ -#if defined(PC98) && defined(LINE30) -#include -#endif - #if !defined(MAXCONS) #define MAXCONS 16 #endif @@ -135,10 +131,6 @@ typedef struct old_mouse_info { } u; } old_mouse_info_t; -/* XXX use sc_bcopy where video memory is concerned */ -extern void generic_bcopy(const void *, void *, size_t); -extern void generic_bzero(void *, size_t); - static default_attr user_default = { (FG_LIGHTGREY | BG_BLACK) << 8, (FG_BLACK | BG_LIGHTGREY) << 8 @@ -168,8 +160,6 @@ static scr_stat *new_scp, *old_scp; static term_stat kernel_console; static default_attr *current_default; static int sc_flags; -static int sc_port = IO_KBD; -static KBDC sc_kbdc = NULL; static char init_done = COLD; static u_short sc_buffer[ROW*COL]; static char shutdown_in_progress = FALSE; @@ -178,33 +168,19 @@ static char switch_in_progress = FALSE; static char write_in_progress = FALSE; static char blink_in_progress = FALSE; static int blinkrate = 0; -#ifndef PC98 - u_int crtc_addr = MONO_BASE; -#endif - char crtc_type = KD_MONO; -static char crtc_vga = FALSE; -static int adp_flags; -static u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0; -static u_char accents = 0; -#ifdef PC98 -static u_char nlkcnt = 0, slkcnt = 0, alkcnt = 0; -#else -static u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0; -#endif -static const u_int n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab); +static int adapter = -1; +static int keyboard = -1; +static keyboard_t *kbd; static int delayed_next_scr = FALSE; static long scrn_blank_time = 0; /* screen saver timeout value */ - int scrn_blanked = 0; /* screen saver active flag */ +static int scrn_blanked = FALSE; /* screen saver active flag */ static long scrn_time_stamp; static int saver_mode = CONS_LKM_SAVER; /* LKM/user saver */ static int run_scrn_saver = FALSE; /* should run the saver? */ static int scrn_idle = FALSE; /* about to run the saver */ u_char scr_map[256]; u_char scr_rmap[256]; -#ifndef PC98 static int initial_video_mode; /* initial video mode # */ -static int bios_video_mode; /* video mode # set by BIOS */ -#endif int fonts_loaded = 0 #ifdef STD8X16FONT | FONT_16 @@ -243,7 +219,6 @@ static int extra_history_size = static void none_saver(int blank) { } static void (*current_saver)(int blank) = none_saver; -static void (*default_saver)(int blank) = none_saver; d_ioctl_t *sc_user_ioctl; static int sticky_splash = FALSE; @@ -264,7 +239,7 @@ static struct tty sccons[MAXCONS+2]; #define SC_CONSOLE 255 u_short *Crtat; #ifdef PC98 -u_short *Atrat; +u_short *Atrat; static u_char default_kanji = UJIS; #endif static const int nsccons = MAXCONS+2; @@ -279,20 +254,40 @@ static const int nsccons = MAXCONS+2; #endif #define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) +/* some useful macros */ +#define kbd_read_char(kbd, wait) \ + (*kbdsw[(kbd)->kb_index]->read_char)((kbd), (wait)) +#define kbd_check_char(kbd) \ + (*kbdsw[(kbd)->kb_index]->check_char)((kbd)) +#define kbd_enable(kbd) \ + (*kbdsw[(kbd)->kb_index]->enable)((kbd)) +#define kbd_disable(kbd) \ + (*kbdsw[(kbd)->kb_index]->disable)((kbd)) +#define kbd_lock(kbd, lockf) \ + (*kbdsw[(kbd)->kb_index]->lock)((kbd), (lockf)) +#define kbd_ioctl(kbd, cmd, arg) \ + (((kbd) == NULL) ? \ + ENODEV : (*kbdsw[(kbd)->kb_index]->ioctl)((kbd), (cmd), (arg))) +#define kbd_clear_state(kbd) \ + (*kbdsw[(kbd)->kb_index]->clear_state)((kbd)) +#define kbd_get_fkeystr(kbd, fkey, len) \ + (*kbdsw[(kbd)->kb_index]->get_fkeystr)((kbd), (fkey), (len)) + /* prototypes */ static int scattach(struct isa_device *dev); -static ointhand2_t scintr; +static kbd_callback_func_t sckbdevent; static int scparam(struct tty *tp, struct termios *t); static int scprobe(struct isa_device *dev); -static int scvidprobe(int unit, int flags); -static int sckbdprobe(int unit, int flags); +static int scvidprobe(int unit, int flags, int cons); +static int sckbdprobe(int unit, int flags, int cons); static void scstart(struct tty *tp); static void scmousestart(struct tty *tp); static void scinit(void); static void scshutdown(int howto, void *arg); -static u_int scgetc(u_int flags); +static u_int scgetc(keyboard_t *kbd, u_int flags); #define SCGETC_CN 1 #define SCGETC_NONBLOCK 2 +static int sccngetch(int flags); static void sccnupdate(scr_stat *scp); static scr_stat *alloc_scp(void); static void init_scp(scr_stat *scp); @@ -300,9 +295,19 @@ static void sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark); static int get_scr_num(void); static timeout_t scrn_timer; static void scrn_update(scr_stat *scp, int show_cursor); -static void scrn_saver(void (*saver)(int), int blank); +#if NSPLASH > 0 +static int scsplash_callback(int); +static void scsplash_saver(int show); +static int add_scrn_saver(void (*this_saver)(int)); +static int remove_scrn_saver(void (*this_saver)(int)); +static int set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border); +static int restore_scrn_saver_mode(scr_stat *scp); static void stop_scrn_saver(void (*saver)(int)); static int wait_scrn_saver_stop(void); +#define scsplash_stick(stick) (sticky_splash = (stick)) +#else +#define scsplash_stick(stick) +#endif /* NSPLASH */ static int switch_scr(scr_stat *scp, u_int next_scr); static void exchange_scr(void); static void scan_esc(scr_stat *scp, u_char c); @@ -310,15 +315,13 @@ static void ansi_put(scr_stat *scp, u_char *buf, int len); static void draw_cursor_image(scr_stat *scp); static void remove_cursor_image(scr_stat *scp); static void move_crsr(scr_stat *scp, int x, int y); -static u_char *get_fstr(u_int c, u_int *len); static void history_to_screen(scr_stat *scp); static int history_up_line(scr_stat *scp); static int history_down_line(scr_stat *scp); static int mask2attr(struct term_stat *term); -#ifndef PC98 -static void set_keyboard(int command, int data); -#endif -static void update_leds(int which); +static int save_kbd_state(scr_stat *scp); +static int update_kbd_state(int state, int mask); +static int update_kbd_leds(int which); static void set_destructive_cursor(scr_stat *scp); static void set_mouse_pos(scr_stat *scp); static int skip_spc_right(scr_stat *scp, u_short *p); @@ -336,14 +339,6 @@ static void draw_cutmarking(scr_stat *scp); static void remove_cutmarking(scr_stat *scp); static void do_bell(scr_stat *scp, int pitch, int duration); static timeout_t blink_screen; -#ifdef SC_SPLASH_SCREEN -static void scsplash_init(scr_stat *scp); -static void scsplash_term(scr_stat *scp); -static void scsplash_saver(int show); -#define scsplash_stick(stick) (sticky_splash = (stick)) -#else -#define scsplash_stick(stick) -#endif static cn_probe_t sccnprobe; static cn_init_t sccninit; @@ -413,26 +408,20 @@ at2pc98(unsigned int attr) static void draw_cursor_image(scr_stat *scp) { -#ifndef PC98 +#ifdef PC98 + (*vidsw[scp->ad]->set_hw_cursor)(scp->adp, scp->xpos, scp->ypos); +#else u_short cursor_image; u_short *ptr; u_short prev_image; -#endif -#ifdef PC98 - int pos = scp->cursor_pos - scp->scr_buf; - while((inb(TEXT_GDC + 0) & 0x04) == 0) {} - outb(TEXT_GDC + 2, 0x49); /* CSRW */ - outb(TEXT_GDC + 0, pos & 0xff); /* EADl */ - outb(TEXT_GDC + 0, pos >> 8); /* EADh */ -#else if (ISPIXELSC(scp)) { sc_bcopy(scp, scp->scr_buf, scp->cursor_pos - scp->scr_buf, scp->cursor_pos - scp->scr_buf, 1); return; } - ptr = (u_short *)(get_adapter(scp)->va_window) + ptr = (u_short *)(scp->adp->va_window) + (scp->cursor_pos - scp->scr_buf); /* do we have a destructive cursor ? */ @@ -487,7 +476,7 @@ remove_cursor_image(scr_stat *scp) sc_bcopy(scp, scp->scr_buf, scp->cursor_oldpos - scp->scr_buf, scp->cursor_oldpos - scp->scr_buf, 0); else - *((u_short *)(get_adapter(scp)->va_window) + *((u_short *)(scp->adp->va_window) + (scp->cursor_oldpos - scp->scr_buf)) = scp->cursor_saveunder; #endif @@ -515,242 +504,72 @@ move_crsr(scr_stat *scp, int x, int y) static int scprobe(struct isa_device *dev) { - if (!scvidprobe(dev->id_unit, dev->id_flags)) { + if (!scvidprobe(dev->id_unit, dev->id_flags, FALSE)) { if (bootverbose) printf("sc%d: no video adapter is found.\n", dev->id_unit); return (0); } -#ifndef PC98 -#if defined(VESA) && defined(VM86) - if (vesa_load()) - return FALSE; -#endif - - (*biosvidsw.diag)(bootverbose); -#endif /* PC98 */ - - sc_port = dev->id_iobase; - if (sckbdprobe(dev->id_unit, dev->id_flags)) - return (IO_KBDSIZE); - else - return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE); + return ((sckbdprobe(dev->id_unit, dev->id_flags, FALSE)) ? -1 : 0); } /* probe video adapters, return TRUE if found */ static int -scvidprobe(int unit, int flags) +scvidprobe(int unit, int flags, int cons) { -#ifndef PC98 video_adapter_t *adp; -#endif - /* do this test only once */ - if (init_done != COLD) - return (crtc_type != -1); + /* + * Access the video adapter driver through the back door! + * Video adapter drivers need to be configured before syscons. + * However, when syscons is being probed as the low-level console, + * they have not been initialized yet. We force them to initialize + * themselves here. XXX + */ + vid_configure(cons ? VIO_PROBE_ONLY : 0); -#ifdef PC98 - Crtat = (u_short *)TEXT_VRAM; - Atrat = (u_short *)TEXT_VRAM + ATTR_OFFSET; - crtc_type = KD_PC98; -#else - if ((*biosvidsw.init)() <= 0) - return FALSE; - if ((adp = (*biosvidsw.adapter)(V_ADP_PRIMARY)) == NULL) - return FALSE; + /* allocate a frame buffer */ + if (adapter < 0) { + adapter = vid_allocate("*", -1, (void *)&adapter); + if (adapter < 0) + return FALSE; + } + adp = vid_get_adapter(adapter); /* shouldn't fail */ - crtc_type = adp->va_type; - crtc_vga = (crtc_type == KD_VGA); - crtc_addr = adp->va_crtc_addr; Crtat = (u_short *)adp->va_window; - adp_flags = adp->va_flags; +#ifdef PC98 + Atrat = Crtat + ATTR_OFFSET; +#endif initial_video_mode = adp->va_initial_mode; - bios_video_mode = adp->va_initial_bios_mode; -#endif /* PC98 */ return TRUE; } /* probe the keyboard, return TRUE if found */ static int -sckbdprobe(int unit, int flags) +sckbdprobe(int unit, int flags, int cons) { -#ifndef PC98 - int codeset; - int c = -1; - int m; - int res, id; -#endif + /* access the keyboard driver through the backdoor! */ + kbd_configure(cons ? KB_CONF_PROBE_ONLY : 0); - sc_kbdc = kbdc_open(sc_port); -#ifndef PC98 - if (!kbdc_lock(sc_kbdc, TRUE)) { - /* driver error? */ - printf("sc%d: unable to lock the controller.\n", unit); - return ((flags & DETECT_KBD) ? FALSE : TRUE); + /* allocate a keyboard and register the keyboard event handler */ + if (keyboard < 0) { + keyboard = kbd_allocate("*", -1, (void *)&keyboard, sckbdevent, NULL); + if (keyboard < 0) + return FALSE; } + kbd = kbd_get_keyboard(keyboard); /* shouldn't fail */ - /* flush any noise in the buffer */ - empty_both_buffers(sc_kbdc, 10); - - /* save the current keyboard controller command byte */ - m = kbdc_get_device_mask(sc_kbdc) & ~KBD_KBD_CONTROL_BITS; - c = get_controller_command_byte(sc_kbdc); - if (c == -1) { - /* CONTROLLER ERROR */ - printf("sc%d: unable to get the current command byte value.\n", unit); - goto fail; - } - if (bootverbose) - printf("sc%d: the current keyboard controller command byte %04x\n", - unit, c); -#if 0 - /* override the keyboard lock switch */ - c |= KBD_OVERRIDE_KBD_LOCK; -#endif - - /* - * The keyboard may have been screwed up by the boot block. - * We may just be able to recover from error by testing the controller - * and the keyboard port. The controller command byte needs to be saved - * before this recovery operation, as some controllers seem to set - * the command byte to particular values. - */ - test_controller(sc_kbdc); - test_kbd_port(sc_kbdc); - - /* enable the keyboard port, but disable the keyboard intr. */ - if (!set_controller_command_byte(sc_kbdc, - KBD_KBD_CONTROL_BITS, - KBD_ENABLE_KBD_PORT | KBD_DISABLE_KBD_INT)) { - /* CONTROLLER ERROR - * there is very little we can do... - */ - printf("sc%d: unable to set the command byte.\n", unit); - goto fail; - } - - /* - * Check if we have an XT keyboard before we attempt to reset it. - * The procedure assumes that the keyboard and the controller have - * been set up properly by BIOS and have not been messed up - * during the boot process. - */ - codeset = -1; - if (flags & XT_KEYBD) - /* the user says there is a XT keyboard */ - codeset = 1; -#ifdef DETECT_XT_KEYBOARD - else if ((c & KBD_TRANSLATION) == 0) { - /* SET_SCANCODE_SET is not always supported; ignore error */ - if (send_kbd_command_and_data(sc_kbdc, KBDC_SET_SCANCODE_SET, 0) - == KBD_ACK) - codeset = read_kbd_data(sc_kbdc); - } - if (bootverbose) - printf("sc%d: keyboard scancode set %d\n", unit, codeset); -#endif /* DETECT_XT_KEYBOARD */ - - if (flags & KBD_NORESET) { - write_kbd_command(sc_kbdc, KBDC_ECHO); - if (read_kbd_data(sc_kbdc) != KBD_ECHO) { - empty_both_buffers(sc_kbdc, 10); - test_controller(sc_kbdc); - test_kbd_port(sc_kbdc); - if (bootverbose) - printf("sc%d: failed to get response from the keyboard.\n", - unit); - goto fail; - } - } else { - /* reset keyboard hardware */ - if (!reset_kbd(sc_kbdc)) { - /* KEYBOARD ERROR - * Keyboard reset may fail either because the keyboard doen't - * exist, or because the keyboard doesn't pass the self-test, - * or the keyboard controller on the motherboard and the keyboard - * somehow fail to shake hands. It is just possible, particularly - * in the last case, that the keyoard controller may be left - * in a hung state. test_controller() and test_kbd_port() appear - * to bring the keyboard controller back (I don't know why and - * how, though.) - */ - empty_both_buffers(sc_kbdc, 10); - test_controller(sc_kbdc); - test_kbd_port(sc_kbdc); - /* We could disable the keyboard port and interrupt... but, - * the keyboard may still exist (see above). - */ - if (bootverbose) - printf("sc%d: failed to reset the keyboard.\n", unit); - goto fail; - } - } - - /* - * Allow us to set the XT_KEYBD flag in UserConfig so that keyboards - * such as those on the IBM ThinkPad laptop computers can be used - * with the standard console driver. - */ - if (codeset == 1) { - if (send_kbd_command_and_data( - sc_kbdc, KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) { - /* XT kbd doesn't need scan code translation */ - c &= ~KBD_TRANSLATION; - } else { - /* KEYBOARD ERROR - * The XT kbd isn't usable unless the proper scan code set - * is selected. - */ - printf("sc%d: unable to set the XT keyboard mode.\n", unit); - goto fail; - } - } - /* enable the keyboard port and intr. */ - if (!set_controller_command_byte(sc_kbdc, - KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK, - (c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK)) - | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) { - /* CONTROLLER ERROR - * This is serious; we are left with the disabled keyboard intr. - */ - printf("sc%d: unable to enable the keyboard port and intr.\n", unit); - goto fail; - } - - /* Get the ID of the keyboard, if any */ - empty_kbd_buffer(sc_kbdc, 5); - res = send_kbd_command(sc_kbdc, KBDC_SEND_DEV_ID); - if (res == KBD_ACK) { - /* 10ms delay */ - DELAY(10000); - id = (read_kbd_data(sc_kbdc) << 8) | read_kbd_data(sc_kbdc); - if (bootverbose) - printf("sc%d: keyboard device ID: %04x\n", unit, id); - } - - kbdc_set_device_mask(sc_kbdc, m | KBD_KBD_CONTROL_BITS), - kbdc_lock(sc_kbdc, FALSE); -#endif /* !PC98 */ return TRUE; -#ifndef PC98 -fail: - if (c != -1) - /* try to restore the command byte as before, if possible */ - set_controller_command_byte(sc_kbdc, 0xff, c); - kbdc_set_device_mask(sc_kbdc, - (flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS); - kbdc_lock(sc_kbdc, FALSE); - return FALSE; -#endif /* !PC98 */ } #if NAPM > 0 static int scresume(void *dummy) { - shfts = ctls = alts = agrs = metas = accents = 0; - return 0; + if (kbd != NULL) + kbd_clear_state(kbd); + return 0; } #endif @@ -758,7 +577,7 @@ static int scattach(struct isa_device *dev) { scr_stat *scp; -#ifndef PC98 +#if defined(VESA) && defined(VM86) video_info_t info; #endif dev_t cdev = makedev(CDEV_MAJOR, 0); @@ -766,13 +585,11 @@ scattach(struct isa_device *dev) int vc; #endif - dev->id_ointr = scintr; scinit(); - sc_flags = dev->id_flags; - if (!ISFONTAVAIL(adp_flags)) - sc_flags &= ~CHAR_CURSOR; - scp = console[0]; + sc_flags = dev->id_flags; + if (!ISFONTAVAIL(scp->adp->va_flags)) + sc_flags &= ~CHAR_CURSOR; /* copy temporary buffer to final buffer */ scp->scr_buf = NULL; @@ -786,28 +603,27 @@ scattach(struct isa_device *dev) #endif /* cut buffer is available only when the mouse pointer is used */ - if (ISMOUSEAVAIL(adp_flags)) + if (ISMOUSEAVAIL(scp->adp->va_flags)) sc_alloc_cut_buffer(scp, FALSE); /* initialize history buffer & pointers */ sc_alloc_history_buffer(scp, sc_history_size, 0, FALSE); -#ifndef PC98 #if defined(VESA) && defined(VM86) if ((sc_flags & VESA800X600) - && ((*biosvidsw.get_info)(scp->adp, M_VESA_800x600, &info) == 0)) { -#ifdef SC_SPLASH_SCREEN - scsplash_term(scp); + && ((*vidsw[scp->ad]->get_info)(scp->adp, M_VESA_800x600, &info) == 0)) { +#if NSPLASH > 0 + splash_term(scp->adp); #endif sc_set_graphics_mode(scp, NULL, M_VESA_800x600); sc_set_pixel_mode(scp, NULL, COL, ROW, 16); initial_video_mode = M_VESA_800x600; -#ifdef SC_SPLASH_SCREEN - scsplash_init(scp); +#if NSPLASH > 0 + /* put up the splash again! */ + splash_init(scp->adp, scsplash_callback); #endif } #endif /* VESA && VM86 */ -#endif /* PC98 */ /* initialize cursor stuff */ if (!ISGRAPHSC(scp)) @@ -816,20 +632,30 @@ scattach(struct isa_device *dev) /* get screen update going */ scrn_timer((void *)TRUE); - update_leds(scp->status); + /* set up the keyboard */ + kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); + update_kbd_state(scp->status, LOCK_MASK); + if (bootverbose) { + printf("sc%d:", dev->id_unit); + if (adapter >= 0) + printf(" fb%d", adapter); + if (keyboard >= 0) + printf(" kbd%d", keyboard); + printf("\n"); + } printf("sc%d: ", dev->id_unit); - switch(crtc_type) { + switch(scp->adp->va_type) { #ifdef PC98 case KD_PC98: printf(" "); break; #else case KD_VGA: - printf("VGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono"); + printf("VGA %s", (scp->adp->va_flags & V_ADP_COLOR) ? "color" : "mono"); break; case KD_EGA: - printf("EGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono"); + printf("EGA %s", (scp->adp->va_flags & V_ADP_COLOR) ? "color" : "mono"); break; case KD_CGA: printf("CGA"); @@ -887,6 +713,7 @@ int scopen(dev_t dev, int flag, int mode, struct proc *p) { struct tty *tp = scdevtotty(dev); + keyarg_t key; if (!tp) return(ENXIO); @@ -898,7 +725,9 @@ scopen(dev_t dev, int flag, int mode, struct proc *p) ttychars(tp); /* Use the current setting of the <-- key as default VERASE. */ /* If the Delete key is preferable, an stty is necessary */ - tp->t_cc[VERASE] = key_map.key[0x0e].map[0]; + key.keynum = 0x0e; /* how do we know this magic number... XXX */ + kbd_ioctl(kbd, GIO_KEYMAPENT, (caddr_t)&key); + tp->t_cc[VERASE] = key.key.map[0]; tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = TTYDEF_CFLAG; @@ -914,10 +743,8 @@ scopen(dev_t dev, int flag, int mode, struct proc *p) return(EBUSY); if (minor(dev) < MAXCONS && !console[minor(dev)]) { console[minor(dev)] = alloc_scp(); -#ifndef PC98 if (ISGRAPHSC(console[minor(dev)])) sc_set_pixel_mode(console[minor(dev)], NULL, COL, ROW, 16); -#endif /* PC98 */ } if (minor(dev)t_winsize.ws_col && !tp->t_winsize.ws_row) { tp->t_winsize.ws_col = console[minor(dev)]->xsize; @@ -994,38 +821,53 @@ scwrite(dev_t dev, struct uio *uio, int flag) return((*linesw[tp->t_line].l_write)(tp, uio, flag)); } -static void -scintr(int unit) +static int +sckbdevent(keyboard_t *thiskbd, int event, void *arg) { static struct tty *cur_tty; - int c, len; + int c; + size_t len; u_char *cp; + /* assert(thiskbd == kbd) */ + + switch (event) { + case KBDIO_KEYINPUT: + break; + case KBDIO_UNLOADING: + kbd = NULL; + kbd_release(thiskbd, (void *)keyboard); + return 0; + default: + return EINVAL; + } + /* * Loop while there is still input to get from the keyboard. * I don't think this is nessesary, and it doesn't fix * the Xaccel-2.1 keyboard hang, but it can't hurt. XXX */ - while ((c = scgetc(SCGETC_NONBLOCK)) != NOKEY) { + while ((c = scgetc(thiskbd, SCGETC_NONBLOCK)) != NOKEY) { cur_tty = VIRTUAL_TTY(get_scr_num()); if (!(cur_tty->t_state & TS_ISOPEN)) if (!((cur_tty = CONSOLE_TTY)->t_state & TS_ISOPEN)) continue; - switch (c & 0xff00) { + switch (KEYFLAGS(c)) { case 0x0000: /* normal key */ - (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); + (*linesw[cur_tty->t_line].l_rint)(KEYCHAR(c), cur_tty); break; case FKEY: /* function key, return string */ - if (cp = get_fstr((u_int)c, (u_int *)&len)) { + cp = kbd_get_fkeystr(thiskbd, KEYCHAR(c), &len); + if (cp != NULL) { while (len-- > 0) - (*linesw[cur_tty->t_line].l_rint)(*cp++ & 0xFF, cur_tty); + (*linesw[cur_tty->t_line].l_rint)(*cp++, cur_tty); } break; case MKEY: /* meta is active, prepend ESC */ (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); - (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); + (*linesw[cur_tty->t_line].l_rint)(KEYCHAR(c), cur_tty); break; case BKEY: /* backtab fixed sequence (esc [ Z) */ (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); @@ -1035,17 +877,11 @@ scintr(int unit) } } -#if 0 - if (cur_console->status & MOUSE_ENABLED) { - cur_console->status &= ~MOUSE_VISIBLE; - remove_mouse_image(cur_console); - } -#else if (cur_console->status & MOUSE_VISIBLE) { remove_mouse_image(cur_console); cur_console->status &= ~MOUSE_VISIBLE; } -#endif + return 0; } static int @@ -1065,9 +901,6 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) int i; struct tty *tp; scr_stat *scp; -#ifndef PC98 - video_adapter_t *adp; -#endif int s; tp = scdevtotty(dev); @@ -1093,11 +926,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return 0; case GIO_COLOR: /* is this a color console ? */ -#ifdef PC98 - *(int*)data = 0; -#else - *(int *)data = (adp_flags & V_ADP_COLOR) ? 1 : 0; -#endif + *(int *)data = (scp->adp->va_flags & V_ADP_COLOR) ? 1 : 0; return 0; case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */ @@ -1115,10 +944,8 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) else sc_flags &= ~BLINK_CURSOR; if ((*(int*)data) & 0x02) { -#ifndef PC98 - if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) + if (!ISFONTAVAIL(scp->adp->va_flags)) return ENXIO; -#endif /* PC98 */ sc_flags |= CHAR_CURSOR; } else sc_flags &= ~CHAR_CURSOR; @@ -1127,10 +954,12 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) * are affected. Update the cursor in the current console... */ if (!ISGRAPHSC(cur_console)) { + s = spltty(); remove_cursor_image(cur_console); if (sc_flags & CHAR_CURSOR) set_destructive_cursor(cur_console); draw_cursor_image(cur_console); + splx(s); } return 0; @@ -1192,10 +1021,8 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) mouse_info_t buf; /* FIXME: */ -#ifndef PC98 - if (!ISMOUSEAVAIL(get_adapter(scp)->va_flags)) + if (!ISMOUSEAVAIL(scp->adp->va_flags)) return ENODEV; -#endif /* PC98 */ if (cmd == OLD_CONS_MOUSECTL) { static u_char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; @@ -1457,8 +1284,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return EINVAL; } /* make screensaver happy */ - scsplash_stick(FALSE); - run_scrn_saver = FALSE; + sc_touch_scrn_saver(); return 0; } @@ -1579,7 +1405,9 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) ptr->mv_grfc.fore = 0; /* not supported */ ptr->mv_grfc.back = 0; /* not supported */ ptr->mv_ovscan = scp->border; - ptr->mk_keylock = scp->status & LOCK_KEY_MASK; + if (scp == cur_console) + save_kbd_state(scp); + ptr->mk_keylock = scp->status & LOCK_MASK; return 0; } return EINVAL; @@ -1611,10 +1439,12 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) scsplash_stick(FALSE); saver_mode = *(int *)data; s = spltty(); +#if NSPLASH > 0 if ((error = wait_scrn_saver_stop())) { splx(s); return error; } +#endif /* NSPLASH */ scp->status |= SAVER_RUNNING; scsplash_stick(TRUE); splx(s); @@ -1643,38 +1473,6 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) splx(s); return 0; -#ifdef PC98 - case SW_PC98_80x25: - case SW_PC98_80x30: /* PC98 TEXT MODES */ - if (!crtc_vga) - return ENXIO; - scp->xsize = 80; - scp->status &= ~MOUSE_VISIBLE; - remove_cutmarking(scp); - s = spltty(); - if ((error = wait_scrn_saver_stop())) { - splx(s); - return error; - } - if (scp->history != NULL) - i = imax(scp->history_size / scp->xsize - - imax(SC_HISTORY_SIZE, scp->ysize), 0); - else - i = 0; - switch (cmd & 0xff) { - case M_PC98_80x25: - scp->ysize = 25; - break; -#ifdef LINE30 - case M_PC98_80x30: - scp->ysize = LINE30_ROW; - break; -#endif - default: - return EINVAL; - } -#endif - case VT_SETMODE: /* set screen switcher mode */ { struct vt_mode *mode; @@ -1779,43 +1577,36 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return 0; case KDSKBSTATE: /* set keyboard state (locks) */ - if (*(int *)data & ~LOCK_KEY_MASK) + if (*(int *)data & ~LOCK_MASK) return EINVAL; - scp->status &= ~LOCK_KEY_MASK; + scp->status &= ~LOCK_MASK; scp->status |= *(int *)data; if (scp == cur_console) - update_leds(scp->status); + update_kbd_state(scp->status, LOCK_MASK); return 0; case KDGKBSTATE: /* get keyboard state (locks) */ - *(int *)data = scp->status & LOCK_KEY_MASK; + if (scp == cur_console) + save_kbd_state(scp); + *(int *)data = scp->status & LOCK_MASK; return 0; case KDSETRAD: /* set keyboard repeat & delay rates */ -#ifndef PC98 if (*(int *)data & ~0x7f) return EINVAL; - if (sc_kbdc != NULL) - set_keyboard(KBDC_SET_TYPEMATIC, *(int *)data); -#endif - return 0; + error = kbd_ioctl(kbd, KDSETRAD, data); + if (error == ENOIOCTL) + error = ENODEV; + return error; case KDSKBMODE: /* set keyboard mode */ switch (*(int *)data) { - case K_RAW: /* switch to RAW scancode mode */ - scp->status &= ~KBD_CODE_MODE; - scp->status |= KBD_RAW_MODE; - return 0; - - case K_CODE: /* switch to CODE mode */ - scp->status &= ~KBD_RAW_MODE; - scp->status |= KBD_CODE_MODE; - return 0; - case K_XLATE: /* switch to XLT ascii mode */ - if (scp == cur_console && scp->status & KBD_RAW_MODE) - shfts = ctls = alts = agrs = metas = accents = 0; - scp->status &= ~(KBD_RAW_MODE | KBD_CODE_MODE); + case K_RAW: /* switch to RAW scancode mode */ + case K_CODE: /* switch to CODE mode */ + scp->kbd_mode = *(int *)data; + if (scp == cur_console) + kbd_ioctl(kbd, cmd, data); return 0; default: return EINVAL; @@ -1823,10 +1614,15 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) /* NOT REACHED */ case KDGKBMODE: /* get keyboard mode */ - *(int *)data = (scp->status & KBD_RAW_MODE) ? K_RAW : - ((scp->status & KBD_CODE_MODE) ? K_CODE : K_XLATE); + *(int *)data = scp->kbd_mode; return 0; + case KDGKBINFO: + error = kbd_ioctl(kbd, cmd, data); + if (error == ENOIOCTL) + error = ENODEV; + return error; + case KDMKTONE: /* sound the bell */ if (*(int*)data) do_bell(scp, (*(int*)data)&0xffff, @@ -1878,44 +1674,74 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return 0; case KDGKBTYPE: /* get keyboard type */ - *(int *)data = 0; /* type not known (yet) */ + error = kbd_ioctl(kbd, cmd, data); + if (error == ENOIOCTL) { + /* always return something? XXX */ + *(int *)data = 0; + } return 0; case KDSETLED: /* set keyboard LED status */ - if (*(int *)data & ~LED_MASK) + if (*(int *)data & ~LED_MASK) /* FIXME: LOCK_MASK? */ return EINVAL; scp->status &= ~LED_MASK; scp->status |= *(int *)data; if (scp == cur_console) - update_leds(scp->status); + update_kbd_leds(scp->status); return 0; case KDGETLED: /* get keyboard LED status */ + if (scp == cur_console) + save_kbd_state(scp); *(int *)data = scp->status & LED_MASK; return 0; - case GETFKEY: /* get functionkey string */ - if (*(u_short*)data < n_fkey_tab) { - fkeyarg_t *ptr = (fkeyarg_t*)data; - bcopy(&fkey_tab[ptr->keynum].str, ptr->keydef, - fkey_tab[ptr->keynum].len); - ptr->flen = fkey_tab[ptr->keynum].len; - return 0; - } - else - return EINVAL; + case CONS_SETKBD: /* set the new keyboard */ + { + keyboard_t *newkbd; - case SETFKEY: /* set functionkey string */ - if (*(u_short*)data < n_fkey_tab) { - fkeyarg_t *ptr = (fkeyarg_t*)data; - bcopy(ptr->keydef, &fkey_tab[ptr->keynum].str, - min(ptr->flen, MAXFK)); - fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK); - return 0; + s = spltty(); + newkbd = kbd_get_keyboard(*(int *)data); + if (newkbd == NULL) { + splx(s); + return EINVAL; + } + error = 0; + if (kbd != newkbd) { + i = kbd_allocate(newkbd->kb_name, newkbd->kb_unit, + (void *)&keyboard, sckbdevent, NULL); + /* i == newkbd->kb_index */ + if (i >= 0) { + if (kbd != NULL) { + save_kbd_state(cur_console); + kbd_release(kbd, (void *)&keyboard); + } + kbd = kbd_get_keyboard(i); /* kbd == newkbd */ + keyboard = i; + kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&cur_console->kbd_mode); + update_kbd_state(cur_console->status, LOCK_MASK); + } else { + error = EPERM; /* XXX */ + } + } + splx(s); + return error; } - else - return EINVAL; + case CONS_RELKBD: /* release the current keyboard */ + s = spltty(); + error = 0; + if (kbd != NULL) { + save_kbd_state(cur_console); + error = kbd_release(kbd, (void *)&keyboard); + if (error == 0) { + kbd = NULL; + keyboard = -1; + } + } + splx(s); + return error; + case GIO_SCRNMAP: /* get output translation table */ bcopy(&scr_map, data, sizeof(scr_map)); return 0; @@ -1926,36 +1752,19 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) scr_rmap[scr_map[i]] = i; return 0; - case GIO_KEYMAP: /* get keyboard translation table */ - bcopy(&key_map, data, sizeof(key_map)); - return 0; + case GIO_KEYMAP: /* get keyboard translation table */ + case PIO_KEYMAP: /* set keyboard translation table */ + case GIO_DEADKEYMAP: /* get accent key translation table */ + case PIO_DEADKEYMAP: /* set accent key translation table */ + case GETFKEY: /* get function key string */ + case SETFKEY: /* set function key string */ + error = kbd_ioctl(kbd, cmd, data); + if (error == ENOIOCTL) + error = ENODEV; + return error; - case PIO_KEYMAP: /* set keyboard translation table */ - accents = 0; - bzero(&accent_map, sizeof(accent_map)); - bcopy(data, &key_map, sizeof(key_map)); - return 0; - - case GIO_DEADKEYMAP: /* get accent key translation table */ - bcopy(&accent_map, data, sizeof(accent_map)); - return 0; - - case PIO_DEADKEYMAP: /* set accent key translation table */ - accents = 0; - bcopy(data, &accent_map, sizeof(accent_map)); - return 0; - -#ifdef PC98 case PIO_FONT8x8: /* set 8x8 dot font */ - case GIO_FONT8x8: /* get 8x8 dot font */ - case PIO_FONT8x14: /* set 8x14 dot font */ - case GIO_FONT8x14: /* get 8x14 dot font */ - case PIO_FONT8x16: /* set 8x16 dot font */ - case GIO_FONT8x16: /* get 8x16 dot font */ - return ENXIO; -#else - case PIO_FONT8x8: /* set 8x8 dot font */ - if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) + if (!ISFONTAVAIL(scp->adp->va_flags)) return ENXIO; bcopy(data, font_8, 8*256); fonts_loaded |= FONT_8; @@ -1969,7 +1778,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return 0; case GIO_FONT8x8: /* get 8x8 dot font */ - if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) + if (!ISFONTAVAIL(scp->adp->va_flags)) return ENXIO; if (fonts_loaded & FONT_8) { bcopy(font_8, data, 8*256); @@ -1979,7 +1788,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return ENXIO; case PIO_FONT8x14: /* set 8x14 dot font */ - if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) + if (!ISFONTAVAIL(scp->adp->va_flags)) return ENXIO; bcopy(data, font_14, 14*256); fonts_loaded |= FONT_14; @@ -1994,7 +1803,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return 0; case GIO_FONT8x14: /* get 8x14 dot font */ - if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) + if (!ISFONTAVAIL(scp->adp->va_flags)) return ENXIO; if (fonts_loaded & FONT_14) { bcopy(font_14, data, 14*256); @@ -2004,7 +1813,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return ENXIO; case PIO_FONT8x16: /* set 8x16 dot font */ - if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) + if (!ISFONTAVAIL(scp->adp->va_flags)) return ENXIO; bcopy(data, font_16, 16*256); fonts_loaded |= FONT_16; @@ -2018,7 +1827,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return 0; case GIO_FONT8x16: /* get 8x16 dot font */ - if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) + if (!ISFONTAVAIL(scp->adp->va_flags)) return ENXIO; if (fonts_loaded & FONT_16) { bcopy(font_16, data, 16*256); @@ -2026,7 +1835,6 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) } else return ENXIO; -#endif /* PC98 */ #ifdef PC98 case ADJUST_CLOCK: /* /dev/rtc for 98note resume */ @@ -2106,16 +1914,15 @@ sccnprobe(struct consdev *cp) return; } - if (!scvidprobe(dvp->id_unit, dvp->id_flags)) { + if (!scvidprobe(dvp->id_unit, dvp->id_flags, TRUE)) { cp->cn_pri = CN_DEAD; return; } + sckbdprobe(dvp->id_unit, dvp->id_flags, TRUE); /* initialize required fields */ cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLE); cp->cn_pri = CN_INTERNAL; - - sc_kbdc = kbdc_open(sc_port); } static void @@ -2128,9 +1935,34 @@ static void sccnputc(dev_t dev, int c) { u_char buf[1]; - int s; scr_stat *scp = console[0]; term_stat save = scp->term; + u_short *p; + int s; + int i; + + if (scp == cur_console && scp->status & SLKED) { + scp->status &= ~SLKED; + update_kbd_state(scp->status, SLKED); + if (cur_console->status & BUFFER_SAVED) { + p = cur_console->history_save; + for (i = 0; i < cur_console->ysize; ++i) { + bcopy(p, cur_console->scr_buf + (cur_console->xsize*i), + cur_console->xsize*sizeof(u_short)); + p += cur_console->xsize; + if (p + cur_console->xsize + > cur_console->history + cur_console->history_size) + p = cur_console->history; + } + cur_console->status &= ~BUFFER_SAVED; + cur_console->history_head = cur_console->history_save; + cur_console->status |= CURSOR_ENABLED; + mark_all(cur_console); + } +#if 1 /* XXX */ + scstart(VIRTUAL_TTY(get_scr_num())); +#endif + } scp->term = kernel_console; current_default = &kernel_default; @@ -2142,7 +1974,7 @@ sccnputc(dev_t dev, int c) current_default = &user_default; scp->term = save; - s = spltty(); /* block scintr and scrn_timer */ + s = spltty(); /* block sckbdevent and scrn_timer */ sccnupdate(scp); splx(s); } @@ -2150,35 +1982,63 @@ sccnputc(dev_t dev, int c) static int sccngetc(dev_t dev) { - int s = spltty(); /* block scintr and scrn_timer while we poll */ + return sccngetch(0); +} + +static int +sccncheckc(dev_t dev) +{ + return sccngetch(SCGETC_NONBLOCK); +} + +static int +sccngetch(int flags) +{ + int cur_mode; + int s = spltty(); /* block sckbdevent and scrn_timer while we poll */ int c; /* * Stop the screen saver and update the screen if necessary. * What if we have been running in the screen saver code... XXX */ - scsplash_stick(FALSE); - run_scrn_saver = FALSE; + sc_touch_scrn_saver(); sccnupdate(cur_console); - c = scgetc(SCGETC_CN); + if (kbd == NULL) { + splx(s); + return -1; + } + + /* + * Make sure the keyboard is accessible even when the kbd device + * driver is disabled. + */ + kbd_enable(kbd); + + /* we shall always use the keyboard in the XLATE mode here */ + cur_mode = cur_console->kbd_mode; + cur_console->kbd_mode = K_XLATE; + kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&cur_console->kbd_mode); + + c = scgetc(kbd, SCGETC_CN | flags); + + cur_console->kbd_mode = cur_mode; + kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&cur_console->kbd_mode); + kbd_disable(kbd); splx(s); - return(c); -} -static int -sccncheckc(dev_t dev) -{ - int s = spltty(); /* block scintr and scrn_timer while we poll */ - int c; - - scsplash_stick(FALSE); - run_scrn_saver = FALSE; - sccnupdate(cur_console); - - c = scgetc(SCGETC_CN | SCGETC_NONBLOCK); - splx(s); - return(c == NOKEY ? -1 : c); /* c == -1 can't happen */ + switch (KEYFLAGS(c)) { + case 0: /* normal char */ + return KEYCHAR(c); + case FKEY: /* function key */ + return c; /* XXX */ + case NOKEY: + case ERRKEY: + default: + return -1; + } + /* NOT REACHED */ } static void @@ -2190,18 +2050,18 @@ sccnupdate(scr_stat *scp) return; if (panicstr || shutdown_in_progress) { - scsplash_stick(FALSE); - run_scrn_saver = FALSE; + sc_touch_scrn_saver(); } else if (scp != cur_console) { return; } if (!run_scrn_saver) scrn_idle = FALSE; +#if NSPLASH > 0 if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle) if (scp->status & SAVER_RUNNING) stop_scrn_saver(current_saver); - +#endif /* NSPLASH */ if (scp != cur_console || blink_in_progress || switch_in_progress) return; @@ -2246,37 +2106,12 @@ scrn_timer(void *arg) } s = spltty(); - /* - * 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. - */ - if (kbdc_lock(sc_kbdc, TRUE)) { - /* - * We have seen the lock flag is not set. Let's reset the flag early; - * otherwise `update_led()' failes which may want the lock - * during `scintr()'. - */ - kbdc_lock(sc_kbdc, FALSE); - if (kbdc_data_ready(sc_kbdc)) - scintr(0); - } - scp = cur_console; /* should we stop the screen saver? */ getmicrouptime(&tv); - if (panicstr || shutdown_in_progress) { - scsplash_stick(FALSE); - run_scrn_saver = FALSE; - } + if (panicstr || shutdown_in_progress) + sc_touch_scrn_saver(); if (run_scrn_saver) { scrn_idle = (tv.tv_sec > scrn_time_stamp + scrn_blank_time); } else { @@ -2285,10 +2120,11 @@ scrn_timer(void *arg) if (scrn_blank_time > 0) run_scrn_saver = TRUE; } +#if NSPLASH > 0 if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle) if (scp->status & SAVER_RUNNING) stop_scrn_saver(current_saver); - +#endif /* NSPLASH */ /* should we just return ? */ if (blink_in_progress || switch_in_progress) { if (arg) @@ -2304,7 +2140,7 @@ scrn_timer(void *arg) /* should we activate the screen saver? */ if ((saver_mode == CONS_LKM_SAVER) && scrn_idle) if (!ISGRAPHSC(scp) || (scp->status & SAVER_RUNNING)) - scrn_saver(current_saver, TRUE); + (*current_saver)(TRUE); if (arg) timeout(scrn_timer, (void *)TRUE, hz / 25); @@ -2385,25 +2221,90 @@ scrn_update(scr_stat *scp, int show_cursor) scp->start = scp->xsize*scp->ysize - 1; } -int +#if NSPLASH > 0 + +static int +scsplash_callback(int event) +{ + int error; + + switch (event) { + case SPLASH_INIT: + if (add_scrn_saver(scsplash_saver) == 0) { + run_scrn_saver = TRUE; + if (cold && !(boothowto & (RB_VERBOSE | RB_CONFIG))) { + scsplash_stick(TRUE); + (*current_saver)(TRUE); + } + } + return 0; + + case SPLASH_TERM: + if (current_saver == scsplash_saver) { + scsplash_stick(FALSE); + error = remove_scrn_saver(scsplash_saver); + if (error) + return error; + } + return 0; + + default: + return EINVAL; + } +} + +static void +scsplash_saver(int show) +{ + static int busy = FALSE; + static int failed = FALSE; + scr_stat *scp; + + if (busy) + return; + busy = TRUE; + + scp = cur_console; + if (show) { + if (!failed) { + if (!scrn_blanked) + set_scrn_saver_mode(scp, -1, NULL, 0); + if (splash(scp->adp, TRUE) == 0) { + scrn_blanked = TRUE; + } else { + failed = TRUE; + scsplash_stick(FALSE); + printf("scsplash_saver(): failed to put up the image\n"); + restore_scrn_saver_mode(scp); + } + } + } else if (!sticky_splash) { + if (scrn_blanked && (splash(scp->adp, FALSE) == 0)) { + restore_scrn_saver_mode(scp); + scrn_blanked = FALSE; + } + } + busy = FALSE; +} + +static int add_scrn_saver(void (*this_saver)(int)) { -#ifdef SC_SPLASH_SCREEN - if (current_saver == scsplash) { - scsplash_stick(FALSE); - stop_scrn_saver(scsplash); - } -#endif + int error; + + if (current_saver != none_saver) { + error = remove_scrn_saver(current_saver); + if (error) + return error; + } - if (current_saver != default_saver) - return EBUSY; run_scrn_saver = FALSE; saver_mode = CONS_LKM_SAVER; current_saver = this_saver; return 0; } -int +static int remove_scrn_saver(void (*this_saver)(int)) { if (current_saver != this_saver) @@ -2416,35 +2317,77 @@ remove_scrn_saver(void (*this_saver)(int)) * before stopping the current saver, rather than blocking by `splXX()'. */ current_saver = none_saver; - if (scrn_blanked > 0) + if (scrn_blanked) stop_scrn_saver(this_saver); - if (scrn_blanked > 0) - return EBUSY; /* XXX */ - - current_saver = default_saver; - return 0; + return (scrn_blanked ? EBUSY : 0); } -static void -scrn_saver(void (*saver)(int), int blank) +static int +set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border) { - static int busy = FALSE; + int s; - if (busy) - return; - busy = TRUE; - (*saver)(blank); - busy = FALSE; + /* assert(scp == cur_console) */ + s = spltty(); + scp->splash_save_mode = scp->mode; + scp->splash_save_status = scp->status & (GRAPHICS_MODE | PIXEL_MODE); + scp->status &= ~PIXEL_MODE; + scp->status |= (UNKNOWN_MODE | SAVER_RUNNING); + splx(s); + if (mode < 0) + return 0; + scp->mode = mode; + if (set_mode(scp) == 0) { + if (scp->adp->va_mode_flags & V_INFO_GRAPHICS) + scp->status |= GRAPHICS_MODE; + if (pal != NULL) + load_palette(scp->adp, pal); + set_border(scp, border); + return 0; + } else { + s = spltty(); + scp->mode = scp->splash_save_mode; + scp->status &= ~(UNKNOWN_MODE | SAVER_RUNNING); + scp->status |= scp->splash_save_status; + splx(s); + return 1; + } +} + +static int +restore_scrn_saver_mode(scr_stat *scp) +{ + int mode; + int status; + int s; + + /* assert(scp == cur_console) */ + s = spltty(); + mode = scp->mode; + status = scp->status; + scp->mode = scp->splash_save_mode; + scp->status &= ~(UNKNOWN_MODE | GRAPHICS_MODE | SAVER_RUNNING); + scp->status |= scp->splash_save_status; + if (set_mode(scp) == 0) { + load_palette(scp->adp, palette); + splx(s); + return 0; + } else { + scp->mode = mode; + scp->status = status; + splx(s); + return 1; + } } static void stop_scrn_saver(void (*saver)(int)) { - scrn_saver(saver, FALSE); + (*saver)(FALSE); run_scrn_saver = FALSE; /* the screen saver may have chosen not to stop after all... */ - if (scrn_blanked > 0) + if (scrn_blanked) return; mark_all(cur_console); @@ -2458,7 +2401,7 @@ wait_scrn_saver_stop(void) { int error = 0; - while (scrn_blanked > 0) { + while (scrn_blanked) { run_scrn_saver = FALSE; error = tsleep((caddr_t)&scrn_blanked, PZERO | PCATCH, "scrsav", 0); run_scrn_saver = FALSE; @@ -2468,6 +2411,15 @@ wait_scrn_saver_stop(void) return error; } +#endif /* NSPLASH */ + +void +sc_touch_scrn_saver(void) +{ + scsplash_stick(FALSE); + run_scrn_saver = FALSE; +} + void sc_clear_screen(scr_stat *scp) { @@ -2490,9 +2442,8 @@ static int switch_scr(scr_stat *scp, u_int next_scr) { /* delay switch if actively updating screen */ - if (scrn_blanked > 0 || write_in_progress || blink_in_progress) { - scsplash_stick(FALSE); - run_scrn_saver = FALSE; + if (scrn_blanked || write_in_progress || blink_in_progress) { + sc_touch_scrn_saver(); delayed_next_scr = next_scr+1; return 0; } @@ -2551,7 +2502,12 @@ switch_scr(scr_stat *scp, u_int next_scr) static void exchange_scr(void) { + /* save the current state of video and keyboard */ move_crsr(old_scp, old_scp->xpos, old_scp->ypos); + if (old_scp->kbd_mode == K_XLATE) + save_kbd_state(old_scp); + + /* set up the video for the new screen */ cur_console = new_scp; #ifdef PC98 if (old_scp->mode != new_scp->mode || ISUNKNOWNSC(old_scp) || ISUNKNOWNSC(new_scp)) @@ -2564,20 +2520,17 @@ exchange_scr(void) if (ISTEXTSC(new_scp) && (sc_flags & CHAR_CURSOR)) set_destructive_cursor(new_scp); if (ISGRAPHSC(old_scp)) - load_palette(new_scp, palette); + load_palette(new_scp->adp, palette); #endif - if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE || - old_scp->status & KBD_CODE_MODE || new_scp->status & KBD_CODE_MODE) - shfts = ctls = alts = agrs = metas = accents = 0; set_border(new_scp, new_scp->border); - update_leds(new_scp->status); + + /* set up the keyboard for the new screen */ + if (old_scp->kbd_mode != new_scp->kbd_mode) + kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&new_scp->kbd_mode); + update_kbd_state(new_scp->status, LOCK_MASK); + delayed_next_scr = FALSE; mark_all(new_scp); -#ifdef PC98 - if (new_scp->mode == 0x102) { - bzero(Crtat, 800*600/8); - } -#endif } static void @@ -3272,7 +3225,7 @@ scan_esc(scr_stat *scp, u_char c) sc_flags &= ~CHAR_CURSOR; #else /* PC98 */ if ((scp->term.param[0] & 0x02) - && ISFONTAVAIL(get_adapter(scp)->va_flags)) + && ISFONTAVAIL(scp->adp->va_flags)) sc_flags |= CHAR_CURSOR; else sc_flags &= ~CHAR_CURSOR; @@ -3287,10 +3240,12 @@ scan_esc(scr_stat *scp, u_char c) * are affected. Update the cursor in the current console... */ if (!ISGRAPHSC(cur_console)) { + i = spltty(); remove_cursor_image(cur_console); if (sc_flags & CHAR_CURSOR) set_destructive_cursor(cur_console); draw_cursor_image(cur_console); + splx(i); } break; @@ -3786,12 +3741,9 @@ ansi_put(scr_stat *scp, u_char *buf, int len) static void scinit(void) { -#ifdef PC98 - u_int hw_cursor; -#else + video_adapter_t *adp; int col; int row; -#endif u_int i; if (init_done != COLD) @@ -3799,32 +3751,18 @@ scinit(void) init_done = WARM; #ifdef PC98 - if (pc98_machine_type & M_8M) { - BELL_PITCH = 1339; - } else { - BELL_PITCH = 1678; - } - outb(0x62, 0xd); - outb(0xA2, 0xd); - /* Extract cursor location */ - while((inb(TEXT_GDC + 0) & 0x04) == 0) {} /* GDC wait */ - outb(TEXT_GDC + 2, 0xe0); /* CSRR */ - while((inb(TEXT_GDC + 0) & 0x1) == 0) {} /* GDC wait */ - hw_cursor = inb(TEXT_GDC + 2); /* EADl */ - hw_cursor |= (inb(TEXT_GDC + 2) << 8); /* EADh */ - inb(TEXT_GDC + 2); /* dummy */ - inb(TEXT_GDC + 2); /* dummy */ - inb(TEXT_GDC + 2); /* dummy */ + if (pc98_machine_type & M_8M) + BELL_PITCH = 1339; + else + BELL_PITCH = 1678; +#endif - if (hw_cursor >= ROW*COL) { - hw_cursor = 0; - } - crtc_vga = TRUE; -#else /* IBM-PC */ - /* extract the hardware cursor location and move it out of the way */ - (*biosvidsw.read_hw_cursor)(V_ADP_PRIMARY, &col, &row); - (*biosvidsw.set_hw_cursor)(V_ADP_PRIMARY, -1, -1); -#endif /* PC98 */ + /* extract the hardware cursor location and hide the cursor for now */ + adp = vid_get_adapter(adapter); + (*vidsw[adapter]->read_hw_cursor)(adp, &col, &row); +#ifndef PC98 + (*vidsw[adapter]->set_hw_cursor)(adp, -1, -1); +#endif /* set up the first console */ current_default = &user_default; @@ -3834,23 +3772,11 @@ scinit(void) /* copy screen to temporary buffer */ if (ISTEXTSC(console[0])) -#ifdef PC98 - generic_bcopy(Crtat, sc_buffer, + generic_bcopy((ushort *)(console[0]->adp->va_window), sc_buffer, console[0]->xsize * console[0]->ysize * sizeof(u_short)); -#else /* PC98 */ - generic_bcopy((ushort *)(get_adapter(console[0])->va_window), sc_buffer, - console[0]->xsize * console[0]->ysize * sizeof(u_short)); -#endif /* PC98 */ console[0]->scr_buf = console[0]->mouse_pos = console[0]->mouse_oldpos = sc_buffer; -#ifdef PC98 - console[0]->cursor_pos = console[0]->cursor_oldpos = sc_buffer + hw_cursor; - console[0]->atr_buf = Atrat; - console[0]->cursor_atr = Atrat + hw_cursor; - console[0]->xpos = hw_cursor % COL; - console[0]->ypos = hw_cursor / COL; -#else if (col >= console[0]->xsize) col = 0; if (row >= console[0]->ysize) @@ -3859,7 +3785,11 @@ scinit(void) console[0]->ypos = row; console[0]->cursor_pos = console[0]->cursor_oldpos = sc_buffer + row*console[0]->xsize + col; +#ifndef PC98 console[0]->cursor_saveunder = *console[0]->cursor_pos; +#else + console[0]->atr_buf = Atrat; + console[0]->cursor_atr = Atrat + row*console[0]->xsize + col; #endif for (i=1; iva_flags)) { + if (ISFONTAVAIL(cur_console->adp->va_flags)) { if (fonts_loaded & FONT_16) { copy_font(cur_console, LOAD, 16, font_16); } else { @@ -3892,22 +3821,20 @@ scinit(void) * FONT KLUDGE * Always use the font page #0. XXX */ - (*biosvidsw.show_font)(cur_console->adp, 0); + (*vidsw[cur_console->ad]->show_font)(cur_console->adp, 0); } - save_palette(cur_console, palette); + save_palette(cur_console->adp, palette); -#ifdef SC_SPLASH_SCREEN - /* put up the splash. */ - scsplash_init(cur_console); -#endif +#if NSPLASH > 0 + /* we are ready to put up the splash image! */ + splash_init(cur_console->adp, scsplash_callback); #endif } static void scshutdown(int howto, void *arg) { - scsplash_stick(FALSE); - run_scrn_saver = FALSE; + sc_touch_scrn_saver(); if (!cold && cur_console->smode.mode == VT_AUTO && console[0]->smode.mode == VT_AUTO) switch_scr(cur_console, 0); @@ -3919,8 +3846,10 @@ sc_clean_up(scr_stat *scp) { int error; +#if NSPLASH > 0 if ((error = wait_scrn_saver_stop())) return error; +#endif /* NSPLASH */ scp->status &= ~MOUSE_VISIBLE; remove_cutmarking(scp); return 0; @@ -4023,13 +3952,13 @@ static scr_stat #ifdef PC98 sc_alloc_cut_buffer(scp, TRUE); #else /* PC98 */ - if (ISMOUSEAVAIL(get_adapter(scp)->va_flags)) + if (ISMOUSEAVAIL(scp->adp->va_flags)) sc_alloc_cut_buffer(scp, TRUE); #endif /* PC98 */ sc_alloc_history_buffer(scp, sc_history_size, 0, TRUE); /* SOS #ifndef PC98 - if (get_adapter(scp)->va_flags & V_ADP_MODECHANGE) + if (scp->adp->va_flags & V_ADP_MODECHANGE) #endif set_mode(scp); */ @@ -4043,26 +3972,14 @@ static scr_stat static void init_scp(scr_stat *scp) { -#ifndef PC98 video_info_t info; -#endif -#ifdef PC98 - scp->mode = M_PC98_80x25; - scp->scr_buf = NULL; - scp->atr_buf = NULL; - scp->font_size = 16; - - scp->xsize = COL; - scp->ysize = ROW; - scp->xpixel = scp->xsize * 8; - scp->ypixel = scp->ysize * scp->font_size; -#else - scp->adp = V_ADP_PRIMARY; - (*biosvidsw.get_info)(scp->adp, initial_video_mode, &info); + scp->ad = adapter; + scp->adp = vid_get_adapter(scp->ad); + (*vidsw[scp->ad]->get_info)(scp->adp, initial_video_mode, &info); scp->status = 0; - scp->mode = scp->initial_mode = initial_video_mode; + scp->mode = initial_video_mode; scp->scr_buf = NULL; if (info.vi_flags & V_INFO_GRAPHICS) { scp->status |= GRAPHICS_MODE; @@ -4079,7 +3996,6 @@ init_scp(scr_stat *scp) scp->font_size = info.vi_cheight; } scp->xoff = scp->yoff = 0; -#endif scp->xpos = scp->ypos = 0; scp->saved_xpos = scp->saved_ypos = -1; scp->start = scp->xsize * scp->ysize; @@ -4104,15 +4020,13 @@ init_scp(scr_stat *scp) scp->mouse_signal = 0; scp->mouse_pid = 0; scp->mouse_proc = NULL; + scp->kbd_mode = K_XLATE; scp->bell_pitch = BELL_PITCH; scp->bell_duration = BELL_DURATION; -#ifdef PC98 - scp->status = 0; - scp->status |= CURSOR_ENABLED; -#else +#ifndef PC98 scp->status |= (*(u_int8_t *)pa_to_va(0x417) & 0x20) ? NLKED : 0; - scp->status |= CURSOR_ENABLED; #endif + scp->status |= CURSOR_ENABLED; scp->pid = 0; scp->proc = NULL; scp->smode.mode = VT_AUTO; @@ -4127,20 +4041,6 @@ init_scp(scr_stat *scp) #endif } -static u_char -*get_fstr(u_int c, u_int *len) -{ - u_int i; - - if (!(c & FKEY)) - return(NULL); - i = (c & 0xFF) - F_FN; - if (i > n_fkey_tab) - return(NULL); - *len = fkey_tab[i].len; - return(fkey_tab[i].str); -} - static void history_to_screen(scr_stat *scp) { @@ -4201,151 +4101,46 @@ history_down_line(scr_stat *scp) * return NOKEY if there is nothing there. */ static u_int -scgetc(u_int flags) +scgetc(keyboard_t *kbd, u_int flags) { - struct keyent_t *key; - u_char scancode, keycode; - u_int state, action; - int c; - static u_char esc_flag = 0, compose = 0; - static u_int chr = 0; + u_int c; + int this_scr; + int f; + int i; + + if (kbd == NULL) + return NOKEY; next_code: + /* I don't like this, but... XXX */ + if (flags & SCGETC_CN) + sccnupdate(cur_console); /* first see if there is something in the keyboard port */ - if (flags & SCGETC_NONBLOCK) { - c = read_kbd_data_no_wait(sc_kbdc); - if (c == -1) - return(NOKEY); - } else { - do { - c = read_kbd_data(sc_kbdc); - } while(c == -1); + for (;;) { + c = kbd_read_char(kbd, !(flags & SCGETC_NONBLOCK)); + if (c == ERRKEY) { + if (!(flags & SCGETC_CN)) + do_bell(cur_console, BELL_PITCH, BELL_DURATION); + } else if (c == NOKEY) + return c; + else + break; } - scancode = (u_char)c; /* make screensaver happy */ - if (!(scancode & 0x80)) { - scsplash_stick(FALSE); - run_scrn_saver = FALSE; - } + if (!(c & RELKEY)) + sc_touch_scrn_saver(); - if (!(flags & SCGETC_CN)) { + if (!(flags & SCGETC_CN)) /* do the /dev/random device a favour */ - add_keyboard_randomness(scancode); + add_keyboard_randomness(c); - if (cur_console->status & KBD_RAW_MODE) - return scancode; - } - - keycode = scancode & 0x7F; - switch (esc_flag) { - case 0x00: /* normal scancode */ - switch(scancode) { - case 0xB8: /* left alt (compose key) */ - if (compose) { - compose = 0; - if (chr > 255) { - do_bell(cur_console, - BELL_PITCH, BELL_DURATION); - chr = 0; - } - } - break; - case 0x38: - if (!compose) { - compose = 1; - chr = 0; - } - break; - case 0xE0: - case 0xE1: - esc_flag = scancode; - goto next_code; - } - break; - case 0xE0: /* 0xE0 prefix */ - esc_flag = 0; - switch (keycode) { - case 0x1C: /* right enter key */ - keycode = 0x59; - break; - case 0x1D: /* right ctrl key */ - keycode = 0x5A; - break; - case 0x35: /* keypad divide key */ - keycode = 0x5B; - break; - case 0x37: /* print scrn key */ - keycode = 0x5C; - break; - case 0x38: /* right alt key (alt gr) */ - keycode = 0x5D; - break; - case 0x47: /* grey home key */ - keycode = 0x5E; - break; - case 0x48: /* grey up arrow key */ - keycode = 0x5F; - break; - case 0x49: /* grey page up key */ - keycode = 0x60; - break; - case 0x4B: /* grey left arrow key */ - keycode = 0x61; - break; - case 0x4D: /* grey right arrow key */ - keycode = 0x62; - break; - case 0x4F: /* grey end key */ - keycode = 0x63; - break; - case 0x50: /* grey down arrow key */ - keycode = 0x64; - break; - case 0x51: /* grey page down key */ - keycode = 0x65; - break; - case 0x52: /* grey insert key */ - keycode = 0x66; - break; - case 0x53: /* grey delete key */ - keycode = 0x67; - break; - - /* the following 3 are only used on the MS "Natural" keyboard */ - case 0x5b: /* left Window key */ - keycode = 0x69; - break; - case 0x5c: /* right Window key */ - keycode = 0x6a; - break; - case 0x5d: /* menu key */ - keycode = 0x6b; - break; - default: /* ignore everything else */ - goto next_code; - } - break; - case 0xE1: /* 0xE1 prefix */ - esc_flag = 0; - if (keycode == 0x1D) - esc_flag = 0x1D; - goto next_code; - /* NOT REACHED */ - case 0x1D: /* pause / break */ - esc_flag = 0; - if (keycode != 0x45) - goto next_code; - keycode = 0x68; - break; - } - - if (!(flags & SCGETC_CN) && (cur_console->status & KBD_CODE_MODE)) - return (keycode | (scancode & 0x80)); + if (cur_console->kbd_mode != K_XLATE) + return KEYCHAR(c); /* if scroll-lock pressed allow history browsing */ - if (cur_console->history && cur_console->status & SLKED) { - int i; + if (!ISGRAPHSC(cur_console) && cur_console->history + && cur_console->status & SLKED) { cur_console->status &= ~CURSOR_ENABLED; if (!(cur_console->status & BUFFER_SAVED)) { @@ -4371,10 +4166,11 @@ scgetc(u_int flags) cur_console->history + cur_console->history_size) #ifdef PC98 { -#endif cur_console->history_head=cur_console->history; -#ifdef PC98 - cur_console->his_atr_head=cur_console->his_atr; } + cur_console->his_atr_head=cur_console->his_atr; + } +#else + cur_console->history_head=cur_console->history; #endif } cur_console->history_pos = cur_console->history_head; @@ -4383,12 +4179,10 @@ scgetc(u_int flags) #endif history_to_screen(cur_console); } - switch (scancode) { -#ifdef PC98 - case 0x3E: /* home key */ -#else - case 0x47: /* home key */ -#endif + switch (c) { + /* FIXME: key codes */ + case SPCLKEY | FKEY | F(49): /* home key */ + remove_cutmarking(cur_console); cur_console->history_pos = cur_console->history_head; #ifdef PC98 cur_console->his_atr_pos = cur_console->his_atr_head; @@ -4396,11 +4190,8 @@ scgetc(u_int flags) history_to_screen(cur_console); goto next_code; -#ifdef PC98 - case 0x3F: /* help key */ -#else - case 0x4F: /* end key */ -#endif + case SPCLKEY | FKEY | F(57): /* end key */ + remove_cutmarking(cur_console); cur_console->history_pos = WRAPHIST(cur_console, cur_console->history_head, cur_console->xsize*cur_console->ysize); @@ -4412,183 +4203,65 @@ scgetc(u_int flags) history_to_screen(cur_console); goto next_code; -#ifdef PC98 - case 0x3A: /* up arrow key */ -#else - case 0x48: /* up arrow key */ -#endif + case SPCLKEY | FKEY | F(50): /* up arrow key */ + remove_cutmarking(cur_console); if (history_up_line(cur_console)) - do_bell(cur_console, BELL_PITCH, BELL_DURATION); + if (!(flags & SCGETC_CN)) + do_bell(cur_console, BELL_PITCH, BELL_DURATION); goto next_code; -#ifdef PC98 - case 0x3D: /* down arrow key */ -#else - case 0x50: /* down arrow key */ -#endif + case SPCLKEY | FKEY | F(58): /* down arrow key */ + remove_cutmarking(cur_console); if (history_down_line(cur_console)) - do_bell(cur_console, BELL_PITCH, BELL_DURATION); + if (!(flags & SCGETC_CN)) + do_bell(cur_console, BELL_PITCH, BELL_DURATION); goto next_code; -#ifdef PC98 - case 0x36: /* roll up key */ -#else - case 0x49: /* page up key */ -#endif + case SPCLKEY | FKEY | F(51): /* page up key */ + remove_cutmarking(cur_console); for (i=0; iysize; i++) if (history_up_line(cur_console)) { - do_bell(cur_console, BELL_PITCH, BELL_DURATION); + if (!(flags & SCGETC_CN)) + do_bell(cur_console, BELL_PITCH, BELL_DURATION); break; } goto next_code; -#ifdef PC98 - case 0x37: /* roll down key */ -#else - case 0x51: /* page down key */ -#endif + case SPCLKEY | FKEY | F(59): /* page down key */ + remove_cutmarking(cur_console); for (i=0; iysize; i++) if (history_down_line(cur_console)) { - do_bell(cur_console, BELL_PITCH, BELL_DURATION); + if (!(flags & SCGETC_CN)) + do_bell(cur_console, BELL_PITCH, BELL_DURATION); break; } goto next_code; } } - if (compose) { - switch (scancode) { - /* key pressed process it */ - case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ - chr = (scancode - 0x40) + chr*10; - goto next_code; - case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ - chr = (scancode - 0x47) + chr*10; - goto next_code; - case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ - chr = (scancode - 0x4E) + chr*10; - goto next_code; - case 0x52: /* keypad 0 */ - chr *= 10; - goto next_code; - - /* key release, no interest here */ - case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ - case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ - case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ - case 0xD2: /* keypad 0 */ - goto next_code; - - case 0x38: /* left alt key */ - break; - default: - if (chr) { - compose = chr = 0; - do_bell(cur_console, BELL_PITCH, BELL_DURATION); - goto next_code; - } - break; - } - } - - state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0)); - if ((!agrs && (cur_console->status & ALKED)) - || (agrs && !(cur_console->status & ALKED))) - keycode += ALTGR_OFFSET; - key = &key_map.key[keycode]; - if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED)) - || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) ) - state ^= 1; - - /* Check for make/break */ - action = key->map[state]; - if (scancode & 0x80) { /* key released */ - if (key->spcl & (0x80>>state)) { - switch (action) { - case LSH: - shfts &= ~1; - break; - case RSH: - shfts &= ~2; - break; - case LCTR: - ctls &= ~1; - break; - case RCTR: - ctls &= ~2; - break; - case LALT: - alts &= ~1; - break; - case RALT: - alts &= ~2; - break; - case NLK: - nlkcnt = 0; - break; - case CLK: -#ifdef PC98 - cur_console->status &= ~CLKED; - update_leds(cur_console->status); -#else - clkcnt = 0; -#endif - break; - case SLK: - slkcnt = 0; - break; - case ASH: - agrs = 0; - break; - case ALK: - alkcnt = 0; - break; - case META: - metas = 0; - break; - } - } - if (chr && !compose) { - action = chr; - chr = 0; - return(action); - } + /* + * Process and consume special keys here. Return a plain char code + * or a char code with the META flag or a function key code. + */ + if (c & RELKEY) { + /* key released */ + /* goto next_code */ } else { /* key pressed */ - if (key->spcl & (0x80>>state)) { - switch (action) { + if (c & SPCLKEY) { + c &= ~SPCLKEY; + switch (KEYCHAR(c)) { /* LOCKING KEYS */ - case NLK: - if (!nlkcnt) { - nlkcnt++; - if (cur_console->status & NLKED) - cur_console->status &= ~NLKED; - else - cur_console->status |= NLKED; - update_leds(cur_console->status); - } - break; - case CLK: -#ifdef PC98 - cur_console->status |= CLKED; - update_leds(cur_console->status); -#else - if (!clkcnt) { - clkcnt++; - if (cur_console->status & CLKED) - cur_console->status &= ~CLKED; - else - cur_console->status |= CLKED; - update_leds(cur_console->status); - } -#endif + case NLK: case CLK: case ALK: break; case SLK: - if (!slkcnt) { - slkcnt++; + kbd_ioctl(kbd, KDGKBSTATE, (caddr_t)&f); + if (f & SLKED) { + cur_console->status |= SLKED; + } else { if (cur_console->status & SLKED) { cur_console->status &= ~SLKED; - if (cur_console->status & BUFFER_SAVED){ + if (cur_console->status & BUFFER_SAVED) { int i; u_short *ptr = cur_console->history_save; #ifdef PC98 @@ -4612,11 +4285,12 @@ scgetc(u_int flags) cur_console->history + cur_console->history_size) #ifdef PC98 - { -#endif + { + ptr = cur_console->history; + ptr_a = cur_console->his_atr; + } +#else ptr = cur_console->history; -#ifdef PC98 - ptr_a = cur_console->his_atr; } #endif } cur_console->status &= ~BUFFER_SAVED; @@ -4629,73 +4303,64 @@ scgetc(u_int flags) } scstart(VIRTUAL_TTY(get_scr_num())); } - else - cur_console->status |= SLKED; - update_leds(cur_console->status); - } - break; - case ALK: - if (!alkcnt) { - alkcnt++; - if (cur_console->status & ALKED) - cur_console->status &= ~ALKED; - else - cur_console->status |= ALKED; - update_leds(cur_console->status); } break; /* NON-LOCKING KEYS */ case NOP: + case LSH: case RSH: case LCTR: case RCTR: + case LALT: case RALT: case ASH: case META: break; + + case BTAB: + return c; + case SPSC: /* force activatation/deactivation of the screen saver */ - accents = 0; - if (scrn_blanked <= 0) { + if (!scrn_blanked) { run_scrn_saver = TRUE; scrn_time_stamp -= scrn_blank_time; } -#ifdef SC_SPLASH_SCREEN +#if NSPLASH > 0 if (cold) { /* * While devices are being probed, the screen saver need * to be invoked explictly. XXX */ - if (scrn_blanked > 0) { + if (scrn_blanked) { scsplash_stick(FALSE); stop_scrn_saver(current_saver); } else { if (!ISGRAPHSC(cur_console)) { scsplash_stick(TRUE); - scrn_saver(current_saver, TRUE); + (*current_saver)(TRUE); } } } -#endif +#endif /* NSPLASH */ break; + case RBT: #ifndef SC_DISABLE_REBOOT - accents = 0; shutdown_nice(); -#endif - break; - case SUSP: -#if NAPM > 0 - accents = 0; - apm_suspend(PMST_SUSPEND); #endif break; - case STBY: #if NAPM > 0 - accents = 0; - apm_suspend(PMST_STANDBY); -#endif + case SUSP: + apm_suspend(PMST_SUSPEND); break; + case STBY: + apm_suspend(PMST_STANDBY); + break; +#else + case SUSP: + case STBY: + break; +#endif case DBG: #ifdef DDB /* try to switch to console 0 */ - accents = 0; /* * TRY to make sure the screen saver is stopped, * and the screen is updated before switching to @@ -4710,135 +4375,47 @@ scgetc(u_int flags) printf("No debugger in kernel\n"); #endif break; - case LSH: - shfts |= 1; - break; - case RSH: - shfts |= 2; - break; - case LCTR: - ctls |= 1; - break; - case RCTR: - ctls |= 2; - break; - case LALT: - alts |= 1; - break; - case RALT: - alts |= 2; - break; - case ASH: - agrs = 1; - break; - case META: - metas = 1; - break; - case NEXT: - { - int next, this = get_scr_num(); - accents = 0; - for (next = this+1; next != this; next = (next+1)%MAXCONS) { - struct tty *tp = VIRTUAL_TTY(next); - if (tp->t_state & TS_ISOPEN) { - switch_scr(cur_console, next); - break; - } - } - } - break; - case BTAB: - accents = 0; - return(BKEY); - default: - if (action >= F_ACC && action <= L_ACC) { - /* turn it into an index */ - action -= F_ACC - 1; - if ((action > accent_map.n_accs) - || (accent_map.acc[action - 1].accchar == 0)) { - /* - * The index is out of range or pointing to an - * empty entry. - */ - accents = 0; - do_bell(cur_console, BELL_PITCH, BELL_DURATION); - } - /* - * If the same accent key has been hit twice, - * produce the accent char itself. - */ - if (action == accents) { - action = accent_map.acc[accents - 1].accchar; - accents = 0; - if (metas) - action |= MKEY; - return (action); - } - /* remember the index and wait for the next key stroke */ - accents = action; - break; - } - if (accents > 0) { - accents = 0; - do_bell(cur_console, BELL_PITCH, BELL_DURATION); - } - if (action >= F_SCR && action <= L_SCR) { - switch_scr(cur_console, action - F_SCR); - break; - } - if (action >= F_FN && action <= L_FN) - action |= FKEY; - return(action); - } - } - else { - if (accents) { - struct acc_t *acc; - int i; - acc = &accent_map.acc[accents - 1]; - accents = 0; - /* - * If the accent key is followed by the space key, - * produce the accent char itself. - */ - if (action == ' ') { - action = acc->accchar; - if (metas) - action |= MKEY; - return (action); - } - for (i = 0; i < NUM_ACCENTCHARS; ++i) { - if (acc->map[i][0] == 0) /* end of the map entry */ + case NEXT: + this_scr = get_scr_num(); + for (i = this_scr + 1; i != this_scr; i = (i + 1)%MAXCONS) { + struct tty *tp = VIRTUAL_TTY(i); + if (tp->t_state & TS_ISOPEN) { + switch_scr(cur_console, i); break; - if (acc->map[i][0] == action) { - action = acc->map[i][1]; - if (metas) - action |= MKEY; - return (action); } } - do_bell(cur_console, BELL_PITCH, BELL_DURATION); - goto next_code; + break; + + default: + if (KEYCHAR(c) >= F_SCR && KEYCHAR(c) <= L_SCR) { + switch_scr(cur_console, KEYCHAR(c) - F_SCR); + break; + } + /* assert(c & FKEY) */ + return c; } - if (metas) - action |= MKEY; - return(action); + /* goto next_code */ + } else { + /* regular keys (maybe MKEY is set) */ + return c; } } + goto next_code; } int scmmap(dev_t dev, vm_offset_t offset, int nprot) { -#ifdef PC98 - if (offset > 0x48000 - PAGE_SIZE) -#else - if (offset > 0x20000 - PAGE_SIZE) -#endif - return -1; - return i386_btop((VIDEOMEM + offset)); + struct tty *tp; + struct scr_stat *scp; + + tp = scdevtotty(dev); + if (!tp) + return ENXIO; + scp = sc_get_scr_stat(tp->t_dev); + return (*vidsw[scp->ad]->mmap)(scp->adp, offset); } /* @@ -4870,87 +4447,64 @@ mask2attr(struct term_stat *term) return attr; } -#ifndef PC98 -static void -set_keyboard(int command, int data) +static int +save_kbd_state(scr_stat *scp) { - int s; + int state; + int error; - if (sc_kbdc == NULL) - return; - - /* prevent the timeout routine from polling the keyboard */ - if (!kbdc_lock(sc_kbdc, TRUE)) - return; - - /* disable the keyboard and mouse interrupt */ - s = spltty(); -#if 0 - c = get_controller_command_byte(sc_kbdc); - if ((c == -1) - || !set_controller_command_byte(sc_kbdc, - kbdc_get_device_mask(sc_kbdc), - KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT - | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { - /* CONTROLLER ERROR */ - kbdc_lock(sc_kbdc, FALSE); - splx(s); - return; + error = kbd_ioctl(kbd, KDGKBSTATE, (caddr_t)&state); + if (error == ENOIOCTL) + error = ENODEV; + if (error == 0) { + scp->status &= ~LOCK_MASK; + scp->status |= state; } - /* - * Now that the keyboard controller is told not to generate - * the keyboard and mouse interrupts, call `splx()' to allow - * the other tty interrupts. The clock interrupt may also occur, - * but the timeout routine (`scrn_timer()') will be blocked - * by the lock flag set via `kbdc_lock()' - */ - splx(s); -#endif - - if (send_kbd_command_and_data(sc_kbdc, command, data) != KBD_ACK) - send_kbd_command(sc_kbdc, KBDC_ENABLE_KBD); - -#if 0 - /* restore the interrupts */ - if (!set_controller_command_byte(sc_kbdc, - kbdc_get_device_mask(sc_kbdc), - c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { - /* CONTROLLER ERROR */ - } -#else - splx(s); -#endif - kbdc_lock(sc_kbdc, FALSE); + return error; } -#endif -static void -update_leds(int which) +static int +update_kbd_state(int new_bits, int mask) { -#ifndef PC98 - static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + int state; + int error; - /* replace CAPS led with ALTGR led for ALTGR keyboards */ - if (key_map.n_keys > ALTGR_OFFSET) { - if (which & ALKED) - which |= CLKED; - else - which &= ~CLKED; + if (mask != LOCK_MASK) { + error = kbd_ioctl(kbd, KDGKBSTATE, (caddr_t)&state); + if (error == ENOIOCTL) + error = ENODEV; + if (error) + return error; + state &= ~mask; + state |= new_bits & mask; + } else { + state = new_bits & LOCK_MASK; } + error = kbd_ioctl(kbd, KDSKBSTATE, (caddr_t)&state); + if (error == ENOIOCTL) + error = ENODEV; + return error; +} - set_keyboard(KBDC_SET_LEDS, xlate_leds[which & LED_MASK]); -#endif +static int +update_kbd_leds(int which) +{ + int error; + + which &= LOCK_MASK; + error = kbd_ioctl(kbd, KDSETLED, (caddr_t)&which); + if (error == ENOIOCTL) + error = ENODEV; + return error; } int set_mode(scr_stat *scp) { -#ifndef PC98 video_info_t info; - video_adapter_t *adp; /* reject unsupported mode */ - if ((*biosvidsw.get_info)(scp->adp, scp->mode, &info)) + if ((*vidsw[scp->ad]->get_info)(scp->adp, scp->mode, &info)) return 1; /* if this vty is not currently showing, do nothing */ @@ -4958,14 +4512,24 @@ set_mode(scr_stat *scp) return 0; /* setup video hardware for the given mode */ - adp = get_adapter(scp); - (*biosvidsw.set_mode)(scp->adp, scp->mode); - Crtat = (u_short *)adp->va_window; + (*vidsw[scp->ad]->set_mode)(scp->adp, scp->mode); + Crtat = (u_short *)scp->adp->va_window; + +#ifdef PC98 + if (scp->status & UNKNOWN_MODE) { + while (!(inb(0x60) & 0x20)) {} /* V-SYNC wait */ + outb(0x62, 0xc); /* text off */ + outb(0xA2, 0xd); /* graphics on */ + } else { + while (!(inb(0x60) & 0x20)) {} /* V-SYNC wait */ + outb(0x62, 0xd); /* text off */ + outb(0xA2, 0xc); /* graphics on */ + } +#endif if (!(scp->status & GRAPHICS_MODE)) { /* load appropriate font */ - if (!(scp->status & PIXEL_MODE) - && ISFONTAVAIL(get_adapter(scp)->va_flags)) { + if (!(scp->status & PIXEL_MODE) && ISFONTAVAIL(scp->adp->va_flags)) { if (scp->font_size < 14) { if (fonts_loaded & FONT_8) copy_font(scp, LOAD, 8, font_8); @@ -4977,57 +4541,28 @@ set_mode(scr_stat *scp) copy_font(scp, LOAD, 14, font_14); } /* - * FONT KLUDGE: - * This is an interim kludge to display correct font. - * Always use the font page #0 on the video plane 2. - * Somehow we cannot show the font in other font pages on - * some video cards... XXX - */ - (*biosvidsw.show_font)(scp->adp, 0); + * FONT KLUDGE: + * This is an interim kludge to display correct font. + * Always use the font page #0 on the video plane 2. + * Somehow we cannot show the font in other font pages on + * some video cards... XXX + */ + (*vidsw[scp->ad]->show_font)(scp->adp, 0); } mark_all(scp); } if (scp->status & PIXEL_MODE) - generic_bzero((u_char *)(adp->va_window), scp->xpixel*scp->ypixel/8); + generic_bzero((u_char *)(scp->adp->va_window), + scp->xpixel*scp->ypixel/8); set_border(scp, scp->border); +#ifndef PC98 /* move hardware cursor out of the way */ - (*biosvidsw.set_hw_cursor)(scp->adp, -1, -1); - - return 0; -#else /* PC98 */ - - if (scp != cur_console) - return 1; - - /* setup video hardware for the given mode */ -#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; - } + (*vidsw[scp->ad]->set_hw_cursor)(scp->adp, -1, -1); #endif - if (scp->status & UNKNOWN_MODE) { - while (!(inb(0x60) & 0x20)) {} /* V-SYNC wait */ - outb(0x62, 0xc); /* text off */ - outb(0xA2, 0xd); /* graphics on */ - } else { - while (!(inb(0x60) & 0x20)) {} /* V-SYNC wait */ - outb(0x62, 0xd); /* text off */ - outb(0xA2, 0xc); /* graphics on */ - } - /* set border color for this (virtual) console */ - set_border(scp, scp->border); return 0; -#endif /* PC98 */ } void @@ -5041,7 +4576,7 @@ set_border(scr_stat *scp, int color) int ylen; int i; - (*biosvidsw.set_border)(scp->adp, color); + (*vidsw[scp->ad]->set_border)(scp->adp, color); if (scp->status & PIXEL_MODE) { outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ @@ -5049,7 +4584,7 @@ set_border(scr_stat *scp, int color) outw(GDCIDX, 0x0f01); /* set/reset enable */ outw(GDCIDX, 0xff08); /* bit mask */ outw(GDCIDX, (color << 8) | 0x00); /* set/reset */ - p = (u_char *)(get_adapter(scp)->va_window); + p = (u_char *)(scp->adp->va_window); xoff = scp->xoff; yoff = scp->yoff*scp->font_size; xlen = scp->xpixel/8; @@ -5070,20 +4605,13 @@ set_border(scr_stat *scp, int color) outw(GDCIDX, 0x0001); /* set/reset enable */ } #else /* PC98 */ - switch (crtc_type) { - case KD_PC98: - outb(0x6c, color << 4); - break; - default: - break; - } + (*vidsw[scp->ad]->set_border)(scp->adp, color); #endif /* PC98 */ } void copy_font(scr_stat *scp, int operation, int font_size, u_char *buf) { -#ifndef PC98 /* * FONT KLUDGE: * This is an interim kludge to display correct font. @@ -5093,14 +4621,13 @@ copy_font(scr_stat *scp, int operation, int font_size, u_char *buf) */ font_loading_in_progress = TRUE; if (operation == LOAD) { - (*biosvidsw.load_font)(scp->adp, 0, font_size, buf, 0, 256); + (*vidsw[scp->ad]->load_font)(scp->adp, 0, font_size, buf, 0, 256); if (sc_flags & CHAR_CURSOR) set_destructive_cursor(scp); } else if (operation == SAVE) { - (*biosvidsw.save_font)(scp->adp, 0, font_size, buf, 0, 256); + (*vidsw[scp->ad]->save_font)(scp->adp, 0, font_size, buf, 0, 256); } font_loading_in_progress = FALSE; -#endif } static void @@ -5110,9 +4637,10 @@ set_destructive_cursor(scr_stat *scp) u_char cursor[32]; u_char *font_buffer; int font_size; + int crtc_addr; int i; - if (!ISFONTAVAIL(get_adapter(scp)->va_flags) + if (!ISFONTAVAIL(scp->adp->va_flags) || (scp->status & (GRAPHICS_MODE | PIXEL_MODE))) return; @@ -5148,10 +4676,11 @@ set_destructive_cursor(scr_stat *scp) (scp->cursor_start >= scp->font_size && i == scp->font_size - 1)) cursor[i] |= 0xff; #if 1 + crtc_addr = scp->adp->va_crtc_addr; while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ; #endif font_loading_in_progress = TRUE; - (*biosvidsw.load_font)(scp->adp, 0, font_size, cursor, DEAD_CHAR, 1); + (*vidsw[scp->ad]->load_font)(scp->adp, 0, font_size, cursor, DEAD_CHAR, 1); font_loading_in_progress = FALSE; #endif } @@ -5409,10 +4938,11 @@ draw_mouse_image(scr_stat *scp) #else u_short buffer[32]; u_short xoffset, yoffset; - u_short *crt_pos = (u_short *)(get_adapter(scp)->va_window) + u_short *crt_pos = (u_short *)(scp->adp->va_window) + (scp->mouse_pos - scp->scr_buf); u_char *font_buffer; int font_size; + int crtc_addr; int i; if (scp->font_size < 14) { @@ -5461,10 +4991,11 @@ draw_mouse_image(scr_stat *scp) #ifndef PC98 #if 1 /* wait for vertical retrace to avoid jitter on some videocards */ + crtc_addr = scp->adp->va_crtc_addr; while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ; #endif font_loading_in_progress = TRUE; - (*biosvidsw.load_font)(scp->adp, 0, 32, scp->mouse_cursor, + (*vidsw[scp->ad]->load_font)(scp->adp, 0, 32, scp->mouse_cursor, SC_MOUSE_CHAR, 4); font_loading_in_progress = FALSE; @@ -5494,7 +5025,7 @@ remove_mouse_image(scr_stat *scp) #ifdef PC98 crt_pos = Atrat + (scp->mouse_oldpos - scp->scr_buf); #else - crt_pos = (u_short *)(get_adapter(scp)->va_window) + crt_pos = (u_short *)(scp->adp->va_window) + (scp->mouse_oldpos - scp->scr_buf); #endif @@ -5522,7 +5053,7 @@ draw_cutmarking(scr_stat *scp) #ifdef PC98 crt_pos = Atrat; #else - crt_pos = (u_short *)(get_adapter(scp)->va_window); + crt_pos = (u_short *)(scp->adp->va_window); #endif for (ptr=scp->scr_buf; ptr<=(scp->scr_buf+(scp->xsize*scp->ysize)); ptr++) { nch = och = *(crt_pos + (ptr - scp->scr_buf)); @@ -5609,23 +5140,25 @@ blink_screen(void *arg) #ifdef PC98 if (blink_in_progress & 1){ fillw(scr_map[0x20], - Crtat, scp->xsize * scp->ysize); + (u_short *)(scp->adp->va_window), + scp->xsize * scp->ysize); fillw(at2pc98(kernel_default.std_color), Atrat, scp->xsize * scp->ysize); } else { fillw(scr_map[0x20], - Crtat, scp->xsize * scp->ysize); + (u_short *)(scp->adp->va_window), + scp->xsize * scp->ysize); fillw(at2pc98(kernel_default.rev_color), Atrat, scp->xsize * scp->ysize); } #else if (blink_in_progress & 1) fillw(kernel_default.std_color | scr_map[0x20], - (u_short *)(get_adapter(scp)->va_window), + (u_short *)(scp->adp->va_window), scp->xsize * scp->ysize); else fillw(kernel_default.rev_color | scr_map[0x20], - (u_short *)(get_adapter(scp)->va_window), + (u_short *)(scp->adp->va_window), scp->xsize * scp->ysize); #endif blink_in_progress--; @@ -5637,28 +5170,9 @@ void sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark) { #ifdef PC98 - if (ISTEXTSC(scp)) { - generic_bcopy(p + from, Crtat + from, + if (ISTEXTSC(scp)) + generic_bcopy(p + from, (u_short *)(scp->adp->va_window) + from, (to - from + 1)*sizeof(u_short)); - } else if (scp->mode == 0x102) { - u_char *d, *e; - int i,j; - - if (mark) - mark = 255; - d = (u_char *)Crtat; - d += 10 + 6*16*100 + (from%80) + 16*100*(from/80); - for (i = from ; i <= to ; i++) { - e = d; - for (j = 0 ; j < 16; j++) { - *e = mark^font_16[(p[i]&0xff)*16+j]; - e+=100; - } - d++; - if ((i % 80) == 79) - d += 20 + 15*100; - } - } #else /* PC98 */ u_char *font; u_char volatile *d; @@ -5672,7 +5186,7 @@ sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark) u_char c; if (ISTEXTSC(scp)) { - generic_bcopy(p + from, (u_short *)(get_adapter(scp)->va_window) + from, + generic_bcopy(p + from, (u_short *)(scp->adp->va_window) + from, (to - from + 1)*sizeof(u_short)); } else /* if ISPIXELSC(scp) */ { if (mark) @@ -5686,7 +5200,7 @@ sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark) font = font_14; line_length = scp->xpixel/8; xsize = scp->xsize; - d = (u_char *)(get_adapter(scp)->va_window) + d = (u_char *)(scp->adp->va_window) + scp->xoff + scp->yoff*font_size*line_length + (from%xsize) + font_size*line_length*(from/xsize); @@ -5756,203 +5270,4 @@ sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark) #endif /* PC98 */ } -#ifdef SC_SPLASH_SCREEN - -static void -scsplash_init(scr_stat *scp) -{ - video_info_t info; - - if (scsplash_load(scp) == 0 && add_scrn_saver(scsplash_saver) == 0) { - default_saver = scsplash_saver; - scrn_blank_time = DEFAULT_BLANKTIME; - run_scrn_saver = TRUE; - if (!(boothowto & (RB_VERBOSE | RB_CONFIG))) { - scsplash_stick(TRUE); - scsplash_saver(TRUE); - } - } -} - -static void -scsplash_term(scr_stat *scp) -{ - default_saver = none_saver; - scsplash_stick(FALSE); - remove_scrn_saver(scsplash_saver); - scsplash_unload(scp); -} - -static void -scsplash_saver(int show) -{ - if (show) - scsplash(TRUE); - else if (!sticky_splash) - scsplash(FALSE); -} - -#endif /* SC_SPLASH_SCREEN */ - -#if defined(PC98) && defined(LINE30) /* 30line */ - -static void master_gdc_cmd(unsigned int cmd) -{ - while ( (inb(0x60) & 2) != 0); - outb(0x62, cmd); -} - -static void master_gdc_prm(unsigned int pmtr) -{ - while ( (inb(0x60) & 2) != 0); - outb(0x60, 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(0x60) & 4) == 0); -} - -static void master_gdc_wait_vsync(void) -{ - while ( (inb(0x60) & 0x20) != 0); - while ( (inb(0x60) & 0x20) == 0); -} - -static void gdc_cmd(unsigned int cmd) -{ - while ( (inb(0xa0) & 2) != 0); - outb( 0xa2, cmd); -} - -static void gdc_prm(unsigned int pmtr) -{ - while ( (inb(0xa0) & 2) != 0); - outb( 0xa0, 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(0xa0) & 0x04) == 0); -} - -static void gdc_wait_vsync(void) -{ - while ( (inb(0xa0) & 0x20) != 0); - while ( (inb(0xa0) & 0x20) == 0); -} - -static int check_gdc_clock(void) -{ - if ((inb(0x31) & 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); -} -#endif /* 30 line */ - #endif /* NSC */ diff --git a/sys/pc98/pc98/syscons.h b/sys/pc98/pc98/syscons.h index 7370c8b260e8..a265d15277ae 100644 --- a/sys/pc98/pc98/syscons.h +++ b/sys/pc98/pc98/syscons.h @@ -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