NetBSD/sys/arch/alpha/common/vga.c
cgd 2c43c05bc2 replace old PCI VGA driver with a common VGA back-end and ISA and PCI
front-ends.  Unfortunately, because of the way ISA and PCI are currently
probed, if you have a PCI VGA board in your machine and both drivers
in your kernel, the ISA VGA driver may accidentally match the PCI board.
For now, the only solution to this is to not put both drivers in
the GENERIC kernels.
1996-11-19 04:38:32 +00:00

330 lines
7.5 KiB
C

/* $NetBSD: vga.c,v 1.1 1996/11/19 04:38:32 cgd Exp $ */
/*
* Copyright (c) 1995, 1996 Carnegie-Mellon University.
* All rights reserved.
*
* Author: Chris G. Demetriou
*
* Permission to use, copy, modify and distribute this software and
* its documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <machine/bus.h>
#include <alpha/wscons/wsconsvar.h>
#include <alpha/common/vgavar.h>
#define VGA_6845_ADDR 0x24
#define VGA_6845_DATA 0x25
struct cfdriver vga_cd = {
NULL, "vga", DV_DULL,
};
static void vga_cursor __P((void *, int, int, int));
static void vga_putstr __P((void *, int, int, char *, int));
static void vga_copycols __P((void *, int, int, int,int));
static void vga_erasecols __P((void *, int, int, int));
static void vga_copyrows __P((void *, int, int, int));
static void vga_eraserows __P((void *, int, int));
struct wscons_emulfuncs vga_emulfuncs = {
vga_cursor,
vga_putstr,
vga_copycols,
vga_erasecols,
vga_copyrows,
vga_eraserows,
};
static int vgaprint __P((void *, const char *));
static int vgaioctl __P((void *, u_long, caddr_t, int, struct proc *));
static int vgammap __P((void *, off_t, int));
/*
* The following functions implement back-end configuration grabbing
* and attachment.
*/
void
vga_getconfig(vc)
struct vga_config *vc;
{
bus_space_tag_t iot;
bus_space_handle_t ioh;
int cpos;
iot = vc->vc_iot;
ioh = vc->vc_ioh;
vc->vc_nrow = 25;
vc->vc_ncol = 80;
bus_space_write_1(iot, ioh, VGA_6845_ADDR, 14);
cpos = bus_space_read_1(iot, ioh, VGA_6845_DATA) << 8;
bus_space_write_1(iot, ioh, VGA_6845_ADDR, 15);
cpos |= bus_space_read_1(iot, ioh, VGA_6845_DATA);
vc->vc_crow = cpos / vc->vc_ncol;
vc->vc_ccol = cpos % vc->vc_ncol;
vc->vc_so = 0;
#if 0
vc->vc_at = 0x00 | 0xf; /* black bg|white fg */
vc->vc_so_at = 0x00 | 0xf | 0x80; /* black bg|white fg|blink */
/* clear screen, frob cursor, etc.? */
pcivga_eraserows(vc, 0, vc->vc_nrow);
#endif
/*
* XXX DEC HAS SWITCHED THE CODES FOR BLUE AND RED!!!
* XXX Therefore, though the comments say "blue bg", the code uses
* XXX the value for a red background!
*/
vc->vc_at = 0x40 | 0x0f; /* blue bg|white fg */
vc->vc_so_at = 0x40 | 0x0f | 0x80; /* blue bg|white fg|blink */
}
void
vga_wscons_attach(parent, vc, console)
struct device *parent;
struct vga_config *vc;
int console;
{
struct wscons_attach_args waa;
struct wscons_odev_spec *wo;
waa.waa_isconsole = console;
wo = &waa.waa_odev_spec;
wo->wo_emulfuncs = &vga_emulfuncs;
wo->wo_emulfuncs_cookie = vc;
wo->wo_ioctl = vgaioctl;
wo->wo_mmap = vgammap;
wo->wo_miscfuncs_cookie = vc;
wo->wo_nrows = vc->vc_nrow;
wo->wo_ncols = vc->vc_ncol;
wo->wo_crow = vc->vc_crow;
wo->wo_ccol = vc->vc_ccol;
config_found(parent, &waa, vgaprint);
}
void
vga_wscons_console(vc)
struct vga_config *vc;
{
struct wscons_odev_spec wo;
wo.wo_emulfuncs = &vga_emulfuncs;
wo.wo_emulfuncs_cookie = vc;
/* ioctl and mmap are unused until real attachment. */
wo.wo_nrows = vc->vc_nrow;
wo.wo_ncols = vc->vc_ncol;
wo.wo_crow = vc->vc_crow;
wo.wo_ccol = vc->vc_ccol;
wscons_attach_console(&wo);
}
static int
vgaprint(aux, pnp)
void *aux;
const char *pnp;
{
if (pnp)
printf("wscons at %s", pnp);
return (UNCONF);
}
static int
vgaioctl(v, cmd, data, flag, p)
void *v;
u_long cmd;
caddr_t data;
int flag;
struct proc *p;
{
/* XXX */
return -1;
}
static int
vgammap(v, offset, prot)
void *v;
off_t offset;
int prot;
{
/* XXX */
return -1;
}
/*
* The following functions implement the MI ANSI terminal emulation on
* a VGA display.
*/
static void
vga_cursor(id, on, row, col)
void *id;
int on, row, col;
{
struct vga_config *vc = id;
bus_space_tag_t iot = vc->vc_iot;
bus_space_handle_t ioh = vc->vc_ioh;
int pos;
#if 0
printf("vga_cursor: %d %d\n", row, col);
#endif
/* turn the cursor off */
if (!on) {
/* XXX disable cursor how??? */
vc->vc_crow = vc->vc_ccol = -1;
} else {
vc->vc_crow = row;
vc->vc_ccol = col;
}
pos = row * vc->vc_ncol + col;
bus_space_write_1(iot, ioh, VGA_6845_ADDR, 14);
bus_space_write_1(iot, ioh, VGA_6845_DATA, pos >> 8);
bus_space_write_1(iot, ioh, VGA_6845_ADDR, 15);
bus_space_write_1(iot, ioh, VGA_6845_DATA, pos);
}
static void
vga_putstr(id, row, col, cp, len)
void *id;
int row, col;
char *cp;
int len;
{
struct vga_config *vc = id;
bus_space_tag_t memt = vc->vc_memt;
bus_space_handle_t memh = vc->vc_memh;
int i, off;
off = (row * vc->vc_ncol + col) * 2;
for (i = 0; i < len; i++, cp++, off += 2) {
bus_space_write_1(memt, memh, off, *cp);
bus_space_write_1(memt, memh, off + 1,
vc->vc_so ? vc->vc_so_at : vc->vc_at);
}
}
static void
vga_copycols(id, row, srccol, dstcol, ncols)
void *id;
int row, srccol, dstcol, ncols;
{
struct vga_config *vc = id;
bus_space_tag_t memt = vc->vc_memt;
bus_space_handle_t memh = vc->vc_memh;
bus_size_t srcoff, srcend, dstoff;
/*
* YUCK. Need bus copy functions.
*/
srcoff = (row * vc->vc_ncol + srccol) * 2;
srcend = srcoff + ncols * 2;
dstoff = (row * vc->vc_ncol + dstcol) * 2;
for (; srcoff < srcend; srcoff += 2, dstoff += 2)
bus_space_write_2(memt, memh, dstoff,
bus_space_read_2(memt, memh, srcoff));
}
static void
vga_erasecols(id, row, startcol, ncols)
void *id;
int row, startcol, ncols;
{
struct vga_config *vc = id;
bus_space_tag_t memt = vc->vc_memt;
bus_space_handle_t memh = vc->vc_memh;
bus_size_t off, endoff;
u_int16_t val;
/*
* YUCK. Need bus 'set' functions.
*/
off = (row * vc->vc_ncol + startcol) * 2;
endoff = off + ncols * 2;
val = (vc->vc_at << 8) | ' ';
for (; off < endoff; off += 2)
bus_space_write_2(memt, memh, off, val);
}
static void
vga_copyrows(id, srcrow, dstrow, nrows)
void *id;
int srcrow, dstrow, nrows;
{
struct vga_config *vc = id;
bus_space_tag_t memt = vc->vc_memt;
bus_space_handle_t memh = vc->vc_memh;
bus_size_t srcoff, srcend, dstoff;
/*
* YUCK. Need bus copy functions.
*/
srcoff = (srcrow * vc->vc_ncol + 0) * 2;
srcend = srcoff + (nrows * vc->vc_ncol * 2);
dstoff = (dstrow * vc->vc_ncol + 0) * 2;
for (; srcoff < srcend; srcoff += 2, dstoff += 2)
bus_space_write_2(memt, memh, dstoff,
bus_space_read_2(memt, memh, srcoff));
}
static void
vga_eraserows(id, startrow, nrows)
void *id;
int startrow, nrows;
{
struct vga_config *vc = id;
bus_space_tag_t memt = vc->vc_memt;
bus_space_handle_t memh = vc->vc_memh;
bus_size_t off, endoff;
u_int16_t val;
/*
* YUCK. Need bus 'set' functions.
*/
off = (startrow * vc->vc_ncol + 0) * 2;
endoff = off + (nrows * vc->vc_ncol) * 2;
val = (vc->vc_at << 8) | ' ';
for (; off < endoff; off += 2)
bus_space_write_2(memt, memh, off, val);
}