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