summaryrefslogtreecommitdiffstats
path: root/sys/pc98/cbus/gdc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/pc98/cbus/gdc.c')
-rw-r--r--sys/pc98/cbus/gdc.c319
1 files changed, 253 insertions, 66 deletions
diff --git a/sys/pc98/cbus/gdc.c b/sys/pc98/cbus/gdc.c
index a6efd2a..e98f35e 100644
--- a/sys/pc98/cbus/gdc.c
+++ b/sys/pc98/cbus/gdc.c
@@ -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: pc98gdc.c,v 1.8 1999/05/09 04:56:42 kato Exp $
+ * $Id: pc98gdc.c,v 1.9 1999/05/30 16:53:20 phk Exp $
*/
#include "gdc.h"
@@ -72,7 +72,7 @@ typedef struct gdc_softc {
#define GDC_SOFTC(unit) \
((gdc_softc_t *)devclass_get_softc(gdc_devclass, unit))
-devclass_t gdc_devclass;
+static devclass_t gdc_devclass;
static int gdcprobe(device_t dev);
static int gdc_attach(device_t dev);
@@ -99,13 +99,15 @@ static int gdc_attach_unit(int unit, gdc_softc_t *sc, int flags);
static d_open_t gdcopen;
static d_close_t gdcclose;
static d_read_t gdcread;
+static d_write_t gdcwrite;
static d_ioctl_t gdcioctl;
+static d_mmap_t gdcmmap;
static struct cdevsw vga_cdevsw = {
/* open */ gdcopen,
/* close */ gdcclose,
- /* read */ noread,
- /* write */ nowrite,
+ /* read */ gdcread,
+ /* write */ gdcwrite,
/* ioctl */ gdcioctl,
/* stop */ nostop,
/* reset */ noreset,
@@ -139,9 +141,24 @@ static int
gdc_attach(device_t dev)
{
gdc_softc_t *sc;
+ int error;
sc = device_get_softc(dev);
- return gdc_attach_unit(device_get_unit(dev), sc, isa_get_flags(dev));
+ error = gdc_attach_unit(device_get_unit(dev), sc, isa_get_flags(dev));
+ if (error)
+ return error;
+
+#ifdef FB_INSTALL_CDEV
+ /* attach a virtual frame buffer device */
+ error = fb_attach(makedev(0, GDC_MKMINOR(unit)), sc->adp, &gdc_cdevsw);
+ if (error)
+ return error;
+#endif /* FB_INSTALL_CDEV */
+
+ if (bootverbose)
+ (*vidsw[sc->adp->va_index]->diag)(sc->adp, bootverbose);
+
+ return 0;
}
static int
@@ -152,7 +169,7 @@ gdc_probe_unit(int unit, gdc_softc_t *sc, int flags)
bzero(sc, sizeof(*sc));
sw = vid_get_switch(DRIVER_NAME);
if (sw == NULL)
- return 0;
+ return ENXIO;
return (*sw->probe)(unit, &sc->adp, NULL, flags);
}
@@ -160,30 +177,78 @@ 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;
+ return (*sw->init)(unit, sc->adp, flags);
+}
- error = (*sw->init)(unit, sc->adp, flags);
- if (error)
- return ENXIO;
+/* cdev driver functions */
#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);
+static int
+gdcopen(dev_t dev, int flag, int mode, struct proc *p)
+{
+ gdc_softc_t *sc;
- return 0;
+ sc = GDC_SOFTC(GDC_UNIT(dev));
+ if (sc == NULL)
+ return ENXIO;
+ if (mode & (O_CREAT | O_APPEND | O_TRUNC))
+ return ENODEV;
+
+ return genfbopen(&sc->gensc, sc->adp, flag, mode, p);
+}
+
+static int
+gdcclose(dev_t dev, int flag, int mode, struct proc *p)
+{
+ gdc_softc_t *sc;
+
+ sc = GDC_SOFTC(GDC_UNIT(dev));
+ return genfbclose(&sc->gensc, sc->adp, flag, mode, p);
+}
+
+static int
+gdcread(dev_t dev, struct uio *uio, int flag)
+{
+ gdc_softc_t *sc;
+
+ sc = GDC_SOFTC(GDC_UNIT(dev));
+ return genfbread(&sc->gensc, sc->adp, uio, flag);
+}
+
+static int
+gdcwrite(dev_t dev, struct uio *uio, int flag)
+{
+ gdc_softc_t *sc;
+
+ sc = GDC_SOFTC(GDC_UNIT(dev));
+ return genfbread(&sc->gensc, sc->adp, uio, flag);
+}
+
+static int
+gdcioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
+{
+ gdc_softc_t *sc;
+
+ sc = GDC_SOFTC(GDC_UNIT(dev));
+ return genfbioctl(&sc->gensc, sc->adp, cmd, arg, flag, p);
}
+static int
+gdcmmap(dev_t dev, vm_offset_t offset, int prot)
+{
+ gdc_softc_t *sc;
+
+ sc = GDC_SOFTC(GDC_UNIT(dev));
+ return genfbmmap(&sc->gensc, sc->adp, offset, prot);
+}
+
+#endif /* FB_INSTALL_CDEV */
+
/* LOW-LEVEL */
#include <machine/clock.h>
@@ -213,7 +278,7 @@ static video_adapter_t adapter_init_value[] = {
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* */
+ TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, 0, /* va_window* */
0, 0, /* va_buffer, va_buffer_size */
0, M_PC98_80x25, 0, /* va_*mode* */
},
@@ -224,6 +289,7 @@ static video_adapter_t biosadapter[1];
/* video driver declarations */
static int gdc_configure(int flags);
static int gdc_nop(void);
+static int gdc_err(video_adapter_t *adp, ...);
static vi_probe_t gdc_probe;
static vi_init_t gdc_init;
static vi_get_info_t gdc_get_info;
@@ -235,11 +301,11 @@ 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_blank_display_t gdc_blank_display;
+static vi_mmap_t gdc_mmap_buf;
+static vi_ioctl_t gdc_dev_ioctl;
static vi_diag_t gdc_diag;
-static int gdc_err(video_adapter_t *adp, ...);
-
static video_switch_t gdcvidsw = {
gdc_probe,
gdc_init,
@@ -258,8 +324,14 @@ static video_switch_t gdcvidsw = {
gdc_read_hw_cursor,
gdc_set_hw_cursor,
gdc_set_hw_cursor_shape,
- (vi_blank_display_t *)gdc_nop,
- gdc_mmap,
+ gdc_blank_display,
+ gdc_mmap_buf,
+ gdc_dev_ioctl,
+ (vi_clear_t *)gdc_err,
+ (vi_fill_rect_t *)gdc_err,
+ (vi_bitblt_t *)gdc_err,
+ (int (*)(void))gdc_err,
+ (int (*)(void))gdc_err,
gdc_diag,
};
@@ -271,15 +343,15 @@ VIDEO_DRIVER(gdc, gdcvidsw, gdc_configure);
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 },
+ TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
#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 },
+ TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
#endif
{ EOT },
};
-static int init_done = FALSE;
+static int gdc_init_done = FALSE;
/* local functions */
static int map_gen_mode_num(int type, int color, int mode);
@@ -287,7 +359,7 @@ 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))) \
+ if (!gdc_init_done || !((adp)->va_flags & (flag))) \
return (err)
/* a backdoor for the console driver */
@@ -336,9 +408,9 @@ probe_adapters(void)
video_info_t info;
/* do this test only once */
- if (init_done)
+ if (gdc_init_done)
return 1;
- init_done = TRUE;
+ gdc_init_done = TRUE;
biosadapter[0] = adapter_init_value[0];
biosadapter[0].va_flags |= V_ADP_PROBED;
@@ -547,6 +619,12 @@ gdc_nop(void)
}
static int
+gdc_err(video_adapter_t *adp, ...)
+{
+ return ENODEV;
+}
+
+static int
gdc_probe(int unit, video_adapter_t **adpp, void *arg, int flags)
{
probe_adapters();
@@ -587,8 +665,8 @@ gdc_get_info(video_adapter_t *adp, int mode, video_info_t *info)
{
int i;
- if (!init_done)
- return 1;
+ if (!gdc_init_done)
+ return ENXIO;
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) {
@@ -596,10 +674,11 @@ gdc_get_info(video_adapter_t *adp, int mode, video_info_t *info)
continue;
if (mode == bios_vmode[i].vi_mode) {
*info = bios_vmode[i];
+ info->vi_buffer_size = info->vi_window_size*info->vi_planes;
return 0;
}
}
- return 1;
+ return EINVAL;
}
/*
@@ -614,7 +693,7 @@ gdc_query_mode(video_adapter_t *adp, video_info_t *info)
video_info_t buf;
int i;
- if (!init_done)
+ if (!gdc_init_done)
return -1;
for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
@@ -661,16 +740,16 @@ gdc_set_mode(video_adapter_t *adp, int mode)
{
video_info_t info;
- prologue(adp, V_ADP_MODECHANGE, 1);
+ prologue(adp, V_ADP_MODECHANGE, ENODEV);
mode = map_gen_mode_num(adp->va_type,
adp->va_flags & V_ADP_COLOR, mode);
if (gdc_get_info(adp, mode, &info))
- return 1;
+ return EINVAL;
#ifdef LINE30
switch (info.vi_mode) {
- case M_PC98_80x25: /* VGA TEXT MODES */
+ case M_PC98_80x25: /* GDC TEXT MODES */
initialize_gdc(T25_G400);
break;
case M_PC98_80x30:
@@ -744,7 +823,7 @@ gdc_set_border(video_adapter_t *adp, int color)
static int
gdc_save_state(video_adapter_t *adp, void *p, size_t size)
{
- return 1;
+ return ENODEV;
}
/*
@@ -754,7 +833,7 @@ gdc_save_state(video_adapter_t *adp, void *p, size_t size)
static int
gdc_load_state(video_adapter_t *adp, void *p)
{
- return 1;
+ return ENODEV;
}
/*
@@ -767,11 +846,11 @@ gdc_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
u_int16_t off;
int s;
- if (!init_done)
- return 1;
+ if (!gdc_init_done)
+ return ENXIO;
if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
- return 1;
+ return ENODEV;
s = spltty();
master_gdc_cmd(0xe0); /* _GDC_CSRR */
@@ -802,14 +881,30 @@ gdc_set_hw_cursor(video_adapter_t *adp, int col, int row)
u_int16_t off;
int s;
- if (!init_done)
- return 1;
+ if (!gdc_init_done)
+ return ENXIO;
if ((col == -1) && (row == -1)) {
off = -1;
+ /* XXX */
+ if (epson_machine_id == 0x20) {
+ s = spltty();
+ outb(0x43f, 0x42);
+ outb(0x0c17, inb(0xc17) & ~0x08);
+ outb(0x43f, 0x40);
+ splx(s);
+ }
} else {
if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
- return 1;
+ return ENODEV;
+ /* XXX */
+ if (epson_machine_id == 0x20) {
+ s = spltty();
+ outb(0x43f, 0x42);
+ outb(0x0c17, inb(0xc17) | 0x08);
+ outb(0x43f, 0x40);
+ splx(s);
+ }
off = row*adp->va_info.vi_width + col;
}
@@ -834,6 +929,9 @@ gdc_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
int end;
int s;
+ if (!gdc_init_done)
+ return ENXIO;
+
start = celsize - (base + height);
end = celsize - base - 1;
/*
@@ -846,28 +944,76 @@ gdc_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
--end;
s = spltty();
+ if (epson_machine_id == 0x20) { /* XXX */
+ outb(0x43f, 0x42);
+ if (height > 0)
+ outb(0x0c17, inb(0xc17) | 0x08);
+ else
+ outb(0x0c17, inb(0xc17) & ~0x08);
+ outb(0x43f, 0x40);
+ }
master_gdc_cmd(0x4b); /* _GDC_CSRFORM */
master_gdc_prm(((height > 0) ? 0x80 : 0) /* cursor on/off */
- | (celsize - 1) & 0x1f); /* cel size */
+ | ((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;
+ return 0;
}
-static void
-dump_buffer(u_char *buf, size_t len)
+/*
+ * blank_display()
+ * Put the display in power save/power off mode.
+ */
+static int
+gdc_blank_display(video_adapter_t *adp, int mode)
{
- int i;
+ int s;
- for(i = 0; i < len;) {
- printf("%02x ", buf[i]);
- if ((++i % 16) == 0)
- printf("\n");
+ if (!gdc_init_done)
+ return ENXIO;
+
+ s = splhigh();
+ switch (mode) {
+ case V_DISPLAY_SUSPEND:
+ case V_DISPLAY_STAND_BY:
+ /*
+ * FIXME: I don't know how to put the display into `suspend'
+ * or `stand-by' mode via GDC...
+ */
+ /* FALL THROUGH */
+
+ case V_DISPLAY_BLANK:
+ if (epson_machine_id == 0x20) { /* XXX */
+ outb(0x43f, 0x42);
+ outb(0xc17, inb(0xc17) & ~0x08);
+ outb(0xc16, inb(0xc16) & ~0x02);
+ outb(0x43f, 0x40);
+ } else {
+ while (!(inb(TEXT_GDC) & 0x20)) /* V-SYNC wait */
+ ;
+ outb(TEXT_GDC + 2, 0xc); /* text off */
+ }
+ break;
+
+ case V_DISPLAY_ON:
+ if (epson_machine_id == 0x20) { /* XXX */
+ outb(0x43f, 0x42);
+ outb(0xc17, inb(0xc17) | 0x08);
+ outb(0xc16, inb(0xc16) | 0x02);
+ outb(0x43f, 0x40);
+ } else {
+ while (!(inb(TEXT_GDC) & 0x20)) /* V-SYNC wait */
+ ;
+ outb(TEXT_GDC + 2, 0xd); /* text on */
+ }
+ break;
}
+ splx(s);
+ return 0;
}
/*
@@ -875,11 +1021,58 @@ dump_buffer(u_char *buf, size_t len)
* Mmap frame buffer.
*/
static int
-gdc_mmap(video_adapter_t *adp, vm_offset_t offset)
+gdc_mmap_buf(video_adapter_t *adp, vm_offset_t offset, int prot)
{
- if (offset > 0x48000 - PAGE_SIZE)
+ /* FIXME: is this correct? XXX */
+ if (offset > VIDEO_BUF_SIZE - PAGE_SIZE)
return -1;
- return i386_btop((VIDEO_BUF_BASE + offset));
+ return i386_btop(adp->va_info.vi_window + offset);
+}
+
+static int
+gdc_dev_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
+{
+ switch (cmd) {
+ case FBIO_GETWINORG: /* get frame buffer window origin */
+ *(u_int *)arg = 0;
+ return 0;
+
+ case FBIO_SETWINORG: /* set frame buffer window origin */
+ case FBIO_SETDISPSTART: /* set display start address */
+ case FBIO_SETLINEWIDTH: /* set scan line length in pixel */
+ case FBIO_GETPALETTE: /* get color palette */
+ case FBIO_SETPALETTE: /* set color palette */
+ case FBIOGETCMAP: /* get color palette */
+ case FBIOPUTCMAP: /* set color palette */
+ return ENODEV;
+
+ case FBIOGTYPE: /* get frame buffer type info. */
+ ((struct fbtype *)arg)->fb_type = fb_type(adp->va_type);
+ ((struct fbtype *)arg)->fb_height = adp->va_info.vi_height;
+ ((struct fbtype *)arg)->fb_width = adp->va_info.vi_width;
+ ((struct fbtype *)arg)->fb_depth = adp->va_info.vi_depth;
+ if ((adp->va_info.vi_depth <= 1) || (adp->va_info.vi_depth > 8))
+ ((struct fbtype *)arg)->fb_cmsize = 0;
+ else
+ ((struct fbtype *)arg)->fb_cmsize = 1 << adp->va_info.vi_depth;
+ ((struct fbtype *)arg)->fb_size = adp->va_buffer_size;
+ return 0;
+
+ default:
+ return fb_commonioctl(adp, cmd, arg);
+ }
+}
+
+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");
+ }
}
/*
@@ -894,8 +1087,8 @@ gdc_diag(video_adapter_t *adp, int level)
int i;
#endif
- if (!init_done)
- return 1;
+ if (!gdc_init_done)
+ return ENXIO;
fb_dump_adp_info(DRIVER_NAME, adp, level);
@@ -912,10 +1105,4 @@ gdc_diag(video_adapter_t *adp, int level)
return 0;
}
-static int
-gdc_err(video_adapter_t *adp, ...)
-{
- return 0;
-}
-
#endif /* NGDC > 0 */
OpenPOWER on IntegriCloud