gfxp_vgatext.c revision 4ab75253616c6d68e967c10221bb663c0bfa99df
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
/* UNIX System Laboratories, Inc. */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/visual_io.h>
#include <sys/ddi_impldefs.h>
#include "gfx_private.h"
#define MYNAME "gfxp_vgatext"
/* I don't know exactly where these should be defined, but this is a */
/* heck of a lot better than constants in the code. */
#define TEXT_ROWS 25
#define TEXT_COLS 80
#define VGA_BRIGHT_WHITE 0x0f
#define VGA_BLACK 0x00
#define VGA_REG_ADDR 0x3c0
#define VGA_REG_SIZE 0x20
#define VGA_MEM_ADDR 0xa0000
#define VGA_MEM_SIZE 0x20000
#define VGA_MMAP_FB_BASE VGA_MEM_ADDR
struct vgatext_softc {
int fb_regno;
int mode; /* KD_TEXT or KD_GRAPHICS */
struct {
int row;
int col;
} cursor;
struct vis_polledio polledio;
struct {
unsigned char red;
unsigned char green;
unsigned char blue;
unsigned char attrib_palette[VGA_ATR_NUM_PLT];
};
static void vgatext_cons_copy(struct vgatext_softc *,
struct vis_conscopy *);
static void vgatext_cons_display(struct vgatext_softc *,
struct vis_consdisplay *);
static void vgatext_cons_cursor(struct vgatext_softc *,
struct vis_conscursor *);
static void vgatext_polled_copy(struct vis_polledio_arg *,
struct vis_conscopy *);
static void vgatext_polled_display(struct vis_polledio_arg *,
struct vis_consdisplay *);
static void vgatext_polled_cursor(struct vis_polledio_arg *,
struct vis_conscursor *);
static void vgatext_init(struct vgatext_softc *);
static void vgatext_set_text(struct vgatext_softc *);
#if defined(USE_BORDERS)
static void vgatext_init_graphics(struct vgatext_softc *);
#endif
static char vgatext_silent;
static char happyface_boot;
typedef enum pc_colors {
pc_black = 0,
pc_blue = 1,
pc_green = 2,
pc_cyan = 3,
pc_red = 4,
pc_magenta = 5,
pc_brown = 6,
pc_white = 7,
pc_grey = 8,
pc_brt_blue = 9,
pc_brt_green = 10,
pc_brt_cyan = 11,
pc_brt_red = 12,
pc_brt_magenta = 13,
pc_yellow = 14,
pc_brt_white = 15
} pc_colors_t;
static const unsigned char solaris_color_to_pc_color[16] = {
pc_brt_white, /* 0 - brt_white */
pc_black, /* 1 - black */
pc_blue, /* 2 - blue */
pc_green, /* 3 - green */
pc_cyan, /* 4 - cyan */
pc_red, /* 5 - red */
pc_magenta, /* 6 - magenta */
pc_brown, /* 7 - brown */
pc_white, /* 8 - white */
pc_grey, /* 9 - gery */
pc_brt_blue, /* 10 - brt_blue */
pc_brt_green, /* 11 - brt_green */
pc_brt_cyan, /* 12 - brt_cyan */
pc_brt_red, /* 13 - brt_red */
pc_brt_magenta, /* 14 - brt_magenta */
pc_yellow /* 15 - yellow */
};
static ddi_device_acc_attr_t dev_attr = {
};
/* default structure for FBIOGATTR ioctl */
static struct fbgattr vgatext_attr = {
/* real_type owner */
/* fbtype: type h w depth cms size */
/* fbsattr: flags emu_type dev_specific */
{ 0, FBTYPE_SUN4COLOR, { 0 } },
/* emu_types */
{ -1 }
};
gfxp_vgatext_softc_alloc(void)
{
}
void
{
}
int
{
int error;
char *parent_type = NULL;
int reg_rnumber;
char *cons;
switch (cmd) {
case DDI_ATTACH:
break;
case DDI_RESUME:
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
/* DDI_ATTACH */
if (error != DDI_SUCCESS) {
goto fail;
}
®_offset);
if (reg_rnumber < 0) {
MYNAME ": can't find reg entry for registers");
goto fail;
}
MYNAME ": can't find reg entry for memory");
goto fail;
}
®_offset);
if (reg_rnumber < 0) {
MYNAME ": can't find reg entry for registers");
goto fail;
}
&mem_offset);
MYNAME ": can't find reg entry for memory");
goto fail;
}
} else {
goto fail;
}
parent_type = NULL;
if (error != DDI_SUCCESS)
goto fail;
if (error != DDI_SUCCESS)
goto fail;
else
if (error != DDI_SUCCESS)
goto fail;
happyface_boot = 1;
vgatext_silent = 1;
}
}
/* only do this if not in graphics mode */
if (vgatext_silent == 0) {
}
return (DDI_SUCCESS);
fail:
if (parent_type != NULL)
return (error);
}
/*ARGSUSED*/
int
{
switch (cmd) {
case DDI_DETACH:
return (DDI_SUCCESS);
default:
cmd);
return (DDI_FAILURE);
}
}
/*ARGSUSED*/
int
{
return (ENXIO);
return (0);
}
/*ARGSUSED*/
int
{
return (0);
}
/*ARGSUSED*/
int
int cmd,
int mode,
int *rval,
{
static char kernel_only[] =
"gfxp_vgatext_ioctl: %s is a kernel only ioctl";
int err;
int kd_mode;
switch (cmd) {
case KDSETMODE:
case KDGETMODE:
return (EFAULT);
break;
case VIS_DEVINIT:
return (ENXIO);
}
if (err != 0) {
"gfxp_vgatext_ioctl: could not initialize console");
return (err);
}
break;
case VIS_CONSCOPY: /* move */
{
struct vis_conscopy pma;
sizeof (struct vis_conscopy), mode))
return (EFAULT);
break;
}
case VIS_CONSDISPLAY: /* display */
{
struct vis_consdisplay display_request;
sizeof (display_request), mode))
return (EFAULT);
break;
}
case VIS_CONSCURSOR:
{
struct vis_conscursor cursor_request;
sizeof (cursor_request), mode))
return (EFAULT);
sizeof (cursor_request), mode))
return (EFAULT);
break;
}
case VIS_GETCMAP:
case VIS_PUTCMAP:
case FBIOPUTCMAP:
case FBIOGETCMAP:
/*
* At the moment, text mode is not considered to have
* a color map.
*/
return (EINVAL);
case FBIOGATTR:
sizeof (struct fbgattr)))
return (EFAULT);
break;
case FBIOGTYPE:
sizeof (struct fbtype)))
return (EFAULT);
break;
default:
return (ENXIO);
}
return (0);
}
#pragma weak progressbar_stop
void
progressbar_stop(void)
{}
static int
{
int i;
return (0);
switch (mode) {
case KD_TEXT:
}
}
break;
case KD_GRAPHICS:
if (vgatext_silent == 1) {
extern void progressbar_stop(void);
vgatext_silent = 0;
}
}
#if defined(USE_BORDERS)
#endif
break;
default:
return (EINVAL);
}
return (0);
}
/*ARGSUSED*/
static int
{
int err;
return (-1);
}
if (!(off >= VGA_MMAP_FB_BASE &&
return (-1);
}
else
return (err);
}
return (0);
}
static int
{
/* initialize console instance */
return (0);
}
/*
* display a string on the screen at (row, col)
* assume it has been cropped to fit.
*/
static void
{
unsigned char *string;
int i;
unsigned char attr;
struct cgatext {
unsigned char ch;
unsigned char attr;
};
if (vgatext_silent)
return;
/*
* Sanity checks. This is a last-ditch effort to avoid damage
* from brokenness or maliciousness above.
*/
return;
/*
* To be fully general, we should copyin the data. This is not
* really relevant for this text-only driver, but a graphical driver
* should support these ioctls from userland to enable simple
* system startup graphics.
*/
addr++;
}
}
static void
struct vis_polledio_arg *arg,
struct vis_consdisplay *da)
{
}
/*
* screen-to-screen copy
*/
static void
{
unsigned short *from;
unsigned short *to;
int cnt;
unsigned short *to_row_start;
unsigned short *from_row_start;
unsigned short *base;
if (vgatext_silent)
return;
/*
* Sanity checks. Note that this is a last-ditch effort to avoid
* damage caused by broken-ness or maliciousness above.
*/
return;
/*
* Remember we're going to copy shorts because each
*/
/* More sanity checks. */
return;
if (to_row_start < from_row_start) {
while (rows_to_move-- > 0) {
to = to_row_start;
}
} else {
/*
* Offset to the end of the region and copy backwards.
*/
to_row_start += cnt;
from_row_start += cnt;
while (rows_to_move-- > 0) {
to = to_row_start;
}
}
}
static void
struct vis_polledio_arg *arg,
struct vis_conscopy *ca)
{
}
static void
{
if (vgatext_silent)
return;
case VIS_HIDE_CURSOR:
break;
case VIS_DISPLAY_CURSOR:
/*
* Sanity check. This is a last-ditch effort to avoid
* damage from brokenness or maliciousness above.
*/
return;
break;
case VIS_GET_CURSOR:
}
break;
}
}
static void
struct vis_polledio_arg *arg,
struct vis_conscursor *ca)
{
}
/*ARGSUSED*/
static void
{
/* Nothing at present */
}
static void
{
short addr;
if (vgatext_silent)
return;
}
static void
{
short addr;
}
/*
* This code is experimental. It's only enabled if console is
* set to graphics, a preliminary implementation of happyface boot.
*/
static void
{
int i;
if (happyface_boot == 0)
return;
/* we are in graphics mode, set to text 80X25 mode */
/* set misc registers */
/* set sequencer registers */
for (i = 1; i < NUM_SEQ_REG; i++) {
}
/* set crt controller registers */
for (i = 0; i < NUM_CRTC_REG; i++) {
}
/* set graphics controller registers */
for (i = 0; i < NUM_GRC_REG; i++) {
}
/* set attribute registers */
for (i = 0; i < NUM_ATR_REG; i++) {
}
/* set palette */
for (i = 0; i < VGA_TEXT_CMAP_ENTRIES; i++) {
}
for (i = VGA_TEXT_CMAP_ENTRIES; i < VGA8_CMAP_ENTRIES; i++) {
}
}
static void
{
unsigned char atr_mode;
if (atr_mode & VGA_ATR_MODE_GRAPH)
#if defined(USE_BORDERS)
#else
#endif
}
#if defined(USE_BORDERS)
static void
{
}
#endif
static void
{
extern unsigned char *ENCODINGS[];
unsigned char *from;
unsigned char *to;
int i;
int j;
int bpc;
/*
* The newboot code to use font plane 2 breaks NVIDIA
* (and some ATI) behavior. Revert back to the S10
* code.
*/
/*
* I'm embarassed to say that I don't know what these magic
* sequences do, other than at the high level of "set the
* memory window to allow font setup". I stole them straight
* from "kd"...
*/
/*
* This assumes 8x16 characters, which yield the traditional 80x25
* screen. It really should support other character heights.
*/
bpc = 16;
for (i = 0; i < 256; i++) {
for (j = 0; j < bpc; j++)
}
}
static void
{
int i;
for (i = 0; i < VGA_ATR_NUM_PLT; i++) {
}
for (i = 0; i < VGA8_CMAP_ENTRIES; i++) {
}
}
static void
{
int i;
for (i = 0; i < VGA_ATR_NUM_PLT; i++) {
}
for (i = 0; i < VGA8_CMAP_ENTRIES; i++) {
}
}
/*
* search the entries of the "reg" property for one which has the desired
* combination of phys_hi bits and contains the desired address.
*
* This version searches a PCI-style "reg" property. It was prompted by
* issues surrounding the presence or absence of an entry for the ROM:
* (a) a transition problem with PowerPC Virtual Open Firmware
* (b) uncertainty as to whether an entry will be included on a device
* with ROM support (and so an "active" ROM base address register),
* but no ROM actually installed.
*
* See the note below on vgatext_get_isa_reg_index for the reasons for
* returning the offset.
*
* Note that this routine may not be fully general; it is intended for the
* specific purpose of finding a couple of particular VGA reg entries and
* may not be suitable for all reg-searching purposes.
*/
static int
dev_info_t *const devi,
unsigned long himask,
unsigned long hival,
unsigned long addr,
{
return (-1);
}
continue;
continue;
continue;
continue;
continue;
return (index);
}
return (-1);
}
/*
* search the entries of the "reg" property for one which has the desired
* combination of phys_hi bits and contains the desired address.
*
* This version searches a ISA-style "reg" property. It was prompted by
* issues surrounding 8514/A support. By IEEE 1275 compatibility conventions,
* 8514/A registers should have been added after all standard VGA registers.
* (a) lists the 8514/A registers before the video memory, and then
* (b) also sorts the entries so that I/O entries come before memory
* entries.
*
* It returns the "reg" index and offset into that register set.
* The offset is needed because there exist (broken?) BIOSes that
* report larger ranges enclosing the standard ranges. One reports
* 0x3bf for 0x21 instead of 0x3c0 for 0x20, for instance. Using the
* offset adjusts for this difference in the base of the register set.
*
* Note that this routine may not be fully general; it is intended for the
* specific purpose of finding a couple of particular VGA reg entries and
* may not be suitable for all reg-searching purposes.
*/
static int
dev_info_t *const devi,
unsigned long hival,
unsigned long addr,
{
return (-1);
}
continue;
continue;
continue;
return (index);
}
return (-1);
}