3435 lines
117 KiB
C
3435 lines
117 KiB
C
#ifndef lint
|
|
static char sccsid[] = "@(#)cgeight.c 1.1 94/10/31 SMI";
|
|
#endif
|
|
|
|
/******************************************************************************
|
|
* ************************************************************************** *
|
|
* *"cgeight.c * *
|
|
* * * *
|
|
* * Device driver for the True Color (TC) Family of Frame Buffers * *
|
|
* * For The Sun Microsystems SBus. * *
|
|
* * * *
|
|
* * Conventions: * *
|
|
* * (1) File is formatted assuming tab stops every four characters. * *
|
|
* * (2) Routines are in alphabetical order. * *
|
|
* * (3) Prefix conventions for routine names: * *
|
|
* * (a) cgeightxxx - external entry point for driver. * *
|
|
* * (b) cg8_xxx - internal pixrect related code. * *
|
|
* * (c) pip_xxx - routine common to all pip implementations. * *
|
|
* * (d) tc_xxx - routine common to all hardware configurations* *
|
|
* * (e) tcp_xxx - routine for TC and TCP products. * *
|
|
* * (f) tcs_xxx - routine for TCS product. * *
|
|
* * * *
|
|
* * Copyright 1991, Sun Microsystems, Inc. * *
|
|
* ************************************************************************** *
|
|
******************************************************************************/
|
|
|
|
#include <sys/types.h> /* General type defs. */
|
|
#include <sys/param.h> /* General system parameters and limits. */
|
|
#include <sys/time.h> /* General timer parameters. */
|
|
|
|
#include <sys/buf.h> /* Input / Output buffer defs. */
|
|
#include <sys/errno.h> /* Kernel error defs. */
|
|
#include <sys/ioccom.h> /* Ioctl registery and macros. */
|
|
#include <sys/map.h> /* Resource allocation map information. */
|
|
#include <sys/proc.h> /* Process data structures and defs. */
|
|
#include <sys/user.h> /* User management and accounting defs. */
|
|
#include <sys/vmmac.h> /* Virtual memory related macros. */
|
|
|
|
#include <machine/eeprom.h> /* Non-volatile ram software defs. */
|
|
#include <machine/enable.h> /* Enable register defs. */
|
|
#include <machine/mmu.h> /* Memory management unit defs. */
|
|
#include <machine/pte.h> /* Page table entry defs. */
|
|
#include <mon/sunromvec.h> /* Rom monitor interface definition. */
|
|
|
|
#include <pixrect/pixrect.h> /* General pixrect related defs. */
|
|
#include <pixrect/pr_impl_util.h> /* Pixrect implementatino utilities. */
|
|
#include <pixrect/pr_planegroups.h> /* Bit plane manipulation defs. */
|
|
|
|
#include <sun/fbio.h> /* General frame buffer ioctl defs. */
|
|
#include <sundev/mbvar.h> /* Main bus interface defs. */
|
|
#include <sbusdev/memfb.h> /* SBus memory mapped frame buf layout. */
|
|
#include <sunwindow/cms.h> /* Colormapseg, cms_map */
|
|
|
|
#include <pixrect/memvar.h> /* Memory pixrect structural defs. */
|
|
#include <pixrect/cg4var.h> /* Need some defs from this device. */
|
|
#include <sundev/cg8reg.h> /* Device dependent memory layouts, etc. */
|
|
#include <pixrect/cg8var.h> /* Pixrect related variables for our card */
|
|
#include <sunwindow/rect.h> /* Definition of Rect data structure. */
|
|
|
|
#include "win.h" /* # of windows(non-zero => sunview) */
|
|
|
|
/*
|
|
* Debugging equates and macros
|
|
*/
|
|
#ifndef TC_DEBUG
|
|
#define TC_DEBUG 0
|
|
#endif TC_DEBUG
|
|
|
|
#define TEST_NEW_HARDWARE 1
|
|
|
|
#if TC_DEBUG
|
|
int tc1_debug = 5; /* Debugging level. */
|
|
#define DEBUGF(level, args) _STMT(if (tc1_debug >= (level)) printf args;)
|
|
#define DEBUG_LEVEL(level) {extern int tc1_debug; tc1_debug = level;}
|
|
#else TC_DEBUG
|
|
#define DEBUGF(level, args) /* nothing */
|
|
#define DEBUG_OFF
|
|
#define DEBUG_LEVEL(level)
|
|
#endif TC_DEBUG
|
|
|
|
/*
|
|
* Information telling how and when to memory map a frame buffer:
|
|
*/
|
|
typedef struct Mmap_Info { /* Frame buffer memory map region info: */
|
|
int group; /* Type of frame buffer to memory map. */
|
|
u_int bgn_offset; /* Offset in vm of start of frame buffer. */
|
|
u_int end_offset; /* Offset in vm of 1st word not in frame buffer. */
|
|
u_int sbus_delta; /* Offset in SBus slot (from device regs) of fb. */
|
|
} Mmap_Info;
|
|
|
|
/*
|
|
* Per-Unit Device Data Definitions:
|
|
*/
|
|
typedef struct Tc1_Softc
|
|
{
|
|
int basepage; /* Physical page # of mmap base addr. */
|
|
#ifdef TEST_NEW_HARDWARE
|
|
int test_basepage; /* Base page of slot 3 for testing h/w. */
|
|
#endif TEST_NEW_HARDWARE
|
|
|
|
int cmap_begin; /* Starting index for color map load. */
|
|
int cmap_count; /* # of entries to load. */
|
|
u_char cmap_blue[TC_CMAP_SIZE]; /* Blue components for color map. */
|
|
u_char cmap_green[TC_CMAP_SIZE]; /* Green components for color map. */
|
|
u_char cmap_red[TC_CMAP_SIZE]; /* Red components for color map. */
|
|
|
|
Tc1_Device_Map *device_reg; /* Device register area virt. address. */
|
|
int dev_reg_mmap_offset; /* Device regs memory offset from selves. */
|
|
int dev_reg_mmap_size; /* Device register area size in bytes. */
|
|
int dev_reg_sbus_base; /* Device register area SBus phys. offset */
|
|
int dev_reg_sbus_delta; /* SBus offset from dev. regs. (=0). */
|
|
Tcs_Device_Map *device_tcs; /* Device register are on TCS card. */
|
|
|
|
u_char em_blue[TC_CMAP_SIZE]; /* Indexed color map emulation : blue. */
|
|
u_char em_green[TC_CMAP_SIZE]; /* Indexed color map emulation : green. */
|
|
u_char em_red[TC_CMAP_SIZE]; /* Indexed color map emulation : red. */
|
|
|
|
u_char *fb_8bit; /* Eight-bit buffer virt. address. */
|
|
int fb_8bit_mmap_size; /* Size of region mmapped into virt memory */
|
|
int fb_8bit_sbus_delta; /* Eight bit SBus offset from device regs. */
|
|
|
|
u_char fb_model; /* Frame buffer model. */
|
|
|
|
u_char *fb_mono; /* Overlay (monochrome) buffer virt. addr. */
|
|
int fb_mono_mmap_size; /* Size of region mmapped into virt memory */
|
|
int fb_mono_sbus_delta; /* Monochrome SBus offset from device regs */
|
|
|
|
u_char *fb_sel; /* Enable (selection) memory virt. addr. */
|
|
int fb_sel_mmap_size; /* Size of region mmapped into virt memory */
|
|
int fb_sel_sbus_delta; /* Selection SBus offset from device regs. */
|
|
|
|
long *fb_tc; /* True color buffer virt. address. */
|
|
int fb_tc_mmap_size; /* Size of region mmapped into virt memory */
|
|
int fb_tc_sbus_delta; /* True color SBus offset from device regs */
|
|
|
|
u_char *fb_video; /* Video enable buffer virt. address. */
|
|
int fb_video_mmap_size; /* Size of region mmapped into vir. memory */
|
|
int fb_video_sbus_delta; /* SBus offset of video enable. */
|
|
|
|
int flags; /* Miscellaneous flags. */
|
|
int height; /* Height of display in scan lines. */
|
|
int linebytes1; /* # of bytes in a monochrome scan line. */
|
|
int linebytes8; /* # of bytes in an eight bit scan line. */
|
|
int linebytes32; /* # of bytes in a true color scan line. */
|
|
|
|
int memory_map_end; /* Total size of mapping of regions. */
|
|
int mmap_count; /* # of entries in use in mmap_info. */
|
|
Mmap_Info mmap_info[5]; /* Information on how to mmap fbs. */
|
|
|
|
int omap_begin; /* Starting index for overlay map load. */
|
|
int omap_count; /* # of entries to load. */
|
|
u_char omap_blue[TC_OMAP_SIZE]; /* Monochrome overlay color map: blue */
|
|
u_char omap_green[TC_OMAP_SIZE]; /* Monochrome overlay color map: green */
|
|
u_char omap_red[TC_OMAP_SIZE]; /* Monochrome overlay color map: red */
|
|
|
|
u_char pg_possible[FB_NPGS]; /* Plane groups which are possible. */
|
|
u_char pg_enabled[FB_NPGS]; /* Plane groups enabled for use. */
|
|
|
|
int pip_on_off_semaphore; /* -1 if on, else # of suspensions */
|
|
u_char sw_cursor_color_frozen; /* Berthold: cursor color is frozen. */
|
|
|
|
#if NWIN > 0
|
|
Pixrect pr; /* Kernel pixrect for this unit. */
|
|
struct cg8_data tc1d; /* Frame buffer specific data. */
|
|
#endif NWIN > 0
|
|
|
|
int timing_regimen; /* Current timing regimen (TCS card.) */
|
|
int width; /* Width of display in pixels. */
|
|
} Tc1_Softc;
|
|
|
|
#define SOFTC register Tc1_Softc
|
|
|
|
/* Forward references for kernel routines used by this device driver: */
|
|
|
|
addr_t kmem_zalloc();
|
|
addr_t map_regs();
|
|
void report_dev();
|
|
|
|
/* Compilation configuration switches and macros: */
|
|
|
|
#ifndef OLDDEVSW
|
|
#define OLDDEVSW 1
|
|
#endif OLDDEVSW
|
|
|
|
#ifndef NOHWINIT
|
|
#define NOHWINIT 0
|
|
#endif NOHWINIT
|
|
|
|
#if NOHWINIT
|
|
int tc1_hwinit = 1;
|
|
int tc1_small = 0;
|
|
int tc1_on = 1; /* Must be 1 to enable tc1 */
|
|
#endif NOHWINIT
|
|
|
|
#define TC_CMAP_ENTRIES MFB_CMAP_ENTRIES
|
|
|
|
#if OLDDEVSW
|
|
#define STATIC /* nothing */
|
|
#else OLDDEVSW
|
|
#define STATIC static
|
|
#endif OLDDEVSW
|
|
|
|
/* Configuration information (device driver operations vector) */
|
|
|
|
static int cgeightattach();
|
|
STATIC int cgeightclose();
|
|
static int cgeightindentify();
|
|
STATIC int cgeightioctl();
|
|
STATIC int cgeightmmap();
|
|
STATIC int cgeightopen();
|
|
static int cgeightpoll();
|
|
|
|
struct dev_ops cgeight_ops = {
|
|
0, /* revision */
|
|
cgeightindentify, /* Device driver indentification routine. */
|
|
cgeightattach, /* Attach this device as a slave. */
|
|
cgeightopen, /* Open the device. */
|
|
cgeightclose, /* Close the device. */
|
|
0, 0, 0, 0, 0,
|
|
cgeightioctl, /* Perform a control operation. */
|
|
0,
|
|
cgeightmmap, /* Map a page of the device's address space. */
|
|
};
|
|
|
|
/*
|
|
* Information kept on a per-unit basis for our device type.
|
|
*/
|
|
static int num_tc; /* # of frame buffers present. */
|
|
static Tc1_Softc *tc1_softc; /* Array of per unit data structures. */
|
|
|
|
#define TC_FB_ATTR 0x9C000001 /* Original SBus TC frame buffer attributes. */
|
|
|
|
/* Handy macros:
|
|
*/
|
|
#define SOFTC register Tc1_Softc /* Short hand for oft-used declaration. */
|
|
|
|
#define getsoftc(unit) (&tc1_softc[unit])
|
|
|
|
#define btob(n) ctob(btoc(n)) /* XXX */
|
|
|
|
#define BCOPY(s,d,c) bcopy((caddr_t) (s), (caddr_t) (d), (u_int) (c))
|
|
#define COPYIN(s,d,c) copyin((caddr_t) (s), (caddr_t) (d), (u_int) (c))
|
|
#define COPYOUT(s,d,c) copyout((caddr_t) (s), (caddr_t) (d), (u_int) (c))
|
|
|
|
/* Forward routine references:
|
|
*/
|
|
static int tcp_attach();
|
|
static int tcs_attach();
|
|
|
|
/* Default data structures for various ioctl requests. */
|
|
|
|
static
|
|
struct fbgattr tc1_attrdefault={ /* Default for FBIOGATTR ioctl: */
|
|
FBTYPE_MEMCOLOR, /* . Actual type. */
|
|
0, /* . Owner. */
|
|
{ /* . Frm buffer type(matchs tc1typedefault)*/
|
|
FBTYPE_MEMCOLOR, /* . . Type. */
|
|
0, /* . . Height. */
|
|
0, /* . . Width. */
|
|
32, /* . . Depth. */
|
|
256, /* . . Color map size. */
|
|
0 /* . . Size. */
|
|
}, /* . . */
|
|
{ /* . Frame buffer attributes (flags): */
|
|
FB_ATTR_AUTOINIT, /* . . Flags. */
|
|
FBTYPE_SUN2BW, /* . . Emu type. */
|
|
{ 0 } /* . . Device specific information. */
|
|
}, /* . . */
|
|
{ /* . Emu types. */
|
|
FBTYPE_MEMCOLOR,
|
|
FBTYPE_SUN2BW,
|
|
-1,
|
|
-1
|
|
}
|
|
};
|
|
|
|
static
|
|
struct fbgattr cg4_attrdefault={ /* Default for FBIOGATTR ioctl in cg4 mode: */
|
|
FBTYPE_SUN4COLOR, /* . Actual type. */
|
|
0, /* . Owner. */
|
|
{ /* . Frm buffer type(match tc1typedefault) */
|
|
FBTYPE_SUN4COLOR, /* . . Type. */
|
|
0, /* . . Height. */
|
|
0, /* . . Width. */
|
|
8, /* . . Depth. */
|
|
256, /* . . Color map size. */
|
|
0 /* . . Size. */
|
|
}, /* . . */
|
|
{ /* . Frame buffer attributes (flags): */
|
|
FB_ATTR_AUTOINIT, /* . . Flags. */
|
|
FBTYPE_SUN2BW, /* . . Emu type. */
|
|
{ 0 } /* . . Device specific information. */
|
|
}, /* . . */
|
|
{ /* . Emu types. */
|
|
FBTYPE_SUN4COLOR,
|
|
FBTYPE_SUN2BW,
|
|
-1,
|
|
-1
|
|
}
|
|
};
|
|
|
|
static
|
|
struct fbtype tc1typedefault={ /* Default for FBIOGTYPE ioctl for cg4, cg8: */
|
|
FBTYPE_SUN2BW, /* . Type. */
|
|
0, /* . Height. */
|
|
0, /* . Width. */
|
|
1, /* . Depth. */
|
|
0, /* . Color map size. */
|
|
0 /* . Size. */
|
|
};
|
|
|
|
static int cmsize = -1;
|
|
|
|
#if NWIN > 0
|
|
|
|
/* SunWindows related: Kernel pixrects operations vector definition.
|
|
*/
|
|
static int cg8_ioctl();
|
|
static int cg8_putattributes();
|
|
static int cg8_putcolormap();
|
|
static int cg8_rop();
|
|
|
|
static
|
|
struct pixrectops tcp_ops={/* Pip option present kernel pixrect ops vector: */
|
|
cg8_rop, /* . Raster operation. */
|
|
cg8_putcolormap, /* . Write the color map. */
|
|
cg8_putattributes, /* . Set the attributes. */
|
|
cg8_ioctl /* . Perform an ioctl operation. */
|
|
};
|
|
|
|
|
|
#endif NWIN > 0
|
|
|
|
/*
|
|
* Table to translate Sun overlay index into a SBus TC overlay index.
|
|
*
|
|
* Note that our overlay map works in a different manner from Sun's cg8, so a
|
|
* translation must be done (using translate_omap data structure):
|
|
* Function Sun LUT index SBus TC LUT index
|
|
* -------- ------------- ------------------
|
|
* True color 0 0
|
|
* Window system foreground 1 2
|
|
* Current window foreground 2 1
|
|
* Window system background 3 3
|
|
*
|
|
*/
|
|
static
|
|
u_char translate_omap[] = /* Translate caller's omap index to match hardware */
|
|
{ 0, 2, 1, 3};
|
|
|
|
/*"cgeightattach"
|
|
*
|
|
* Perform device specific initializations. (Called during autoconfiguration
|
|
* process.) This routine allocates the per-unit data structure associated
|
|
* with the device and initializes it from the properties exported by the
|
|
* on-board PROM. In addition it maps the device's memory regions into
|
|
* virtual memory and performs hardware specific initializations.
|
|
*
|
|
* = 1 if success
|
|
* = 0 if failure
|
|
*
|
|
*/
|
|
static cgeightattach(devi)
|
|
struct dev_info *devi; /* ->dev info struct w/node id...(rest filled here)*/
|
|
{
|
|
FB_Attributes fb_attr; /* Attributes about fb from on-board PROM. */
|
|
SOFTC *softc; /* Pointer to per-unit data for this device */
|
|
static int unit; /* Unit # to use.(NOTE VALUE INCREMENTS!) */
|
|
|
|
DEBUGF(1, ("cgeightattach num_tc=%d unit=%d\n", num_tc, unit));
|
|
|
|
|
|
/* If this is the first time attach has ever been called, allocate
|
|
* softc structures for the frame buffers.
|
|
*/
|
|
if (!tc1_softc)
|
|
{
|
|
tc1_softc = (struct Tc1_Softc *)
|
|
kmem_zalloc((u_int) sizeof (Tc1_Softc) * num_tc);
|
|
}
|
|
softc = getsoftc(unit);
|
|
|
|
|
|
|
|
/* SET UP PROPERTIES RELATED TO DEVICE REGISTER AREA AND MEMORIES
|
|
*
|
|
* Get properties from the on-board PROM (set up by Forth code at ipl time)
|
|
* Fill in the switches related to them. (Note we default enabled to
|
|
* possible here, but enabled bits are related to the type of device
|
|
* being emulated.)
|
|
*/
|
|
fb_attr.integer = (int)getprop(devi->devi_nodeid, "depth", TC_FB_ATTR);
|
|
if ( fb_attr.integer <= 1 ) fb_attr.integer = TC_FB_ATTR;
|
|
DEBUGF(5, (" PROM frame buffer attributes are %x\n", fb_attr.integer));
|
|
softc->pg_possible[PIXPG_OVERLAY] = fb_attr.flags.monochrome;
|
|
softc->pg_possible[PIXPG_OVERLAY_ENABLE] = fb_attr.flags.selection;
|
|
softc->pg_possible[PIXPG_8BIT_COLOR] = fb_attr.flags.eight_bit_hardware;
|
|
softc->pg_possible[PIXPG_24BIT_COLOR] = fb_attr.flags.true_color;
|
|
softc->pg_possible[PIXPG_VIDEO_ENABLE] = fb_attr.flags.pip_possible;
|
|
BCOPY(softc->pg_possible, softc->pg_enabled, FB_NPGS);
|
|
|
|
softc->fb_model = fb_attr.flags.model;
|
|
if ( softc->fb_model == 0 )
|
|
{
|
|
softc->fb_model = ( softc->pg_possible[PIXPG_8BIT_COLOR] ) ?
|
|
RASTEROPS_TCP : RASTEROPS_TC;
|
|
}
|
|
softc->timing_regimen = NATIVE_TIMING;
|
|
|
|
/* Get display image dimensions, and number of bytes between rows in a
|
|
* 1-bit pixel scan line. Use this information to generate the inter-row
|
|
* spacing for 8-bit and 32-bit scan lines.
|
|
*/
|
|
softc->width = getprop(devi->devi_nodeid, "width", 1152);
|
|
softc->height = getprop(devi->devi_nodeid, "height", 900);
|
|
softc->linebytes1 = getprop(devi->devi_nodeid, "linebytes",
|
|
mpr_linebytes(1152, 8));
|
|
softc->linebytes8 = softc->linebytes1 * 8;
|
|
softc->linebytes32 = softc->linebytes1 * 32;
|
|
|
|
/* PERFORM BOARD SPECIFIC PROCESSING BASED ON THE TYPE OF BOARD SPECIFIED
|
|
*
|
|
* The depth attribrute from the PROMs specifies the SBus Card model
|
|
* being used. Use this information to perform model specific
|
|
* initializations. A return code of zero indicates an error occurred, in
|
|
* which case this routine should signal a failure.
|
|
*/
|
|
switch(softc->fb_model)
|
|
{
|
|
default:
|
|
case RASTEROPS_TC:
|
|
case RASTEROPS_TCP:
|
|
if ( tcp_attach(devi, softc) == 0 ) return 0;
|
|
break;
|
|
case RASTEROPS_TCS:
|
|
if ( tcs_attach(devi, softc) == 0 ) return 0;
|
|
break;
|
|
}
|
|
|
|
/* REGISTER OUR DEVICE
|
|
*
|
|
* Save unit number in device information area we were passed.
|
|
* Attach interrupt routine. Save back pointer to softc in device
|
|
* information area. Increment the unit number for the next attach,
|
|
* and report the device.
|
|
*/
|
|
devi->devi_unit = unit;
|
|
addintr(devi->devi_intr[0].int_pri, cgeightpoll, devi->devi_name, unit);
|
|
devi->devi_data = (addr_t) softc;
|
|
|
|
unit++;
|
|
report_dev(devi);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*"cgeightclose"
|
|
*
|
|
* Close down operations on a SBus TC board
|
|
*
|
|
* = 0
|
|
*/
|
|
/*ARGSUSED*/
|
|
STATIC cgeightclose(dev, flag)
|
|
dev_t dev; /* = device specification for device to be closed. */
|
|
int flag; /* = read/write flags (unused in this routine. */
|
|
{
|
|
DEBUGF(2, ("cgeightclose(%d)\n", minor(dev)));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*"cgeightindentify"
|
|
*
|
|
* Check if a name matches that of our device, and if so update the
|
|
* count of devices we maintain.
|
|
*
|
|
* = number of devices present
|
|
* = 0 if name passed does not match, or this device type is disabled
|
|
*/
|
|
static cgeightindentify(name)
|
|
char *name; /* -> name to be tested. */
|
|
{
|
|
DEBUGF(1, ("cgeightindentify(%s)\n", name));
|
|
|
|
# if NOHWINIT
|
|
if (!tc1_on)
|
|
return 0;
|
|
# endif NOHWINIT
|
|
|
|
return (strcmp(name, "cgeight") == 0) ? ++num_tc : 0;
|
|
}
|
|
|
|
/*"cgeightioctl"
|
|
*
|
|
* Perform an input / output control operation on a SBus TC card
|
|
* or associated driver code.
|
|
*
|
|
* = 0 if successful operation
|
|
* ~= 0 if error detected
|
|
*/
|
|
cgeightioctl(dev, cmd, data, flag)
|
|
dev_t dev; /* = device specification for device to operate upon. */
|
|
int cmd; /* = opcode for operation to be performed. */
|
|
caddr_t data; /* -> data area for the operation . (may be in or out). */
|
|
int flag; /* = modifier info. for operation to be performed. */
|
|
{
|
|
SOFTC *softc = getsoftc(minor(dev)); /* Pointer to per-unit info. */
|
|
|
|
# ifdef TC_DEBUG
|
|
DEBUGF(5, ("tconeioctl: cmd = "));
|
|
switch (cmd) {
|
|
case FBIOSATTR:
|
|
DEBUGF(5, ("FBIOSATTR\n")); break;
|
|
case FBIOGATTR:
|
|
DEBUGF(5, ("FBIOGATTR\n")); break;
|
|
case FBIOGETCMAP:
|
|
DEBUGF(6, ("FBIOGETCMAP\n")); break;
|
|
case FBIOPUTCMAP:
|
|
DEBUGF(6, ("FBIOPUTCMAP\n")); break;
|
|
case FBIOGTYPE:
|
|
DEBUGF(5, ("FBIOGTYPE\n")); break;
|
|
case FBIOGPIXRECT:
|
|
DEBUGF(5, ("FBIOGPIXRECT\n")); break;
|
|
case FBIOSVIDEO:
|
|
DEBUGF(5, ("FBIOSVIDEO\n")); break;
|
|
case FBIOGVIDEO:
|
|
DEBUGF(5, ("FBIOGVIDEO\n")); break;
|
|
case PIPIO_G_CURSOR_COLOR_FREEZE:
|
|
DEBUGF(5, ("PIPIO_G_CURSOR_COLOR_FREEZE\n")); break;
|
|
case PIPIO_G_EMULATION_MODE:
|
|
DEBUGF(5, ("PIPIO_G_EMULATION_MODE\n")); break;
|
|
case PIPIO_G_FB_INFO:
|
|
DEBUGF(5, ("PIPIO_G_FB_INFO\n")); break;
|
|
case PIPIO_S_CURSOR_COLOR_FREEZE:
|
|
DEBUGF(5, ("PIPIO_S_CURSOR_COLOR_FREEZE\n")); break;
|
|
case PIPIO_S_EMULATION_MODE:
|
|
DEBUGF(5, ("PIPIO_S_EMULATION_MODE\n")); break;
|
|
default:
|
|
DEBUGF(5, ("not supported (0x%x)\n", cmd)); break;
|
|
}
|
|
# endif TC_DEBUG
|
|
|
|
/* Process request based on its type. Cases are alphabetical.
|
|
*/
|
|
switch (cmd)
|
|
{
|
|
case FBIOGATTR:
|
|
return x_g_attr( softc, (struct fbgattr *)data );
|
|
case FBIOGETCMAP:
|
|
return x_getcmap( softc, (struct fbcmap *)data );
|
|
#if NWIN > 0
|
|
case FBIOGPIXRECT:
|
|
return x_g_pixrect( softc, dev, (struct fbpixrect *)data );
|
|
#endif NWIN > 0
|
|
case FBIOGTYPE:
|
|
return x_g_type( softc, (struct fbtype *)data );
|
|
case FBIOGVIDEO:
|
|
switch(softc->fb_model)
|
|
{
|
|
default:
|
|
*(int *)data = mfb_get_video(&softc->device_reg->sun_mfb_reg) ?
|
|
FBVIDEO_ON : FBVIDEO_OFF;
|
|
break;
|
|
case RASTEROPS_TCS:
|
|
break;
|
|
}
|
|
break;
|
|
case FBIOPUTCMAP:
|
|
switch(softc->fb_model)
|
|
{
|
|
default:
|
|
return tc_putcmap( softc, (struct fbcmap *)data );
|
|
case RASTEROPS_TCS:
|
|
return tcs_putcmap( softc, (struct fbcmap *)data );
|
|
}
|
|
case FBIOSVIDEO:
|
|
switch(softc->fb_model)
|
|
{
|
|
default:
|
|
mfb_set_video(&softc->device_reg->sun_mfb_reg,
|
|
*(int *)data & FBVIDEO_ON);
|
|
break;
|
|
case RASTEROPS_TCS:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
/* Ioctls placed under the guise of the PIP which should always be
|
|
* handled.
|
|
*/
|
|
case PIPIO_G_CURSOR_COLOR_FREEZE:
|
|
*(int *)data = softc->sw_cursor_color_frozen;
|
|
break;
|
|
case PIPIO_G_EMULATION_MODE:
|
|
return x_g_emulation_mode( softc, (Pipio_Emulation *)data );
|
|
case PIPIO_G_FB_INFO:
|
|
return x_g_fb_info( softc, (Pipio_Fb_Info *)data );
|
|
case PIPIO_S_CURSOR_COLOR_FREEZE:
|
|
softc->sw_cursor_color_frozen = *(int *)data;
|
|
break;
|
|
case PIPIO_S_EMULATION_MODE:
|
|
return x_s_emulation_mode( softc, (Pipio_Emulation *)data );
|
|
#ifdef TEST_NEW_HARDWARE
|
|
case PIPIO_S_MAP_SLOT:
|
|
return x_s_map_slot( softc, (u_int *)data );
|
|
#endif TEST_NEW_HARDWARE
|
|
|
|
/*- Unknown request, see if the pip knows about it...
|
|
*/
|
|
default:
|
|
#ifndef NO_PIP
|
|
if ( (pip_ioctl(softc, cmd, data, flag) != 0) )
|
|
{
|
|
DEBUGF(5, ("not supported (0x%x)\n", cmd));
|
|
return EINVAL;
|
|
}
|
|
#else NO_PIP
|
|
return EINVAL;
|
|
#endif !NO_PIP
|
|
} /* switch(cmd) */
|
|
return 0;
|
|
}
|
|
|
|
/*"cgeightmmap"
|
|
*
|
|
* Provide physical page address associated with a memory map offset. This
|
|
* routine determines which of the six discontiguous physical memory
|
|
* regions the offset passed to it is associated with. Based on that
|
|
* determination a physical page address is calculated and returned.
|
|
*
|
|
* = PTE subset for the page in question
|
|
* = -1 if off is not within the memory space for one of the frame buffers
|
|
*
|
|
* Notes:
|
|
* (1) The value given by "off" is relative to the device register area
|
|
* (since its address was given in the map_regs call to allocate
|
|
* virtual memory for the mapping.)
|
|
* (2) See the description "Physical to virtual memory mapping for devices
|
|
* on the tc1" near the end of this file for further details of the
|
|
* mapping process.
|
|
*/
|
|
/*ARGSUSED*/
|
|
STATIC cgeightmmap(dev, off, prot)
|
|
dev_t dev; /* = device which is to be memory mapped. */
|
|
register off_t off; /* = offset into memory map for page to be mapped. */
|
|
int prot; /* (unused) */
|
|
{
|
|
int mmi; /* Index: # of mmap_info entry examining. */
|
|
Mmap_Info *mmp; /* Cursor: mmap_info entry examining. */
|
|
off_t phys_off; /* Physical offset from base page of page. */
|
|
SOFTC *softc = /* Pointer to per-unit info. */
|
|
getsoftc(minor(dev));
|
|
|
|
DEBUGF(off ? 9 : 1, ("cgeightmmap(%d, 0x%x)\n", minor(dev), (u_int) off));
|
|
|
|
#ifdef TEST_NEW_HARDWARE
|
|
if ( off >= 0x00900000 )
|
|
{
|
|
if ( softc->test_basepage == 0 ) return -1;
|
|
phys_off = (off-0x900000);
|
|
printf("Returning offset %x as phys_off %x and address %x\n",
|
|
off, phys_off, softc->test_basepage+btop(phys_off));
|
|
return softc->test_basepage + btop(phys_off);
|
|
}
|
|
#endif TEST_NEW_HARDWARE
|
|
|
|
/* It's not us, it's an interesting approach, but its not us!
|
|
*/
|
|
if ( (off < 0) || (off > softc->memory_map_end) )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
/* From "off" determine which physical memory is being referenced.
|
|
* Recalculate "off" as a physical offset relative to base page (that was
|
|
* mapped with map_regs).
|
|
*/
|
|
if ( off >= softc->dev_reg_mmap_offset ) /* DEVICE MAP */
|
|
{
|
|
phys_off = (off-softc->dev_reg_mmap_offset) + softc->dev_reg_sbus_delta;
|
|
return softc->basepage + btop(phys_off);
|
|
}
|
|
|
|
for ( mmi=0, mmp=softc->mmap_info; mmi < softc->mmap_count; mmi++, mmp++ )
|
|
{
|
|
if ( off >= mmp->bgn_offset && off < mmp->end_offset )
|
|
{
|
|
phys_off = (off - mmp->bgn_offset) + mmp->sbus_delta;
|
|
#if TC_DEBUG
|
|
DEBUGF((mmp->group==PIXPG_OVERLAY &&
|
|
off==mmp->bgn_offset) ? 1 : 9,
|
|
("cgeightmmap returning 0x%x (0x%x)\n",
|
|
ptob(softc->basepage)+phys_off,
|
|
softc->basepage+btop(phys_off)));
|
|
if ( off == mmp->bgn_offset )
|
|
{
|
|
switch (mmp->group)
|
|
{
|
|
case PIXPG_8BIT_COLOR:
|
|
printf("cgeightmmap returning eight bit color");
|
|
break;
|
|
case PIXPG_OVERLAY:
|
|
printf("cgeightmmap returning monochrome");
|
|
break;
|
|
case PIXPG_OVERLAY_ENABLE:
|
|
printf("cgeightmmap returning selection");
|
|
break;
|
|
case PIXPG_24BIT_COLOR:
|
|
printf("cgeightmmap returning true color");
|
|
break;
|
|
case PIXPG_VIDEO_ENABLE:
|
|
printf("cgeightmmap returning video enable");
|
|
break;
|
|
}
|
|
printf(" start at 0x%x (0x%x)\n",
|
|
ptob(softc->basepage)+phys_off,
|
|
softc->basepage+btop(phys_off));
|
|
}
|
|
#endif TC_DEBUG
|
|
return softc->basepage + btop(phys_off);
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/*"cgeightopen"
|
|
*
|
|
* Open a SBus TC board "device" for use.
|
|
*
|
|
* Parameters:
|
|
* dev = device to be opened
|
|
* flag = flags indicating access method (e.g., read, write)
|
|
*
|
|
* Function value:
|
|
* = return code from frame buffer driver open routine
|
|
*/
|
|
STATIC cgeightopen(dev, flag)
|
|
dev_t dev; /* = device specification giving what device instance to open */
|
|
int flag; /* = flags indicating access method (e.g., read, write). */
|
|
{
|
|
#ifdef LOADABLE
|
|
extern dev_t fbdev; /* Unit # of /dev/fb. */
|
|
#endif LOADABLE
|
|
|
|
DEBUGF(2, ("cgeightopen(%d,%d)\n", major(dev), minor(dev)));
|
|
|
|
#ifdef LOADABLE
|
|
/* This driver is dynamically loaded, so if the value for /dev/fb has
|
|
* not been set, make ourselves the default frame buffer. NOTE hardwire
|
|
* of /dev/fb's major device number!
|
|
*/
|
|
if ( (fbdev < 1) || (fbdev == 22) )
|
|
{
|
|
fbdev = dev;
|
|
}
|
|
#endif LOADABLE
|
|
|
|
return fbopen(dev, flag, num_tc);
|
|
}
|
|
|
|
/*"cgeightpoll"
|
|
*
|
|
* Interrupt service routine for vertical retrace interrupts
|
|
* on this device type. Loop through each device instance
|
|
* looking for one with an interrupt pending.
|
|
*
|
|
* = number of interrupts serviced
|
|
*/
|
|
static cgeightpoll()
|
|
{
|
|
Tcs_Device_Map *device_tcs; /* Poniter to tcs device register area. */
|
|
int instance; /* Index: instance now examining interrupt on*/
|
|
int serviced; /* Number of interrupts serviced. */
|
|
SOFTC *softc; /* Pointer to characteristics for our unit. */
|
|
|
|
serviced = 0;
|
|
for (softc = tc1_softc, instance = num_tc; --instance >= 0; softc++)
|
|
{
|
|
switch(softc->fb_model)
|
|
{
|
|
default:
|
|
if ( mfb_int_pending((struct mfb_reg *)softc->device_reg) )
|
|
{
|
|
mfb_int_disable( ((struct mfb_reg *)softc->device_reg) );
|
|
serviced++;
|
|
}
|
|
break;
|
|
case RASTEROPS_TCP:
|
|
case RASTEROPS_TC:
|
|
mfb_int_disable( ((struct mfb_reg *)softc->device_reg) );
|
|
serviced++;
|
|
break;
|
|
|
|
case RASTEROPS_TCS:
|
|
device_tcs = softc->device_tcs;
|
|
if ( device_tcs->tc_venus.status & VENUS_VERT_INT )
|
|
{
|
|
tcs_update_cmap(softc);
|
|
device_tcs->tc_venus.control4 = 0;
|
|
device_tcs->tc_venus.status = 0;
|
|
serviced++;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return serviced;
|
|
}
|
|
|
|
/*"cg8_ioctl"
|
|
*/
|
|
static int cg8_ioctl(pr, cmd, data)
|
|
Pixrect *pr;
|
|
int cmd;
|
|
caddr_t data;
|
|
{
|
|
static int save_window_fd;
|
|
|
|
switch (cmd)
|
|
{
|
|
case FBIOGPLNGRP:
|
|
*(int *) data = PIX_ATTRGROUP(cg8_d(pr)->planes);
|
|
break;
|
|
|
|
case FBIOAVAILPLNGRP:
|
|
{
|
|
static int cg4groups =
|
|
MAKEPLNGRP(PIXPG_OVERLAY) |
|
|
MAKEPLNGRP(PIXPG_OVERLAY_ENABLE) |
|
|
MAKEPLNGRP(PIXPG_24BIT_COLOR);
|
|
|
|
struct cg8_data *cg8d;
|
|
int fbi;
|
|
int group_mask = 0;
|
|
|
|
cg8d = cg8_d(pr);
|
|
for (fbi = 0; fbi < cg8d->num_fbs; fbi++)
|
|
{
|
|
group_mask |= MAKEPLNGRP(cg8d->fb[fbi].group);
|
|
}
|
|
*(int *) data = group_mask;
|
|
break;
|
|
}
|
|
|
|
case FBIO_FULLSCREEN_ELIMINATION_GROUPS:
|
|
{
|
|
struct cg8_data *cg8d;
|
|
char *elim_groups = (char *)data;
|
|
|
|
bzero(elim_groups, PIXPG_LAST_PLUS_ONE);
|
|
if ( cg8d->flags & CG8_EIGHT_BIT_PRESENT )
|
|
{
|
|
elim_groups[PIXPG_24BIT_COLOR] = 1;
|
|
}
|
|
else
|
|
{
|
|
elim_groups[PIXPG_8BIT_COLOR] = 1;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case FBIOGCMSIZE:
|
|
if (cmsize < 0)
|
|
return -1;
|
|
*(int *) data = cmsize;
|
|
break;
|
|
|
|
case FBIOSCMSIZE:
|
|
cmsize = *(int *) data;
|
|
break;
|
|
|
|
case FBIOSCMS:
|
|
cg8_d(pr)->cms = *(struct colormapseg *) data;
|
|
break;
|
|
|
|
case FBIOSWINFD:
|
|
cg8_d(pr)->windowfd = *(int *) data;
|
|
break;
|
|
|
|
case FBIOSAVWINFD:
|
|
if (cg8_d(pr)->windowfd >= -1)
|
|
{
|
|
save_window_fd = cg8_d(pr)->windowfd;
|
|
cg8_d(pr)->windowfd = -2;
|
|
}
|
|
break;
|
|
|
|
case FBIORESWINFD:
|
|
cg8_d(pr)->windowfd = save_window_fd;
|
|
break;
|
|
|
|
default:
|
|
return ENOTTY;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*"cg8_putattributes"
|
|
*/
|
|
static int cg8_putattributes (pr, planesp)
|
|
Pixrect *pr; /* -> pixrect to set plane group of. */
|
|
u_int *planesp; /* -> encoded group and plane mask */
|
|
{
|
|
struct cg8_data *cg8d; /* private data */
|
|
int dont_set_planes;
|
|
u_int planes,
|
|
group;
|
|
|
|
dont_set_planes = *planesp & PIX_DONT_SET_PLANES;
|
|
planes = *planesp & PIX_ALL_PLANES;/* the plane mask */
|
|
group = PIX_ATTRGROUP(*planesp); /* extract the group part */
|
|
|
|
cg8d = cg8_d (pr);
|
|
|
|
/*
|
|
* User is trying to set the group to something else. We'll see if the
|
|
* group is supported. If does, do as he wishes.
|
|
*/
|
|
if (group != PIXPG_CURRENT || group == PIXPG_INVALID)
|
|
{
|
|
int active = 0,
|
|
found = 0,
|
|
cm_size;
|
|
|
|
/* kernel should not access the color frame buffer */
|
|
|
|
if (group == PIXPG_TRANSPARENT_OVERLAY)
|
|
{
|
|
group = PIXPG_OVERLAY;
|
|
cg8d->flags |= CG8_COLOR_OVERLAY;
|
|
}
|
|
else
|
|
{
|
|
cg8d->flags &= ~CG8_COLOR_OVERLAY;
|
|
}
|
|
|
|
for (; active < cg8d->num_fbs && !found; active++)
|
|
{
|
|
if (found = (group == cg8d->fb[active].group))
|
|
{
|
|
cg8d->mprp = cg8d->fb[active].mprp;
|
|
cg8d->planes = PIX_GROUP (group) |
|
|
(cg8d->mprp.planes & PIX_ALL_PLANES);
|
|
cg8d->active = active;
|
|
pr->pr_depth = cg8d->fb[active].depth;
|
|
switch (group)
|
|
{
|
|
default:
|
|
case PIXPG_8BIT_COLOR:
|
|
case PIXPG_24BIT_COLOR:
|
|
cm_size = TC_CMAP_SIZE;
|
|
if (cg8d->flags&CG8_PIP_PRESENT) cg8d->flags|=CG8_STOP_PIP;
|
|
break;
|
|
case PIXPG_OVERLAY:
|
|
cm_size = 4;
|
|
cg8d->flags &= ~CG8_STOP_PIP;
|
|
break;
|
|
case PIXPG_OVERLAY_ENABLE:
|
|
cm_size = 0;
|
|
cg8d->flags &= ~CG8_STOP_PIP;
|
|
break;
|
|
case PIXPG_VIDEO_ENABLE:
|
|
cm_size = 0;
|
|
if (cg8d->flags&CG8_PIP_PRESENT) cg8d->flags|=CG8_STOP_PIP;
|
|
break;
|
|
}
|
|
cg8_ioctl(pr, FBIOSCMSIZE, (caddr_t) &cm_size);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* group is PIXPG_CURRNT here */
|
|
if (!dont_set_planes) {
|
|
cg8d->planes =
|
|
cg8d->mprp.planes =
|
|
cg8d->fb[cg8d->active].mprp.planes =
|
|
PIX_GROUP(group) | planes;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*"cg8_putcolormap"
|
|
*/
|
|
static int cg8_putcolormap(pr, index, count, red, green, blue)
|
|
Pixrect *pr;
|
|
int index,
|
|
count;
|
|
unsigned char *red,
|
|
*green,
|
|
*blue;
|
|
{
|
|
struct cg8_data *cg8d;
|
|
struct fbcmap fbmap;
|
|
int cc,i,plane;
|
|
|
|
/*
|
|
* Set "cg8d" to the cg8 private data structure. If the plane
|
|
* is not specified in the index, then use the currently active
|
|
* plane. ### Does this conflict with the cg4 model?
|
|
*/
|
|
|
|
cg8d = cg8_d(pr);
|
|
if (PIX_ATTRGROUP(index))
|
|
{
|
|
plane = PIX_ATTRGROUP(index) & PIX_GROUP_MASK;
|
|
index &= PR_FORCE_UPDATE | PIX_ALL_PLANES;
|
|
}
|
|
else
|
|
plane = cg8d->fb[cg8d->active].group;
|
|
|
|
/* If updates are to be forced, or the plane groups are 8 or 24 set
|
|
* the colormap via ioctl. Otherwise, use the emulation approach.
|
|
*/
|
|
|
|
if (index & PR_FORCE_UPDATE ||
|
|
plane == PIXPG_24BIT_COLOR || plane == PIXPG_8BIT_COLOR)
|
|
{
|
|
cg8d->flags |= CG8_KERNEL_UPDATE; /* BCOPY vs. COPYIN */
|
|
fbmap.index = index | PIX_GROUP(plane);
|
|
fbmap.count = count;
|
|
fbmap.red = red;
|
|
fbmap.green = green;
|
|
fbmap.blue = blue;
|
|
return cgeightioctl(cg8d->fd, FBIOPUTCMAP, (caddr_t) &fbmap, 0);
|
|
}
|
|
else /* emulated index */
|
|
{
|
|
if (plane == PIXPG_OVERLAY_ENABLE) return 0;
|
|
|
|
if (plane == PIXPG_OVERLAY)
|
|
{
|
|
for (cc=i=0; count && !cc; i++,index++,count--)
|
|
{
|
|
cg8d->flags |= CG8_KERNEL_UPDATE; /* BCOPY vs. COPYIN */
|
|
/* Index 0 is mapped to 1. All others mapped to 3. */
|
|
fbmap.index = (index ? 3 : 1) | PIX_GROUP(plane);
|
|
fbmap.count = 1;
|
|
fbmap.red = red+i;
|
|
fbmap.green = green+i;
|
|
fbmap.blue = blue+i;
|
|
cc = cgeightioctl(cg8d->fd, FBIOPUTCMAP, (caddr_t) &fbmap, 0);
|
|
}
|
|
return cc;
|
|
}
|
|
}
|
|
return PIX_ERR;
|
|
}
|
|
|
|
/* Macros to change a cg8 pixrect into a memory pixrect */
|
|
|
|
#define PR_TO_MEM(src, mem) \
|
|
if (src && src->pr_ops != &mem_ops) \
|
|
{ \
|
|
mem.pr_ops = &mem_ops; \
|
|
mem.pr_size = src->pr_size; \
|
|
mem.pr_depth = src->pr_depth; \
|
|
mem.pr_data = (char *) &cg8_d(src)->mprp; \
|
|
src = &mem; \
|
|
}
|
|
|
|
/*"cg8_rop"
|
|
*/
|
|
static int cg8_rop(dpr, dx, dy, w, h, op, spr, sx, sy)
|
|
Pixrect *dpr, *spr;
|
|
int dx, dy, w, h, op, sx, sy;
|
|
{
|
|
struct cg8_data *cg8d; /* Pointer to cg8 private data. */
|
|
Pixrect dmempr; /* Scratch area to build mem pixrect for dst. in. */
|
|
Pixrect smempr; /* Scratch area to build mem pixrect for src in. */
|
|
|
|
if (dpr->pr_depth>8 || (spr && spr->pr_depth>8))
|
|
{
|
|
printf("kernel: cg8_rop error: attempt at 32 bit rop\n");
|
|
return 0;
|
|
}
|
|
|
|
/* If the video enable plane group is being written to, ignore the
|
|
* call since, we do not map it in the kernel.
|
|
*/
|
|
cg8d = (dpr->pr_ops != &mem_ops ) ? cg8_d(dpr) : cg8_d(spr);
|
|
if ( cg8d->fb[cg8d->active].group == PIXPG_VIDEO_ENABLE )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
PR_TO_MEM(dpr, dmempr);
|
|
PR_TO_MEM(spr, smempr);
|
|
return pr_rop(dpr, dx, dy, w, h, op, spr, sx, sy);
|
|
}
|
|
|
|
#ifndef NO_PIP
|
|
|
|
/* Routines to support Picture In A Picture Option card.
|
|
*
|
|
*
|
|
* Notes:
|
|
* (1) Control status register zero has one bit which is shared, that is,
|
|
* it has different meanings on input and output. If the bit is written
|
|
* it directs that a one-shot grab should be done. If the bit is read
|
|
* it indicates if the pip has been turned on. Because of this sharing
|
|
* it is not possible to use read modify write cycles in "pip_off".
|
|
*
|
|
* (2) The TCP_CSR0_TURN_PIP_ON bit is used to set the pip on or off. Its
|
|
* value when read (TCP_CSR0_PIP_IS_ACTIVE) indicates if the pip is
|
|
* actively writing data, NOT necessarily if the pip is on. The
|
|
* TCP_CSR0_PIP_IS_ON bit indicates the the pip has been turned on, or
|
|
* is running. The cycle looks like:
|
|
*
|
|
* PIP_ON set Field start PIP_OFF set Field end
|
|
* | | | |
|
|
* | V V V
|
|
* V ____________...________________________
|
|
* PIP_IS_ACTIVE ________/ \_________
|
|
* __________________...________________________
|
|
* PIP_IS_ON __/ \_________
|
|
*
|
|
* (3) In addition, TCP_CSR0_PIP_IS_ACTIVE will drop if the input source is
|
|
* not present, even though it is "ON". So TCP_CSR0_PIP_IS_ON should be
|
|
* examined to determine the state of the pip, not
|
|
* TCP_CSR0_PIP_IS_ACTIVE.
|
|
*
|
|
* (4) When turning off the pip it will continue until the end of the field
|
|
* as shown above. So TCP_CSR0_PIP_IS_ACTIVE may be polled to see if
|
|
* the pip is off.
|
|
*
|
|
* 2
|
|
* I C Bus Programming Considerations And Details:
|
|
*
|
|
* (1) The i2c bus is implemented on the PIP as two contiguous bits in a
|
|
* single register. Thus read-modify writes are used to set and clear
|
|
* the bits. This can cause a problem during acknowledgement cycles
|
|
* since the receiver of data (one of the devices on the i2c bus) will
|
|
* hold the data line low during the acknowledgement cycle, which is
|
|
* ended with the clock being set high by us. However, since the clock
|
|
* is set high with a read-modify-write we pick up a low setting for
|
|
* the data bit and store it back. To get around this we explicitly set
|
|
* the data bit back to high after, or while, setting the clock. This
|
|
* actions are flagged with comments in the code below.
|
|
*
|
|
* (2) The standard cycle for sending the first data byte is as follows:
|
|
*
|
|
* Start
|
|
* |
|
|
* |
|
|
* |
|
|
* V 1 2 3 4 5 6 7 8 ack
|
|
* Clock: ____ __ __ __ __ __ __ __ __ __
|
|
* \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__
|
|
*
|
|
* Sender: __ _____ _____ _____ _____ _____ _____ _____ ____________
|
|
* Data \___/_____X_____X_____X_____X_____X_____X_____X_____/
|
|
*
|
|
* Reciever: ____________________________________________________ __
|
|
* Data \_____/
|
|
*
|
|
* (3) The standard cycle for sending subsequent bytes is:
|
|
*
|
|
*
|
|
* 1 2 3 4 5 6 7 8 ack
|
|
* Clock: __ __ __ __ __ __ __ __ __
|
|
* ____/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__
|
|
*
|
|
* Sender: _________ _____ _____ _____ _____ _____ _____ ___________
|
|
* Data \_____X_____X_____X_____X_____X_____X_____X_____/
|
|
*
|
|
* Reciever: __________________________________________________ ___
|
|
* Data \____/
|
|
*
|
|
* (4) The standard cycle for stop at the end of data transmission is:
|
|
*
|
|
*
|
|
* Clock: ______
|
|
* ____/
|
|
*
|
|
* Sender: ___ ____
|
|
* Data \__/
|
|
*
|
|
* (5) The standard cycle for reading a byte is:
|
|
*
|
|
*
|
|
* 1 2 3 4 5 6 7 8 stop
|
|
* Clock: __ __ __ __ __ __ __ __ _____
|
|
* ____/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/
|
|
*
|
|
* Sender: __________________________________________________ ____
|
|
* Data \__/
|
|
*
|
|
* Receiver: _________ _____ _____ _____ _____ _____ _____ ____
|
|
* Data \_____X_____X_____X_____X_____X_____X_____X____\____
|
|
*
|
|
*/
|
|
|
|
/*"pip_ioctl"
|
|
*
|
|
* Perform a pip-related input / output control operation on a
|
|
* SBus TC Card or its associated driver code
|
|
*
|
|
* = 0 if successful operation
|
|
* ~= 0 if error detected
|
|
*/
|
|
/*ARGSUSED*/
|
|
pip_ioctl(softc, cmd, data, flag)
|
|
SOFTC *softc; /* -> instance dependent storage. */
|
|
int cmd; /* = opcode for operation to be performed. */
|
|
caddr_t data; /* -> data area for the operation (may be in or out). */
|
|
int flag; /* = modifier info. for operation to be performed. */
|
|
{
|
|
|
|
# ifdef TC_DEBUG
|
|
DEBUGF(5, ("tconeioctl: cmd = "));
|
|
switch (cmd) {
|
|
case PIPIO_G_EMULATION_MODE:
|
|
DEBUGF(5, ("PIPIO_G_EMULATION_MODE\n")); break;
|
|
case PIPIO_G_PIP_ON_OFF:
|
|
DEBUGF(5, ("PIPIO_G_PIP_ON_OFF\n")); break;
|
|
case PIPIO_G_PIP_ON_OFF_SUSPEND:
|
|
DEBUGF(5, ("PIP_G_PIP_ON_OFF_SUSPEND\n")); break;
|
|
case PIPIO_G_PIP_ON_OFF_RESUME:
|
|
DEBUGF(5, ("PIP_G_PIP_ON_OFF_RESUME\n")); break;
|
|
|
|
case PIPIO_S_EMULATION_MODE:
|
|
DEBUGF(5, ("PIPIO_S_EMULATION_MODE\n")); break;
|
|
case PIPIO_S_PIP_ON_OFF:
|
|
DEBUGF(5, ("PIP_S_PIP_ON_OFF\n")); break;
|
|
default:
|
|
DEBUGF(5, ("not supported (0x%x)\n", cmd)); break;
|
|
}
|
|
# endif TC_DEBUG
|
|
|
|
/* Make sure pip operations are possible, then process request based on its
|
|
* type. Cases are alphabetical.
|
|
*/
|
|
if ( softc->pg_possible[PIXPG_VIDEO_ENABLE] == 0 )
|
|
{
|
|
return EINVAL;
|
|
}
|
|
switch (cmd)
|
|
{
|
|
case PIPIO_G_PIP_ON_OFF:
|
|
*(int *)data =
|
|
(softc->device_reg->control_status&TCP_CSR0_PIP_IS_ON) ? 1 : 0;
|
|
break;
|
|
case PIPIO_G_PIP_ON_OFF_RESUME:
|
|
softc->pip_on_off_semaphore--;
|
|
if ( softc->pip_on_off_semaphore < 0 )
|
|
{
|
|
softc->pip_on_off_semaphore = -1; /* In case too many resumes */
|
|
pip_on(softc->device_reg);
|
|
*(int *)data = 1;
|
|
}
|
|
else
|
|
{
|
|
*(int *)data = 0;
|
|
}
|
|
break;
|
|
case PIPIO_G_PIP_ON_OFF_SUSPEND:
|
|
*(int *)data = pip_off(softc, 0);
|
|
softc->pip_on_off_semaphore++;
|
|
break;
|
|
|
|
case PIPIO_S_PIP_ON_OFF:
|
|
if ( *(int *)data )
|
|
{
|
|
pip_on(softc->device_reg);
|
|
softc->pip_on_off_semaphore = -1;
|
|
}
|
|
else
|
|
{
|
|
pip_off(softc, 0);
|
|
softc->pip_on_off_semaphore = 0;
|
|
}
|
|
break;
|
|
|
|
/*- Unknown request, return fact we could not process it. */
|
|
|
|
default:
|
|
return ENOTTY;
|
|
|
|
} /* switch(cmd) */
|
|
return 0;
|
|
}
|
|
|
|
/*"pip_off"
|
|
*
|
|
* Turn off live video generation, returning the previous state of the bit.
|
|
*
|
|
*
|
|
* Notes:
|
|
* (1) See notes 2 and 3 at the beginning of this file for a detailed
|
|
* explanation of all the shenanigans with bits in control status
|
|
* register 0 that occur here.
|
|
*
|
|
* = 1 if pip was on
|
|
* = 0 if pip was off
|
|
*/
|
|
int pip_off(softc, wait_for_inactive)
|
|
SOFTC *softc; /* -> device instance dependent data. */
|
|
int wait_for_inactive; /* = 1 if wait for pip to actually turn off */
|
|
{
|
|
int i; /* Index: # of times gone around wait loop. */
|
|
int pip_was_on; /* Indicates if pip was active. */
|
|
Tc1_Device_Map *dmap; /* -> device area on TCPIP card. */
|
|
|
|
dmap = softc->device_reg;
|
|
pip_was_on = dmap->control_status & TCP_CSR0_PIP_IS_ON;
|
|
dmap->control_status&=(u_char)~(TCP_CSR0_TURN_PIP_ON|TCP_CSR0_PIP_ONE_SHOT);
|
|
if ( wait_for_inactive && (dmap->control_status & TCP_CSR0_PIP_IS_ACTIVE) )
|
|
{
|
|
printf("Waiting for inactive\n");
|
|
for (i = 0; i < 10000000; i++)
|
|
{
|
|
if ( !(dmap->control_status & TCP_CSR0_PIP_IS_ACTIVE) ) break;
|
|
}
|
|
if ( i >= 10000000 )
|
|
{
|
|
printf(" Pip did not turn off in %d loops!!!!\n", i);
|
|
}
|
|
}
|
|
return (pip_was_on) ? 1 : 0;
|
|
}
|
|
|
|
/*"pip_on"
|
|
*
|
|
* Turn on live video generation. (Don't do it unless there
|
|
* is an active data source connected.
|
|
*/
|
|
int pip_on(dmap)
|
|
Tc1_Device_Map *dmap; /* -> device area on TCPIP card. */
|
|
{
|
|
if ( dmap->control_status1 & TCP_CSR1_INPUT_CONNECTED )
|
|
{
|
|
dmap->control_status =
|
|
((u_int)dmap->control_status&~TCP_CSR0_PIP_ONE_SHOT) |
|
|
TCP_CSR0_TURN_PIP_ON;
|
|
}
|
|
}
|
|
|
|
#endif !NO_PIP
|
|
|
|
/*"tc_putcmap"
|
|
*
|
|
* Local routine to set the color map values for either the 24-bit or the
|
|
* monochrome frame buffer on a TC or TCP card. In addition to real lookup
|
|
* table manipulation, emulation of 8-bit indexed color maps is done for
|
|
* 24-bit mode. (Called by tcone_ioctl).
|
|
* = 0 if success
|
|
* = error indication otherwise
|
|
*/
|
|
static int tc_putcmap( softc, cmap )
|
|
SOFTC *softc; /* -> characteristics for our unit. */
|
|
struct fbcmap *cmap; /* -> where to get colormap(data area from ioctl). */
|
|
{
|
|
u_int count; /* # of color map entries to set. */
|
|
Tc1_Device_Map *device_reg; /* Pointer to the Brooktrees. */
|
|
int force_update; /* Indicates if should access real luts */
|
|
u_int index; /* Index of first entry to access. */
|
|
int n_entry; /* Loop index: current color map entry. */
|
|
int plane_group; /* Top 7 bits of index = plane group. */
|
|
|
|
device_reg = softc->device_reg;
|
|
|
|
/*
|
|
* Verify we need to actually move some data.Initialize variables
|
|
* from caller's parameters, etc. If the plane group is zero, use
|
|
* the 24 bit group.
|
|
*/
|
|
if ( (cmap->count == 0) || !cmap->red || !cmap->green || !cmap->blue )
|
|
{
|
|
return 0;
|
|
}
|
|
count = cmap->count;
|
|
index = cmap->index & PIX_ALL_PLANES;
|
|
if (index+count > TC_CMAP_SIZE)
|
|
{
|
|
return EINVAL;
|
|
}
|
|
force_update = cmap->index & PR_FORCE_UPDATE;
|
|
if ( !(plane_group = PIX_ATTRGROUP(cmap->index)) )
|
|
{
|
|
plane_group = PIXPG_24BIT_COLOR;
|
|
}
|
|
|
|
/* Move caller's data, there are 2 cases: kernel space and user space.
|
|
*/
|
|
if (softc->tc1d.flags & CG8_KERNEL_UPDATE)
|
|
{
|
|
DEBUGF(6, ("Kernel putcmap\n", 0) );
|
|
softc->tc1d.flags &= ~CG8_KERNEL_UPDATE;
|
|
BCOPY( cmap->red, softc->cmap_red, count );
|
|
BCOPY( cmap->green, softc->cmap_green, count);
|
|
BCOPY( cmap->blue, softc->cmap_blue, count );
|
|
}
|
|
else
|
|
{
|
|
DEBUGF(6, ("User putcmap, index=%x, count=%d, pg=%d\n",
|
|
index, count, plane_group) );
|
|
if ( COPYIN( cmap->red, softc->cmap_red, count ) ||
|
|
COPYIN( cmap->green, softc->cmap_green, count) ||
|
|
COPYIN( cmap->blue, softc->cmap_blue, count ) )
|
|
{
|
|
return EFAULT;
|
|
}
|
|
}
|
|
|
|
/* If there is no eight bit buffer and hardware update is not forced,
|
|
* set 8-bit index emulation color table entries for 24-bit buffer.
|
|
* (The check for the 8-bit plane group is here in case the kernel
|
|
* knows 8-bit h'ware exists, but the driver didn't export it to Sunview.)
|
|
*/
|
|
if ( !force_update && (softc->pg_enabled[PIXPG_8BIT_COLOR] == 0) &&
|
|
((plane_group==PIXPG_24BIT_COLOR) || (plane_group==PIXPG_8BIT_COLOR)) )
|
|
{
|
|
for (n_entry = 0; n_entry < count; n_entry++, index++)
|
|
{
|
|
softc->em_red[index] = softc->cmap_red[n_entry];
|
|
softc->em_green[index] = softc->cmap_green[n_entry];
|
|
softc->em_blue[index] = softc->cmap_blue[n_entry];
|
|
}
|
|
}
|
|
|
|
/* Set entries in actual Brooktree lookup tables for 8/24-bit buffer.
|
|
*/
|
|
else if ( plane_group == PIXPG_24BIT_COLOR ||
|
|
plane_group == PIXPG_8BIT_COLOR )
|
|
{
|
|
DEBUGF(6, ("Real pcmap: group=%d flags=%x",
|
|
plane_group, softc->tc1d.flags) );
|
|
DEBUGF(6, (" first = %d", index) );
|
|
DEBUGF(6, (" count = %d\n", count) );
|
|
|
|
device_reg->dacs.bt457.all_address = index;
|
|
for (n_entry = 0; n_entry < count; n_entry++)
|
|
{
|
|
device_reg->dacs.bt457.red_color = softc->cmap_red[n_entry];
|
|
device_reg->dacs.bt457.green_color = softc->cmap_green[n_entry];
|
|
device_reg->dacs.bt457.blue_color = softc->cmap_blue[n_entry];
|
|
}
|
|
}
|
|
|
|
else if (plane_group != PIXPG_OVERLAY )
|
|
{
|
|
printf("Illegal plane group %d encountered\n", plane_group);
|
|
return EINVAL;
|
|
}
|
|
|
|
/* Set entries in actual Brooktree lookup tables for monochrome overlay.
|
|
* At the same time write the shadow color map which fbiogetcmap gets
|
|
* values from. Note that our overlay map works in a different manner from
|
|
* Sun's cg8, so a translation must be done (using translate_omap data
|
|
* structure):
|
|
* Function Sun LUT index SBus TC LUT index
|
|
* -------- ------------- ------------------
|
|
* True color 0 0
|
|
* Window system foreground 1 2
|
|
* Current window foreground 2 1
|
|
* Window system background 3 3
|
|
*
|
|
* Note we only write the overlay if 24-bit enabled to get around
|
|
* a problem with cg4 emulation. Also we implement cursor color
|
|
* freezing here for true color!
|
|
*/
|
|
else if ( softc->pg_enabled[PIXPG_24BIT_COLOR] )
|
|
{
|
|
DEBUGF(6, ("Overlay pcmap: flags=%x", softc->tc1d.flags) );
|
|
DEBUGF(6, (" first = %d", index) );
|
|
DEBUGF(6, (" count = %d\n", count) );
|
|
|
|
for (n_entry = 0; n_entry < count; n_entry++, index++)
|
|
{
|
|
if ( !softc->sw_cursor_color_frozen || index != 2 )
|
|
{
|
|
device_reg->dacs.bt457.all_address = translate_omap[index];
|
|
device_reg->dacs.bt457.red_overlay =
|
|
softc->omap_red[index] = softc->cmap_red[n_entry];
|
|
device_reg->dacs.bt457.green_overlay =
|
|
softc->omap_green[index] = softc->cmap_green[n_entry];
|
|
device_reg->dacs.bt457.blue_overlay =
|
|
softc->omap_blue[index] = softc->cmap_blue[n_entry];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*"tcp_attach"
|
|
*
|
|
* Perform device specific initializations for TC or TCP frame buffer.
|
|
* (Called from cgeightattach().) This routine initializes parts of the
|
|
* per-unit data structure. In addition it maps the device's memory regions
|
|
* into virtual memory and performs hardware specific initializations.
|
|
* A number of per-unit data items have already been initialized from PROMs
|
|
* in cgeightattach().
|
|
*
|
|
* = 1 if success
|
|
* = 0 if failure
|
|
*/
|
|
static int tcp_attach(devi, softc)
|
|
struct dev_info *devi; /* -> device info structure w/node id... (rest filled here). */
|
|
SOFTC *softc; /* -> per-unit data structure to be filled in. */
|
|
{
|
|
int color; /* Index: next color to set in lut ramp. */
|
|
Tc1_Device_Map *dmap; /* Fast pointer to device register area. */
|
|
int fb_map_bytes; /* # of bytes needed to map frame buffers. */
|
|
addr_t reg; /* Virt. addr of device map(&optionally fbs)*/
|
|
register u_long *sel_addr; /* Cursor: selection memory word to init. */
|
|
register int sel_cnt; /* Index: # of words initialized in sel mem */
|
|
int sel_max; /* # of words in sel. mem. to initialize. */
|
|
|
|
/* PROCESS REMAINING PROM PARAMETERS:
|
|
*
|
|
* Pick up the device specific parameters exported by the on-board PROMs.
|
|
* Use this information to set up memory mapping characteristics of the
|
|
* board.
|
|
*/
|
|
DEBUGF(5, ("tcp_attach softc at %x\n", softc));
|
|
|
|
/* Device register area parameters:
|
|
*/
|
|
softc->dev_reg_sbus_base =
|
|
getprop(devi->devi_nodeid, "device-map-offset", 0x400000);
|
|
softc->dev_reg_mmap_offset = CG8_VADDR_DAC;
|
|
softc->dev_reg_sbus_delta = 0;
|
|
softc->dev_reg_mmap_size = ptob(btopr(NBPG));
|
|
softc->memory_map_end =
|
|
softc->dev_reg_mmap_offset + softc->dev_reg_mmap_size;
|
|
|
|
DEBUGF(5, (" dev_reg_sbus_base is %x\n", softc->dev_reg_sbus_base));
|
|
|
|
/* Monochrome frame buffer parameters:
|
|
*/
|
|
softc->fb_mono_sbus_delta =
|
|
getprop(devi->devi_nodeid, "monochrome-offset", 0x00C00000);
|
|
softc->fb_mono_sbus_delta -= softc->dev_reg_sbus_base;
|
|
softc->fb_mono_mmap_size =
|
|
getprop(devi->devi_nodeid, "monochrome-size", 1152*900/8);
|
|
softc->fb_mono_mmap_size = ptob(btopr(softc->fb_mono_mmap_size));
|
|
|
|
DEBUGF(5, ("monochrome sbus delta %x mmap offset %x size %x\n",
|
|
softc->fb_mono_sbus_delta,
|
|
0,
|
|
softc->fb_mono_mmap_size));
|
|
|
|
/* Selection memory parameters:
|
|
*/
|
|
softc->fb_sel_sbus_delta =
|
|
getprop(devi->devi_nodeid, "selection-offset", 0x00D00000);
|
|
softc->fb_sel_sbus_delta -= softc->dev_reg_sbus_base;
|
|
softc->fb_sel_mmap_size =
|
|
getprop(devi->devi_nodeid, "selection-size", 1152*900/8);
|
|
softc->fb_sel_mmap_size = ptob(btopr(softc->fb_sel_mmap_size));
|
|
|
|
DEBUGF(5, ("selection sbus delta %x mmap offset %x size %x\n",
|
|
softc->fb_sel_sbus_delta,
|
|
softc->fb_mono_mmap_size,
|
|
softc->fb_sel_mmap_size));
|
|
|
|
/* Eight bit frame buffer parameters (set them up even if don't use them):
|
|
*/
|
|
softc->fb_8bit_sbus_delta = 0x00700000 - softc->dev_reg_sbus_base;
|
|
softc->fb_8bit_mmap_size = ptob(btopr(1152*900));
|
|
|
|
DEBUGF(5, ("eight_bit sbus delta %x mmap offset %x size %x\n",
|
|
softc->fb_8bit_sbus_delta,
|
|
softc->fb_mono_mmap_size+softc->fb_sel_mmap_size,
|
|
softc->fb_8bit_mmap_size));
|
|
|
|
/* True color frame buffer parameters:
|
|
*/
|
|
softc->fb_tc_sbus_delta =
|
|
getprop(devi->devi_nodeid, "true-color-offset", 0x00800000);
|
|
softc->fb_tc_sbus_delta -= softc->dev_reg_sbus_base;
|
|
softc->fb_tc_mmap_size =
|
|
getprop(devi->devi_nodeid, "true-color-size", 1152*900*4);
|
|
softc->fb_tc_mmap_size = ptob(btopr(softc->fb_tc_mmap_size));
|
|
|
|
DEBUGF(5, ("true_color sbus delta %x size %x\n",
|
|
softc->fb_tc_sbus_delta, softc->fb_tc_mmap_size));
|
|
|
|
/* Video enable memory parameters (set them up even if we don't use them):
|
|
*/
|
|
softc->fb_video_sbus_delta = 0x00E00000 - softc->dev_reg_sbus_base;
|
|
softc->fb_video_mmap_size = ptob(btopr(1152*900/8));
|
|
|
|
DEBUGF(5, ("video_enable sbus delta %x size %x\n",
|
|
softc->fb_video_sbus_delta, softc->fb_video_mmap_size));
|
|
|
|
|
|
|
|
/* ALLOCATE SPACE IN KERNEL VIRTUAL MEMORY FOR THE DEVICE REGISTERS AND
|
|
* MONOCHROME OPERATIONS, BUILD THE TABLE USED FOR USER SPACE MAPPING
|
|
*
|
|
* Allocate space in virtual memory for the device register area (and
|
|
* possibly the frame buffers.) Remember the virtual address of the device
|
|
* register area, and its physical address, which will be used by
|
|
* cgeightmmap as the base mapping for all physical pages.
|
|
*
|
|
* #### The |= 18000000 kludge is because the 4.1.1 code on a SS2 does
|
|
* not return the correct address for the Sbus slot! (Bug 1046449)
|
|
* This can be removed when that is fixed.
|
|
*/
|
|
# if NWIN > 0
|
|
fb_map_bytes = softc->fb_mono_mmap_size + softc->fb_sel_mmap_size;
|
|
if ( softc->pg_possible[PIXPG_8BIT_COLOR] )
|
|
{
|
|
fb_map_bytes += softc->fb_8bit_mmap_size;
|
|
}
|
|
# else NWIN > 0
|
|
fb_map_bytes = 0;
|
|
# endif NWIN > 0
|
|
|
|
#ifdef sun4c
|
|
(u_int)devi->devi_reg[0].reg_addr |= 0x18000000; /* SEE NOTE ABOVE */
|
|
#endif sun4c
|
|
if ( !(reg = (addr_t)map_regs(
|
|
(addr_t)(devi->devi_reg[0].reg_addr + softc->dev_reg_sbus_base),
|
|
(u_int)(fb_map_bytes + softc->dev_reg_mmap_size),
|
|
devi->devi_reg[0].reg_bustype)))
|
|
{
|
|
return 0;
|
|
}
|
|
softc->device_reg = (Tc1_Device_Map *) reg;
|
|
dmap = softc->device_reg;
|
|
softc->basepage = fbgetpage(reg);
|
|
|
|
DEBUGF(5, ("tcp_attach reg=0x%x basepage=0x%x (0x%x)\n",
|
|
(u_int)reg, ptob(softc->basepage), softc->basepage));
|
|
|
|
/* Default operations to emulate a Sun CG8 card (this may be modified later
|
|
* via the PIPIO_S_EMULATION_MODE ioctl.)
|
|
* Determine if there is a pip and/or eight bit memory present. If this is
|
|
* an old style frame buffer set the register to enable use of selection
|
|
* memory.
|
|
*/
|
|
softc->pg_enabled[PIXPG_8BIT_COLOR] = 0;
|
|
|
|
#ifndef NO_PIP
|
|
if ( softc->pg_possible[PIXPG_VIDEO_ENABLE] )
|
|
{
|
|
if ( (dmap->control_status1 & TCP_CSR1_NO_PIP) == 0 )
|
|
{
|
|
softc->pip_on_off_semaphore = 0;
|
|
pip_off(softc, 0);
|
|
}
|
|
else
|
|
{
|
|
softc->pg_possible[PIXPG_VIDEO_ENABLE] = 0;
|
|
softc->pg_enabled[PIXPG_VIDEO_ENABLE] = 0;
|
|
}
|
|
}
|
|
#endif !NO_PIP
|
|
if ( softc->fb_model == RASTEROPS_TC )
|
|
{
|
|
dmap->control_status |= TC1_SELECTION_ENABLE;
|
|
}
|
|
|
|
/* For the kernel's use map in the monochrome frame buffer, selection
|
|
* memory, and if present the eight bit memory after the device registers.
|
|
* For each buffer calculate its virtual address, and place this
|
|
* information into the device-dependent structure. Note in the kernel the
|
|
* the device register appears before the frame buffer so we are constantly
|
|
* adding in NBPG to the virtual offsets. In user mode the opposite is
|
|
* true, because of the way cg8_make maps things.
|
|
*/
|
|
#if NWIN > 0
|
|
if (fb_map_bytes)
|
|
{
|
|
fbmapin(reg + NBPG,
|
|
(int) (softc->basepage + btop(softc->fb_mono_sbus_delta)),
|
|
softc->fb_mono_mmap_size);
|
|
softc->fb_mono = (u_char *)reg + NBPG;
|
|
|
|
DEBUGF(5, ("tcp_attach fb_mono= 0x%x/0x%x (0x%x)\n",
|
|
(u_int) softc->fb_mono,
|
|
fbgetpage((addr_t) softc->fb_mono) << PGSHIFT,
|
|
fbgetpage((addr_t) softc->fb_mono)));
|
|
|
|
|
|
fbmapin(reg + NBPG + softc->fb_mono_mmap_size,
|
|
(int) (softc->basepage + btop(softc->fb_sel_sbus_delta)),
|
|
softc->fb_sel_mmap_size);
|
|
softc->fb_sel = (u_char *)reg + NBPG + softc->fb_mono_mmap_size;
|
|
|
|
DEBUGF(5, ("tcp_attach fb_sel= 0x%x/0x%x (0x%x)\n",
|
|
(u_int) softc->fb_sel,
|
|
fbgetpage((addr_t) softc->fb_sel) << PGSHIFT,
|
|
fbgetpage((addr_t) softc->fb_sel)));
|
|
|
|
if ( softc->pg_possible[PIXPG_8BIT_COLOR] )
|
|
{
|
|
fbmapin(reg+NBPG+softc->fb_mono_mmap_size+softc->fb_sel_mmap_size,
|
|
(int) (softc->basepage + btop(softc->fb_8bit_sbus_delta)),
|
|
softc->fb_8bit_mmap_size);
|
|
softc->fb_8bit = (u_char *)reg + NBPG + softc->fb_mono_mmap_size +
|
|
softc->fb_sel_mmap_size;
|
|
|
|
DEBUGF(5, ("tcp_attach fb_8bit= 0x%x/0x%x (0x%x)\n",
|
|
(u_int) softc->fb_8bit,
|
|
fbgetpage((addr_t) softc->fb_8bit) << PGSHIFT,
|
|
fbgetpage((addr_t) softc->fb_8bit)));
|
|
}
|
|
}
|
|
|
|
#endif NWIN > 0
|
|
|
|
/* Build the memory mapping information used to map in the various frame
|
|
* buffers in user (process) space.
|
|
*/
|
|
x_build_mmap_info(softc);
|
|
|
|
|
|
|
|
/* INITIALIZE RAMDACs AND SELECTION MEMORY IN PREPARATION FOR WINDOW USAGE
|
|
*
|
|
* Before initializing the Brooktree's make sure the selection memory
|
|
* indicates that the monochrome plane is visible. This is necessary
|
|
* because we are about to enable the selection memory as an input into the
|
|
* overlay port on the RAMDACs.
|
|
*/
|
|
#if NWIN > 0
|
|
sel_max = 900*softc->linebytes1 / sizeof(u_long);
|
|
for(sel_addr=(u_long *)softc->fb_sel, sel_cnt=0; sel_cnt<sel_max; sel_cnt++)
|
|
{
|
|
*sel_addr++ = 0xffffffff;
|
|
}
|
|
#endif NWIN > 0
|
|
|
|
/* Initialize the 3 Brooktree 457s for:
|
|
* (1) 4:1 multiplexing (since we are not 1280x1024)
|
|
* (2) Transparent overlay for overlay color 0.
|
|
* (3) Display the overlay plane
|
|
* Enable read and write to all planes, turn off blinking, and set
|
|
* control register.
|
|
*/
|
|
DEBUGF(5, ("TCONE: Initializing Brooktrees\n") );
|
|
|
|
dmap->dacs.bt457.all_address = BT457_COMMAND;
|
|
dmap->dacs.bt457.all_control = 0x43;
|
|
dmap->dacs.bt457.all_address = BT457_READ_MASK;
|
|
dmap->dacs.bt457.all_control = 0xff;
|
|
dmap->dacs.bt457.all_address = BT457_BLINK_MASK;
|
|
dmap->dacs.bt457.all_control = 0;
|
|
dmap->dacs.bt457.all_address = BT457_CONTROL;
|
|
dmap->dacs.bt457.all_control = 0;
|
|
|
|
/* Initialize overlay plane color map and load Brooktree 457's as a group
|
|
* with that map. (See tc_putcmap routine below for description of this
|
|
* funny mapping.)
|
|
*/
|
|
dmap->dacs.bt457.all_address = 0;
|
|
dmap->dacs.bt457.all_overlay = /* Unused, this is transparency value! */
|
|
softc->omap_red[0] =
|
|
softc->omap_green[0] =
|
|
softc->omap_blue[0] =
|
|
0x00;
|
|
dmap->dacs.bt457.all_address = 2;
|
|
dmap->dacs.bt457.all_overlay = /* Window system background: white guardian*/
|
|
softc->omap_red[1] =
|
|
softc->omap_green[1] =
|
|
softc->omap_blue[1] =
|
|
0xff;
|
|
dmap->dacs.bt457.all_address = 1;
|
|
dmap->dacs.bt457.all_overlay = /* Current window foreground. */
|
|
softc->omap_red[2] =
|
|
softc->omap_green[2] =
|
|
softc->omap_blue[2] =
|
|
0xff;
|
|
dmap->dacs.bt457.all_address = 3;
|
|
dmap->dacs.bt457.all_overlay = /* Window system foreground: black guardian*/
|
|
softc->omap_red[3] =
|
|
softc->omap_green[3] =
|
|
softc->omap_blue[3] =
|
|
0x00;
|
|
softc->sw_cursor_color_frozen = 0; /*Allow cursor color to be set normally*/
|
|
|
|
/* Load Brooktree 457's as a group with a linear ramp for the 24-bit true
|
|
* color frame buffer.
|
|
*/
|
|
for (color=0, dmap->dacs.bt457.all_address=0; color < TC_CMAP_SIZE; color++)
|
|
{
|
|
dmap->dacs.bt457.all_color = color;
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*"tcs_attach"
|
|
*
|
|
* Perform device specific initializations for TCS frame buffer.
|
|
* (Called from cgeightattach().) This routine initializes parts of the
|
|
* per-unit data structure. In addition it maps the device's memory regions
|
|
* into virtual memory and performs hardware specific initializations.
|
|
* A number of per-unit data items have already been initialized from PROMs
|
|
* in cgeightattach().
|
|
*
|
|
* = 1 if success
|
|
* = 0 if failure
|
|
*/
|
|
static int tcs_attach(devi, softc)
|
|
struct dev_info *devi; /* -> device info struct w/node id...(rest filled here) */
|
|
SOFTC *softc; /* -> per-unit data structure to be filled in. */
|
|
{
|
|
int color; /* Index: next color to set in lut ramp. */
|
|
Tcs_Device_Map *dmap; /* Fast pointer to device register area. */
|
|
int fb_map_bytes; /* # of bytes needed to map frame buffers. */
|
|
addr_t reg; /* Virt addr of device map(&optionally fbs) */
|
|
register u_long *sel_addr; /* Cursor: selection memory word to init. */
|
|
register int sel_cnt; /* Index: # of sel. mem. words initialized */
|
|
int sel_max; /* # of words in selection memory to init. */
|
|
|
|
/* PROCESS REMAINING PROM PARAMETERS:
|
|
*
|
|
* Pick up the device specific parameters exported by the on-board PROMs.
|
|
* Use this information to set up memory mapping characteristics of the
|
|
* board.
|
|
*/
|
|
DEBUG_LEVEL(5);
|
|
DEBUGF(5, ("tcs_attach softc at %x\n", softc));
|
|
|
|
/* Device register area parameters:
|
|
*/
|
|
softc->dev_reg_sbus_base =
|
|
getprop(devi->devi_nodeid, "device-map-offset", 0x00040000);
|
|
softc->dev_reg_mmap_offset = CG8_VADDR_DAC;
|
|
softc->dev_reg_sbus_delta = 0;
|
|
softc->dev_reg_mmap_size = ptob(btopr(NBPG));
|
|
softc->memory_map_end = softc->dev_reg_mmap_offset+softc->dev_reg_mmap_size;
|
|
|
|
|
|
DEBUGF(5, (" dev_reg_sbus_base is %x\n", softc->dev_reg_sbus_base));
|
|
|
|
/* Monochrome frame buffer parameters:
|
|
*/
|
|
softc->fb_mono_sbus_delta =
|
|
getprop(devi->devi_nodeid, "monochrome-offset", 0x00100000);
|
|
softc->fb_mono_sbus_delta -= softc->dev_reg_sbus_base;
|
|
softc->fb_mono_mmap_size =
|
|
getprop(devi->devi_nodeid, "monochrome-size", 0x40000);
|
|
softc->fb_mono_mmap_size = ptob(btopr(softc->fb_mono_mmap_size));
|
|
|
|
DEBUGF(5, ("monochrome sbus delta %x mmap offset %x size %x\n",
|
|
softc->fb_mono_sbus_delta,
|
|
0,
|
|
softc->fb_mono_mmap_size));
|
|
|
|
/* Selection memory parameters:
|
|
*/
|
|
softc->fb_sel_sbus_delta =
|
|
getprop(devi->devi_nodeid, "selection-offset", 0x00140000);
|
|
softc->fb_sel_sbus_delta -= softc->dev_reg_sbus_base;
|
|
softc->fb_sel_mmap_size =
|
|
getprop(devi->devi_nodeid, "selection-size", 0x40000);
|
|
softc->fb_sel_mmap_size = ptob(btopr(softc->fb_sel_mmap_size));
|
|
|
|
DEBUGF(5, ("selection sbus delta %x mmap offset %x size %x\n",
|
|
softc->fb_sel_sbus_delta,
|
|
softc->fb_mono_mmap_size,
|
|
softc->fb_sel_mmap_size));
|
|
|
|
/* Eight bit frame buffer parameters (set them up even if don't use them):
|
|
*/
|
|
softc->fb_8bit_sbus_delta = 0x00180000 - softc->dev_reg_sbus_base;
|
|
softc->fb_8bit_mmap_size = ptob(btopr(0x80000));
|
|
|
|
softc->pg_possible[PIXPG_8BIT_COLOR] = 0;
|
|
|
|
DEBUGF(5, ("eight_bit sbus delta %x mmap offset %x size %x\n",
|
|
softc->fb_8bit_sbus_delta,
|
|
softc->fb_mono_mmap_size + softc->fb_sel_mmap_size,
|
|
softc->fb_8bit_mmap_size));
|
|
|
|
/* True color frame buffer parameters:
|
|
*/
|
|
softc->fb_tc_sbus_delta =
|
|
getprop(devi->devi_nodeid, "true-color-offset", 0x00200000);
|
|
softc->fb_tc_sbus_delta -= softc->dev_reg_sbus_base;
|
|
softc->fb_tc_mmap_size =
|
|
getprop(devi->devi_nodeid, "true-color-size", 0x200000);
|
|
softc->fb_tc_mmap_size = ptob(btopr(softc->fb_tc_mmap_size));
|
|
|
|
DEBUGF(5, ("true_color sbus delta %x size %x\n",
|
|
softc->fb_tc_sbus_delta,
|
|
softc->fb_tc_mmap_size));
|
|
|
|
|
|
/* ALLOCATE SPACE IN KERNEL VIRTUAL MEMORY FOR THE DEVICE REGISTERS AND
|
|
* MONOCHROME OPERATIONS
|
|
*
|
|
* Allocate space in virtual memory for the device register area (and
|
|
* possibly the frame buffers.) Remember the virtual address of the device
|
|
* register area, and its physical address, which will be used by
|
|
* cgeightmmap as the base mapping for all physical pages.
|
|
*
|
|
* #### The |= 18000000 kludge is because the 4.1.1 code on a SS2 does
|
|
* not return the correct address for the Sbus slot! (Bug 1046449)
|
|
* This can be removed when that is fixed.
|
|
*/
|
|
# if NWIN > 0
|
|
fb_map_bytes = softc->fb_mono_mmap_size + softc->fb_sel_mmap_size;
|
|
# else NWIN > 0
|
|
fb_map_bytes = 0;
|
|
# endif NWIN > 0
|
|
#ifdef sun4c
|
|
(u_int)devi->devi_reg[0].reg_addr |= 0x18000000; /* SEE NOTE ABOVE */
|
|
#endif sun4c
|
|
if ( !(reg = (addr_t)map_regs(
|
|
(addr_t)(devi->devi_reg[0].reg_addr + softc->dev_reg_sbus_base),
|
|
(u_int)(fb_map_bytes + softc->dev_reg_mmap_size),
|
|
devi->devi_reg[0].reg_bustype)))
|
|
{
|
|
return 0;
|
|
}
|
|
softc->device_tcs = (Tcs_Device_Map *) reg;
|
|
dmap = softc->device_tcs;
|
|
softc->basepage = fbgetpage(reg);
|
|
|
|
DEBUGF(5, ("tcs_attach reg=0x%x basepage=0x%x (0x%x)\n",
|
|
(u_int)reg, ptob(softc->basepage), softc->basepage));
|
|
|
|
/* Default operations to emulate a Sun CG8 card (this may be modified later
|
|
* via the PIPIO_S_EMULATION_MODE ioctl.)
|
|
*/
|
|
softc->pg_enabled[PIXPG_8BIT_COLOR] = 0;
|
|
|
|
/* For the kernel's use map in the monochrome frame buffer, and selection
|
|
* memory after the device registers. For each buffer calculate its virtual
|
|
* address, and place this information into the device-dependent structure.
|
|
* Note in the kernel the the device register appears before the frame
|
|
* buffer so we are constantly adding in NBPG to the virtual offsets. In
|
|
* user mode the opposite is true, because of the way cg8_make maps things.
|
|
*/
|
|
#if NWIN > 0
|
|
if (fb_map_bytes)
|
|
{
|
|
fbmapin(reg + NBPG,
|
|
(int) (softc->basepage + btop(softc->fb_mono_sbus_delta)),
|
|
softc->fb_mono_mmap_size);
|
|
softc->fb_mono = (u_char *)reg + NBPG;
|
|
|
|
DEBUGF(5, ("tcs_attach fb_mono= 0x%x/0x%x (0x%x)\n",
|
|
(u_int) softc->fb_mono,
|
|
fbgetpage((addr_t) softc->fb_mono) << PGSHIFT,
|
|
fbgetpage((addr_t) softc->fb_mono)));
|
|
|
|
|
|
fbmapin(reg + NBPG + softc->fb_mono_mmap_size,
|
|
(int) (softc->basepage + btop(softc->fb_sel_sbus_delta)),
|
|
softc->fb_sel_mmap_size);
|
|
softc->fb_sel = (u_char *)reg + NBPG + softc->fb_mono_mmap_size;
|
|
|
|
DEBUGF(5, ("tcs_attach fb_sel= 0x%x/0x%x (0x%x)\n",
|
|
(u_int) softc->fb_sel,
|
|
fbgetpage((addr_t) softc->fb_sel) << PGSHIFT,
|
|
fbgetpage((addr_t) softc->fb_sel)));
|
|
|
|
}
|
|
|
|
#endif NWIN > 0
|
|
|
|
/* Build the memory mapping information used to map in the various frame
|
|
* buffers in user (process) space.
|
|
*/
|
|
x_build_mmap_info(softc);
|
|
|
|
|
|
/* INITIALIZE VENUS CHIPS, RAMDAC AND SELECTION MEMORY IN PREPARATION FOR
|
|
* WINDOW USAGE
|
|
*
|
|
* Initialize venus chips to turn on operation of Brooktree, memory timing,
|
|
* etc. Use the switch settings if this is not a model a board.
|
|
*
|
|
* Before initializing the Brooktree make sure the selection memory
|
|
* indicates that the monochrome plane is visible. This is necessary
|
|
* because we are about to enable the selection memory as an input into the
|
|
* overlay port on the RAMDACs.
|
|
*/
|
|
if ( softc->device_tcs->tc_venus.io_general & VENUS_TCS_MODEL_A )
|
|
{
|
|
tcs_init_native(softc);
|
|
}
|
|
else
|
|
{
|
|
switch( softc->device_tcs->tc_venus.io_general & VENUS_TIMING_MASK )
|
|
{
|
|
default:
|
|
printf("Unknown switch setting: defaulting to native timing.\n");
|
|
case VENUS_TIMING_NATIVE: tcs_init_native(softc); break;
|
|
case VENUS_TIMING_NTSC: tcs_init_ntsc(softc); break;
|
|
case VENUS_TIMING_PAL: tcs_init_pal(softc); break;
|
|
}
|
|
softc->linebytes1 = softc->width / 8;
|
|
softc->linebytes32 = softc->width * 4;
|
|
}
|
|
|
|
sel_max = softc->width*softc->linebytes1 / sizeof(u_long);
|
|
for(sel_addr=(u_long *)softc->fb_sel, sel_cnt=0; sel_cnt<sel_max; sel_cnt++)
|
|
{
|
|
*sel_addr++ = 0xffffffff;
|
|
}
|
|
|
|
/* Initialize the Brooktree 473:
|
|
*/
|
|
DEBUGF(5, ("tcs_attach: Initializing Brooktree 473\n") );
|
|
|
|
dmap->dac.control = 0x30; /* 8-bit pixels, NTSC timing (IRE = 7.5) */
|
|
dmap->dac.read_mask = 0xff;
|
|
|
|
/* Initialize overlay plane color map.
|
|
*/
|
|
dmap->dac.overlay_write_addr = 0; /* Overlay colors: */
|
|
dmap->dac.overlay = 0x00; /* 00: transparent pass-through. */
|
|
dmap->dac.overlay = 0x00; /* ... */
|
|
dmap->dac.overlay = 0x00; /* ... */
|
|
dmap->dac.overlay = 0xff; /* 01: true color cursor value: white. */
|
|
dmap->dac.overlay = 0xff; /* ... */
|
|
dmap->dac.overlay = 0xff; /* ... */
|
|
dmap->dac.overlay = 0xff; /* 10: window background color: white. */
|
|
dmap->dac.overlay = 0xff; /* ... */
|
|
dmap->dac.overlay = 0xff; /* ... */
|
|
dmap->dac.overlay = 0x00; /* 11: window foreground color: black. */
|
|
dmap->dac.overlay = 0x00; /* ... */
|
|
dmap->dac.overlay = 0x00; /* ... */
|
|
|
|
softc->omap_red[0] = softc->omap_green[0] = softc->omap_blue[0] = 0x00;
|
|
softc->omap_red[1] = softc->omap_green[1] = softc->omap_blue[1] = 0xff;
|
|
softc->omap_red[2] = softc->omap_green[2] = softc->omap_blue[2] = 0xff;
|
|
softc->omap_red[3] = softc->omap_green[3] = softc->omap_blue[3] = 0x00;
|
|
|
|
/* Load Brooktree 473 as a group with a linear ramp for the 24-bit true
|
|
* color frame buffer. Use cmap_xxx as a shadow table since we load the
|
|
* entire lut in tcs_putcmap(). (See note 1 in tcs_putcmap.)
|
|
*/
|
|
for (color = 0, dmap->dac.ram_write_addr = 0; color < TC_CMAP_SIZE; color++)
|
|
{
|
|
softc->cmap_red[color] = dmap->dac.color = color;
|
|
softc->cmap_green[color] = dmap->dac.color = color;
|
|
softc->cmap_blue[color] = dmap->dac.color = color;
|
|
}
|
|
|
|
DEBUG_LEVEL(0);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*"tcs_init_native"
|
|
*
|
|
* Initialize venus chips on SBus TCS Card to operate at
|
|
* Apple 13" monitor scan rates (60Hz non-interlaced, 640 x 480.)
|
|
*/
|
|
tcs_init_native(softc)
|
|
SOFTC *softc; /* characteristics for our unit. */
|
|
{
|
|
Tcs_Device_Map *dmap; /* -> device register area on TCS card. */
|
|
u_int io_conf; /* Value to load into io config register. */
|
|
u_int io_gen; /* Value to load into io general register. */
|
|
|
|
dmap = softc->device_tcs;
|
|
softc->timing_regimen = NATIVE_TIMING;
|
|
softc->width = 640;
|
|
softc->height = 480;
|
|
softc->linebytes1 = softc->width / 8;
|
|
softc->linebytes8 = softc->width;
|
|
softc->linebytes32 = softc->width * 4;
|
|
|
|
io_gen = (dmap->tc_venus.io_general & VENUS_TCS_MODEL_A) ? 0x001c : 0x781c;
|
|
io_conf = (dmap->tc_venus.io_general & VENUS_TCS_MODEL_A) ? 0x00df : 0x1fdf;
|
|
|
|
/*
|
|
* Initialize venus chip 0 which affects Brooktree operations and color
|
|
* buffer operations. Configure the system as a 24-bit true color card.
|
|
*/
|
|
dmap->tc_venus.control1 = 0x00;
|
|
dmap->tc_venus.control2 = 0x00;
|
|
dmap->tc_venus.control3 = 0x00;
|
|
dmap->tc_venus.control4 = 0x00;
|
|
dmap->tc_venus.refresh_interval = 0x70;
|
|
dmap->tc_venus.control1 = 0x11;
|
|
|
|
dmap->tc_venus.io_general = io_gen;
|
|
dmap->tc_venus.io_config = io_conf;
|
|
|
|
dmap->tc_venus.display_start = 0x00000000;
|
|
dmap->tc_venus.half_row_incr = 0x00000100;
|
|
dmap->tc_venus.display_pitch = 0x00000140;
|
|
dmap->tc_venus.cas_mask = 0x7f;
|
|
dmap->tc_venus.horiz_latency = 0x00;
|
|
|
|
dmap->tc_venus.horiz_end_sync = 0x000c;
|
|
dmap->tc_venus.horiz_end_blank = 0x0024;
|
|
dmap->tc_venus.horiz_start_blank = 0x00c4;
|
|
dmap->tc_venus.horiz_total = 0x00d4;
|
|
dmap->tc_venus.horiz_half_line = 0x0000;
|
|
dmap->tc_venus.horiz_count_load = 0x0000;
|
|
|
|
dmap->tc_venus.vert_end_sync = 0x02;
|
|
dmap->tc_venus.vert_end_blank = 0x29;
|
|
dmap->tc_venus.vert_start_blank = 0x0209;
|
|
dmap->tc_venus.vert_total = 0x020c;
|
|
dmap->tc_venus.vert_count_load = 0x0000;
|
|
dmap->tc_venus.vert_interrupt = 0x020a;
|
|
|
|
dmap->tc_venus.y_zoom = 0x01;
|
|
dmap->tc_venus.soft_register = 0x00;
|
|
|
|
dmap->tc_venus.io_general = io_gen & ~VENUS_SOFT_RESET;
|
|
dmap->tc_venus.io_general = io_gen;
|
|
|
|
dmap->tc_venus.control3 = 0x73;
|
|
dmap->tc_venus.control1 = 0xf1; /* Enable video. */
|
|
|
|
/*
|
|
* Initialize venus chip 1 which affects 1-bit monochrome and selection
|
|
* memory operations.
|
|
*/
|
|
dmap->mono_venus.control1 = 0x00;
|
|
dmap->mono_venus.control2 = 0x00;
|
|
dmap->mono_venus.control3 = 0x00;
|
|
dmap->mono_venus.control4 = 0x00;
|
|
dmap->mono_venus.refresh_interval = 0x70; /* Set refresh interval. */
|
|
dmap->mono_venus.control1 = 0x13;
|
|
|
|
dmap->mono_venus.io_config = 0x00;
|
|
dmap->mono_venus.display_start = 0x00000000;
|
|
dmap->mono_venus.half_row_incr = 0x00000080;
|
|
dmap->mono_venus.display_pitch = 0x00000050;
|
|
dmap->mono_venus.cas_mask = 0x3f;
|
|
dmap->mono_venus.horiz_latency = 0x00;
|
|
|
|
dmap->mono_venus.horiz_end_sync = 0x000c;
|
|
dmap->mono_venus.horiz_end_blank = 0x0024;
|
|
dmap->mono_venus.horiz_start_blank = 0x00c4;
|
|
dmap->mono_venus.horiz_total = 0x00d4;
|
|
dmap->mono_venus.horiz_half_line = 0x0000;
|
|
dmap->mono_venus.horiz_count_load = 0x0000;
|
|
|
|
dmap->mono_venus.vert_end_sync = 0x02;
|
|
dmap->mono_venus.vert_end_blank = 0x29;
|
|
dmap->mono_venus.vert_start_blank = 0x0209;
|
|
dmap->mono_venus.vert_total = 0x020c;
|
|
dmap->mono_venus.vert_count_load = 0x0000;
|
|
dmap->mono_venus.vert_interrupt = 0x0000;
|
|
|
|
dmap->mono_venus.y_zoom = 0x01;
|
|
dmap->mono_venus.soft_register = 0xf0;
|
|
|
|
dmap->mono_venus.control3 = 0xf3;
|
|
dmap->mono_venus.control1 = 0xf3;
|
|
}
|
|
|
|
/*"tcs_init_ntsc"
|
|
*
|
|
* Initialize venus chips on SBus TCS Card to operate at NTSC scan rates.
|
|
* (30Hz interlaced 640 x 480.)
|
|
* If a genlock device is connected external (genlock) sync will be used.
|
|
*/
|
|
tcs_init_ntsc(softc)
|
|
SOFTC *softc; /* characteristics for our unit. */
|
|
{
|
|
Tcs_Device_Map *dmap; /* -> device register area on TCS card. */
|
|
u_int io_conf; /* Value to load into io config register. */
|
|
u_int io_gen; /* Value to load into io general register. */
|
|
|
|
dmap = softc->device_tcs;
|
|
softc->timing_regimen = NTSC_TIMING;
|
|
softc->width = 640;
|
|
softc->height = 480;
|
|
softc->linebytes1 = softc->width / 8;
|
|
softc->linebytes8 = softc->width;
|
|
softc->linebytes32 = softc->width * 4;
|
|
|
|
if ( dmap->tc_venus.io_general & VENUS_TCS_MODEL_A )
|
|
{
|
|
io_gen = ( dmap->tc_venus.io_general & VENUS_NO_GENLOCK ) ?
|
|
0x007c : 0x0074;
|
|
io_conf = 0x00df;
|
|
}
|
|
else
|
|
{
|
|
io_gen = ( dmap->tc_venus.io_general & VENUS_NO_GENLOCK ) ?
|
|
0x78bc : 0x78f4;
|
|
io_conf = 0x1fdf;
|
|
}
|
|
|
|
/*
|
|
* Initialize venus chip 0 which affects Brooktree operations and color
|
|
* buffer operations. Configure the system as a 24-bit true color card.
|
|
*/
|
|
dmap->tc_venus.control1 = 0x00;
|
|
dmap->tc_venus.control2 = 0x00;
|
|
dmap->tc_venus.control3 = 0x00;
|
|
dmap->tc_venus.control4 = 0x00;
|
|
dmap->tc_venus.refresh_interval = 0x70; /* Set refresh interval. */
|
|
dmap->tc_venus.control1 = 0x11;
|
|
dmap->tc_venus.control2 = 0x00;
|
|
dmap->tc_venus.control3 = 0x7b;
|
|
dmap->tc_venus.control4 = 0x00;
|
|
|
|
dmap->tc_venus.io_general = io_gen;
|
|
dmap->tc_venus.io_config = io_conf;
|
|
|
|
dmap->tc_venus.display_start = 0x00000000;
|
|
dmap->tc_venus.half_row_incr = 0x00000100;
|
|
dmap->tc_venus.display_pitch = 0x00000140;
|
|
dmap->tc_venus.cas_mask = 0x7f;
|
|
dmap->tc_venus.horiz_latency = 0x00;
|
|
|
|
dmap->tc_venus.horiz_end_sync = 0x000d;
|
|
dmap->tc_venus.horiz_half_line = 0x0060;
|
|
dmap->tc_venus.horiz_count_load = 0x0000;
|
|
dmap->tc_venus.vert_end_sync = 0x02;
|
|
dmap->tc_venus.vert_end_blank = 0x12;
|
|
dmap->tc_venus.vert_start_blank = 0x0102;
|
|
dmap->tc_venus.vert_count_load = 0x0000;
|
|
dmap->tc_venus.vert_interrupt = 0x0103;
|
|
if ( dmap->tc_venus.io_general & VENUS_NO_GENLOCK )
|
|
{
|
|
dmap->tc_venus.horiz_end_blank = 0x001c;
|
|
dmap->tc_venus.horiz_start_blank = 0x00bc;
|
|
dmap->tc_venus.horiz_total = 0x00c1;
|
|
dmap->tc_venus.vert_total = 0x0105;
|
|
}
|
|
else
|
|
{
|
|
dmap->tc_venus.horiz_end_blank = 0x001b;
|
|
dmap->tc_venus.horiz_start_blank = 0x00bb;
|
|
dmap->tc_venus.horiz_total = 0x00ff;
|
|
dmap->tc_venus.vert_total = 0x01ff;
|
|
}
|
|
|
|
dmap->tc_venus.y_zoom = 0x01;
|
|
dmap->tc_venus.soft_register = 0xf0;
|
|
|
|
dmap->tc_venus.io_general = io_gen & ~VENUS_SOFT_RESET;
|
|
dmap->tc_venus.io_general = io_gen;
|
|
|
|
if ( dmap->tc_venus.io_general & VENUS_NO_GENLOCK )
|
|
{
|
|
dmap->tc_venus.control3 = 0x7b;
|
|
dmap->tc_venus.control1 = 0xf9;
|
|
}
|
|
else
|
|
{
|
|
dmap->tc_venus.control3 = 0xfb;
|
|
dmap->tc_venus.control1 = 0xf1;
|
|
}
|
|
|
|
/*
|
|
* Initialize venus chip 1 which affects 1-bit monochrome and selection
|
|
* memory operations.
|
|
*/
|
|
dmap->mono_venus.control1 = 0x00;
|
|
dmap->mono_venus.control2 = 0x00;
|
|
dmap->mono_venus.control3 = 0x00;
|
|
dmap->mono_venus.control4 = 0x00;
|
|
dmap->mono_venus.refresh_interval = 0x70; /* Set refresh interval. */
|
|
dmap->mono_venus.control1 = 0x13;
|
|
dmap->mono_venus.io_config = 0x0000;
|
|
|
|
dmap->mono_venus.display_start = 0x00000000;
|
|
dmap->mono_venus.half_row_incr = 0x00000080;
|
|
dmap->mono_venus.display_pitch = 0x00000050;
|
|
dmap->mono_venus.cas_mask = 0x3f;
|
|
dmap->mono_venus.horiz_latency = 0x00;
|
|
|
|
dmap->mono_venus.horiz_end_sync = 0x000d;
|
|
dmap->mono_venus.horiz_end_blank = 0x001b;
|
|
dmap->mono_venus.horiz_start_blank = 0x00bb;
|
|
dmap->mono_venus.horiz_total = 0x00ff;
|
|
dmap->mono_venus.horiz_half_line = 0x0000;
|
|
dmap->mono_venus.horiz_count_load = 0x0000;
|
|
|
|
dmap->mono_venus.vert_end_sync = 0x02;
|
|
dmap->mono_venus.vert_end_blank = 0x12;
|
|
dmap->mono_venus.vert_start_blank = 0x0102;
|
|
dmap->mono_venus.vert_total = 0x01ff;
|
|
dmap->mono_venus.vert_count_load = 0x0000;
|
|
dmap->mono_venus.vert_interrupt = 0x0000;
|
|
|
|
dmap->mono_venus.y_zoom = 0x01;
|
|
dmap->mono_venus.soft_register = 0xf0;
|
|
|
|
dmap->mono_venus.control3 = 0xfb;
|
|
if ( dmap->tc_venus.io_general & VENUS_NO_GENLOCK )
|
|
{
|
|
dmap->mono_venus.control1 = 0xfb;
|
|
}
|
|
else
|
|
{
|
|
dmap->mono_venus.control1 = 0xf3;
|
|
}
|
|
}
|
|
|
|
/*"tcs_init_pal"
|
|
*
|
|
* Initialize venus chips on SBus TCS Card to operate at PAL scan rates.
|
|
* (25Hz interlaced 768 x 592.)
|
|
* If a genlock device is connected external (genlock) sync will be used.
|
|
*/
|
|
tcs_init_pal(softc)
|
|
SOFTC *softc; /* characteristics for our unit. */
|
|
{
|
|
Tcs_Device_Map *dmap; /* -> device register area on TCS card. */
|
|
u_int io_conf; /* Value to load into io config register. */
|
|
u_int io_gen; /* Value to load into io general register. */
|
|
|
|
dmap = softc->device_tcs;
|
|
softc->timing_regimen = PAL_TIMING;
|
|
softc->width = 768;
|
|
softc->height = 592;
|
|
softc->linebytes1 = softc->width / 8;
|
|
softc->linebytes8 = softc->width;
|
|
softc->linebytes32 = softc->width * 4;
|
|
|
|
if ( dmap->tc_venus.io_general & VENUS_TCS_MODEL_A )
|
|
{
|
|
io_gen = ( dmap->tc_venus.io_general & VENUS_NO_GENLOCK ) ?
|
|
0x00bc : 0x00b4;
|
|
io_conf = 0x00df;
|
|
}
|
|
else
|
|
{
|
|
io_gen = ( dmap->tc_venus.io_general & VENUS_NO_GENLOCK ) ?
|
|
0x787c : 0x78f4;
|
|
io_conf = 0x1fdf;
|
|
}
|
|
|
|
/*
|
|
* Initialize venus chip 0 which affects Brooktree operations and color
|
|
* buffer operations. Configure the system as a 24-bit true color card.
|
|
*/
|
|
dmap->tc_venus.control1 = 0x00;
|
|
dmap->tc_venus.control2 = 0x00;
|
|
dmap->tc_venus.control3 = 0x00;
|
|
dmap->tc_venus.control4 = 0x00;
|
|
dmap->tc_venus.refresh_interval = 0x70;
|
|
dmap->tc_venus.control1 = 0x11;
|
|
dmap->tc_venus.control2 = 0x00;
|
|
dmap->tc_venus.control3 = 0x00;
|
|
dmap->tc_venus.control4 = 0x00;
|
|
|
|
dmap->tc_venus.io_general = io_gen;
|
|
dmap->tc_venus.io_config = io_conf;
|
|
|
|
dmap->tc_venus.display_start = 0x00000000;
|
|
dmap->tc_venus.half_row_incr = 0x00000100;
|
|
dmap->tc_venus.display_pitch = 0x00000180;
|
|
dmap->tc_venus.cas_mask = 0x7f;
|
|
dmap->tc_venus.horiz_latency = 0x00;
|
|
|
|
dmap->tc_venus.horiz_end_sync = 0x0010;
|
|
dmap->tc_venus.horiz_end_blank = 0x0024;
|
|
dmap->tc_venus.horiz_start_blank = 0x00e4;
|
|
dmap->tc_venus.horiz_total = 0x00ea;
|
|
dmap->tc_venus.horiz_half_line = 0x0075;
|
|
dmap->tc_venus.horiz_count_load = 0x0000;
|
|
|
|
dmap->tc_venus.vert_end_sync = 0x02;
|
|
dmap->tc_venus.vert_end_blank = 0x16;
|
|
dmap->tc_venus.vert_start_blank = 0x0136;
|
|
dmap->tc_venus.vert_total = 0x0138;
|
|
dmap->tc_venus.vert_count_load = 0x0000;
|
|
dmap->tc_venus.vert_interrupt = 0x0137;
|
|
|
|
dmap->tc_venus.y_zoom = 0x01;
|
|
dmap->tc_venus.soft_register = 0xf0;
|
|
|
|
dmap->tc_venus.io_general = io_gen & ~VENUS_SOFT_RESET;
|
|
dmap->tc_venus.io_general = io_gen;
|
|
|
|
if ( dmap->tc_venus.io_general & VENUS_NO_GENLOCK )
|
|
{
|
|
dmap->tc_venus.control3 = 0x7b;
|
|
dmap->tc_venus.control1 = 0xf9;
|
|
}
|
|
else
|
|
{
|
|
dmap->tc_venus.control3 = 0xfb;
|
|
dmap->tc_venus.control1 = 0xf1;
|
|
}
|
|
|
|
/*
|
|
* Initialize venus chip 1 which affects 1-bit monochrome and selection
|
|
* memory operations.
|
|
*/
|
|
dmap->mono_venus.control1 = 0x00;
|
|
dmap->mono_venus.control2 = 0x00;
|
|
dmap->mono_venus.control3 = 0x00;
|
|
dmap->mono_venus.control4 = 0x00;
|
|
dmap->mono_venus.refresh_interval = 0x70; /* Set refresh interval. */
|
|
dmap->mono_venus.control1 = 0x13;
|
|
|
|
dmap->mono_venus.io_config = 0x0000;
|
|
dmap->mono_venus.display_start = 0x00000000;
|
|
dmap->mono_venus.half_row_incr = 0x00000080;
|
|
dmap->mono_venus.display_pitch = 0x00000060;
|
|
dmap->mono_venus.cas_mask = 0x3f;
|
|
dmap->mono_venus.horiz_latency = 0x00;
|
|
|
|
dmap->mono_venus.horiz_end_sync = 0x0010;
|
|
dmap->mono_venus.horiz_end_blank = 0x0024;
|
|
dmap->mono_venus.horiz_start_blank = 0x00e4;
|
|
dmap->mono_venus.horiz_total = 0x00ff;
|
|
dmap->mono_venus.horiz_half_line = 0x0075;
|
|
dmap->mono_venus.horiz_count_load = 0x0000;
|
|
|
|
dmap->mono_venus.vert_end_sync = 0x02;
|
|
dmap->mono_venus.vert_end_blank = 0x16;
|
|
dmap->mono_venus.vert_start_blank = 0x0136;
|
|
dmap->mono_venus.vert_total = 0x01ff;
|
|
dmap->mono_venus.vert_count_load = 0x0000;
|
|
dmap->mono_venus.vert_interrupt = 0x0000;
|
|
|
|
dmap->mono_venus.y_zoom = 0x01;
|
|
dmap->mono_venus.soft_register = 0xf0;
|
|
|
|
dmap->mono_venus.control3 = 0xfb;
|
|
if ( dmap->tc_venus.io_general & VENUS_NO_GENLOCK )
|
|
{
|
|
dmap->mono_venus.control1 = 0xfb;
|
|
}
|
|
else
|
|
{
|
|
dmap->mono_venus.control1 = 0xf3;
|
|
}
|
|
}
|
|
|
|
/*"tcs_putcmap"
|
|
*
|
|
* Local routine to set the color map values for either the 24-bit or the
|
|
* monochrome frame buffer for RASTEROPS_TCS card. In addition to real
|
|
* lookup table manipulation, emulation of 8-bit indexed color maps is
|
|
* done for 24-bit mode.
|
|
*
|
|
* Note that for this card the lut load must occur during vertical retrace,
|
|
* so the vertical retrace interrupt is used. Since the SPARCstation is really
|
|
* quite fast relative to the loading of the lut we always load the entire lut.
|
|
* This is possible because we maintain the whole lut in cmap_xxx within softc.
|
|
*
|
|
* = 0 if success
|
|
* = error indication otherwise
|
|
*/
|
|
static int tcs_putcmap( softc, cmap )
|
|
SOFTC *softc; /* -> characteristics for our unit. */
|
|
struct fbcmap *cmap; /* -> where to get color map (ioctl data area). */
|
|
{
|
|
u_int count; /* # of color map entries to set. */
|
|
int force_update; /* Indicates if access real luts. */
|
|
u_int index; /* Index: entry in cmap_xxx to access. */
|
|
int n_entry; /* Index: ordinal # of current map entry. */
|
|
int plane_group; /* Top 7 bits of index = plane group. */
|
|
|
|
/*
|
|
* Verify we need to actually move some data. Initialize variables from
|
|
* caller's parameters, etc. If the plane group is zero, default an
|
|
* appropriate plane group.
|
|
*/
|
|
if ( (cmap->count == 0) || !cmap->red || !cmap->green || !cmap->blue )
|
|
{
|
|
return 0;
|
|
}
|
|
count = cmap->count;
|
|
index = cmap->index & PIX_ALL_PLANES;
|
|
if (index+count > TC_CMAP_SIZE)
|
|
{
|
|
return EINVAL;
|
|
}
|
|
force_update = cmap->index & PR_FORCE_UPDATE;
|
|
if ( !(plane_group = PIX_ATTRGROUP(cmap->index)) )
|
|
{
|
|
plane_group = softc->pg_enabled[PIXPG_24BIT_COLOR] ?
|
|
PIXPG_24BIT_COLOR : PIXPG_8BIT_COLOR;
|
|
}
|
|
|
|
/* If interruts are enabled disable so we can update things in peace.
|
|
*/
|
|
#ifdef NOTDEF
|
|
if ( softc->device_tcs->tc_venus.control4 & VENUS_VERT_INT_ENA )
|
|
{
|
|
softc->device_tcs->tc_venus.control4 = 0;
|
|
softc->device_tcs->tc_venus.status = 0;
|
|
}
|
|
#endif NOTDEF
|
|
|
|
/* Move caller's data, there are 4 cases: kernel space and user space
|
|
* in overlay or colormap luts.
|
|
* Note we move the data into the proper index location RASTEROPS_TCS
|
|
* (see note 1 above.)
|
|
*/
|
|
if ( plane_group == PIXPG_OVERLAY )
|
|
{
|
|
if (softc->tc1d.flags & CG8_KERNEL_UPDATE)
|
|
{
|
|
softc->tc1d.flags &= ~CG8_KERNEL_UPDATE;
|
|
BCOPY( cmap->red, &softc->omap_red[index], count );
|
|
BCOPY(cmap->green,&softc->omap_green[index],count);
|
|
BCOPY(cmap->blue,&softc->omap_blue[index], count );
|
|
}
|
|
else
|
|
{
|
|
if ( COPYIN(cmap->red,&softc->omap_red[index], count ) ||
|
|
COPYIN(cmap->green,&softc->omap_green[index], count) ||
|
|
COPYIN( cmap->blue, &softc->omap_blue[index], count ) )
|
|
{
|
|
return EFAULT;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (softc->tc1d.flags & CG8_KERNEL_UPDATE)
|
|
{
|
|
softc->tc1d.flags &= ~CG8_KERNEL_UPDATE;
|
|
BCOPY( cmap->red, &softc->cmap_red[index], count );
|
|
BCOPY( cmap->green, &softc->cmap_green[index], count);
|
|
BCOPY( cmap->blue, &softc->cmap_blue[index], count );
|
|
}
|
|
else
|
|
{
|
|
if ( COPYIN( cmap->red, &softc->cmap_red[index], count ) ||
|
|
COPYIN(cmap->green,&softc->cmap_green[index], count) ||
|
|
COPYIN( cmap->blue, &softc->cmap_blue[index], count ) )
|
|
{
|
|
return EFAULT;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* If we are doing cg8 emulation, and hardware update is not forced,
|
|
* set 8-bit index emulation color table entries for 24-bit buffer.
|
|
* (The check for the 8-bit plane group is here in case the kernel
|
|
* knows 8-bit hardware exists, but the driver did not export it to
|
|
* Sunview.)
|
|
*/
|
|
if ( !force_update && (softc->pg_enabled[PIXPG_8BIT_COLOR] == 0) &&
|
|
((plane_group==PIXPG_24BIT_COLOR) || (plane_group==PIXPG_8BIT_COLOR)) )
|
|
{
|
|
for (n_entry = 0; n_entry < count; n_entry++, index++)
|
|
{
|
|
softc->em_red[index] = softc->cmap_red[index];
|
|
softc->em_green[index] = softc->cmap_green[index];
|
|
softc->em_blue[index] = softc->cmap_blue[index];
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Set entries in actual Brooktree lookup tables for 8/24-bit buffer.
|
|
*/
|
|
else if ( plane_group==PIXPG_24BIT_COLOR || plane_group==PIXPG_8BIT_COLOR )
|
|
{
|
|
softc->tc1d.flags |= CG8_24BIT_CMAP;
|
|
softc->device_tcs->tc_venus.control4 = 5;
|
|
}
|
|
|
|
/*
|
|
* Set entries in actual Brooktree lookup tables for monochrome overlay.
|
|
*/
|
|
else if ( plane_group == PIXPG_OVERLAY )
|
|
{
|
|
if ( softc->pg_enabled[PIXPG_24BIT_COLOR] != 0 )
|
|
{
|
|
softc->tc1d.flags |= CG8_OVERLAY_CMAP;
|
|
softc->device_tcs->tc_venus.control4 = 5;
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
printf("Illegal plane group %d encountered\n", plane_group);
|
|
return EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*"tcs_update_cmap"
|
|
*
|
|
* For a TCS card update the color maps (color and overlay) if
|
|
* required. This routine is called from cgeightpoll() when
|
|
* a vertical interrupt is detected on a tcs board. It does
|
|
* not clear the interrupt, as this is done in cgeightpoll().
|
|
*/
|
|
static tcs_update_cmap(softc)
|
|
SOFTC *softc; /* -> to characteristics for our unit. */
|
|
{
|
|
Tcs_Device_Map *device_tcs; /* Pointer to tcs device register area. */
|
|
int n_entry; /* Index: entry in cmap_xxx now accessing. */
|
|
|
|
device_tcs = softc->device_tcs;
|
|
if ( softc->tc1d.flags & CG8_24BIT_CMAP )
|
|
{
|
|
device_tcs->dac.ram_write_addr = 0;
|
|
for (n_entry=0; n_entry < TC_CMAP_SIZE; n_entry++)
|
|
{
|
|
device_tcs->dac.color = softc->cmap_red[n_entry];
|
|
device_tcs->dac.color = softc->cmap_green[n_entry];
|
|
device_tcs->dac.color = softc->cmap_blue[n_entry];
|
|
}
|
|
softc->tc1d.flags &= ~CG8_24BIT_CMAP;
|
|
}
|
|
if ( softc->tc1d.flags & CG8_OVERLAY_CMAP )
|
|
{
|
|
for (n_entry=0; n_entry < TC_OMAP_SIZE; n_entry++)
|
|
{
|
|
if ( !softc->sw_cursor_color_frozen || n_entry != 2 )
|
|
{
|
|
device_tcs->dac.overlay_write_addr =
|
|
translate_omap[n_entry];
|
|
device_tcs->dac.overlay = softc->omap_red[n_entry];
|
|
device_tcs->dac.overlay = softc->omap_green[n_entry];
|
|
device_tcs->dac.overlay = softc->omap_blue[n_entry];
|
|
}
|
|
}
|
|
softc->tc1d.flags &= ~CG8_OVERLAY_CMAP;
|
|
}
|
|
}
|
|
|
|
/*"x_build_mmap_info"
|
|
*
|
|
* Local routine to build table used to memory map frame buffers into
|
|
* user space (as opposed to kernel space which is done using fb_mapin).
|
|
* Note the order of mapping will properly map a traditional cg8 card
|
|
* (if other extraneous plane groups are not present.)
|
|
*/
|
|
x_build_mmap_info( softc )
|
|
SOFTC *softc; /* -> characteristics for this instance. */
|
|
{
|
|
int mmi; /* Index: number of entries in mmap_info set up. */
|
|
Mmap_Info *mmp; /* Cursor: entry in mmap_info to initialize. */
|
|
u_int offset; /* Offset into virtual memory of next fb. */
|
|
|
|
mmi = 0;
|
|
mmp = softc->mmap_info;
|
|
offset = 0;
|
|
|
|
if ( softc->pg_enabled[PIXPG_OVERLAY] )
|
|
{
|
|
mmp->group = PIXPG_OVERLAY;
|
|
mmp->bgn_offset = offset;
|
|
mmp->end_offset = offset + softc->fb_mono_mmap_size;
|
|
mmp->sbus_delta = softc->fb_mono_sbus_delta;
|
|
offset = mmp->end_offset;
|
|
mmp++;
|
|
mmi++;
|
|
}
|
|
if ( softc->pg_enabled[PIXPG_OVERLAY_ENABLE] )
|
|
{
|
|
mmp->group = PIXPG_OVERLAY_ENABLE;
|
|
mmp->bgn_offset = offset;
|
|
mmp->end_offset = offset + softc->fb_sel_mmap_size;
|
|
mmp->sbus_delta = softc->fb_sel_sbus_delta;
|
|
offset = mmp->end_offset;
|
|
mmp++;
|
|
mmi++;
|
|
}
|
|
if ( softc->pg_enabled[PIXPG_24BIT_COLOR] )
|
|
{
|
|
mmp->group = PIXPG_24BIT_COLOR;
|
|
mmp->bgn_offset = offset;
|
|
mmp->end_offset = offset + softc->fb_tc_mmap_size;
|
|
mmp->sbus_delta = softc->fb_tc_sbus_delta;
|
|
offset = mmp->end_offset;
|
|
mmp++;
|
|
mmi++;
|
|
}
|
|
if ( softc->pg_enabled[PIXPG_8BIT_COLOR] )
|
|
{
|
|
mmp->group = PIXPG_8BIT_COLOR;
|
|
mmp->bgn_offset = offset;
|
|
mmp->end_offset = offset + softc->fb_8bit_mmap_size;
|
|
mmp->sbus_delta = softc->fb_8bit_sbus_delta;
|
|
offset = mmp->end_offset;
|
|
mmp++;
|
|
mmi++;
|
|
}
|
|
if ( softc->pg_enabled[PIXPG_VIDEO_ENABLE] )
|
|
{
|
|
mmp->group = PIXPG_VIDEO_ENABLE;
|
|
mmp->bgn_offset = offset;
|
|
mmp->end_offset = offset + softc->fb_video_mmap_size;
|
|
mmp->sbus_delta = softc->fb_video_sbus_delta;
|
|
offset = mmp->end_offset;
|
|
mmp++;
|
|
mmi++;
|
|
}
|
|
|
|
softc->mmap_count = mmi;
|
|
}
|
|
|
|
/*"x_g_attr"
|
|
*
|
|
* Local routine to return the characteristics (attributes) associated
|
|
* with the current frame buffer. (Called by tcone_ioctl).
|
|
*
|
|
* = 0 if success
|
|
* = error indication otherwise
|
|
*/
|
|
static int x_g_attr( softc, gattr )
|
|
SOFTC *softc; /* -> characteristics for our unit. */
|
|
struct fbgattr *gattr; /* -> where to put attributes(data area from ioctl) */
|
|
{
|
|
/* Return the characteristics of the frame buffer being emulated. Fill in
|
|
* the characteristics which were received from the PROMs.
|
|
*/
|
|
if ( softc->pg_enabled[PIXPG_24BIT_COLOR] )
|
|
{
|
|
*gattr = tc1_attrdefault;
|
|
gattr->fbtype.fb_height = softc->height;
|
|
gattr->fbtype.fb_width = softc->width;
|
|
gattr->fbtype.fb_size =
|
|
softc->fb_mono_mmap_size + softc->fb_sel_mmap_size +
|
|
softc->fb_tc_mmap_size;
|
|
}
|
|
else
|
|
{
|
|
*gattr = cg4_attrdefault;
|
|
gattr->fbtype.fb_height = softc->height;
|
|
gattr->fbtype.fb_width = softc->width;
|
|
gattr->fbtype.fb_size =
|
|
softc->fb_mono_mmap_size + softc->fb_sel_mmap_size +
|
|
softc->fb_8bit_mmap_size;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*"x_g_emulation_mode"
|
|
*
|
|
* Local routine to get emulation mode of driver operations.
|
|
*
|
|
* = 0 if success
|
|
* = error indication otherwise
|
|
*/
|
|
static int x_g_emulation_mode( softc, mode )
|
|
SOFTC *softc; /* -> characteristics for our unit. */
|
|
Pipio_Emulation *mode; /* -> where to put mode of emulation. */
|
|
{
|
|
int pgi; /* Index: next entry in pg_enabled to access. */
|
|
|
|
/*
|
|
* Set up plane group information based on softc entries.
|
|
* Get timing regimen.
|
|
*/
|
|
for ( pgi = 0; pgi < FB_NPGS; pgi++ )
|
|
{
|
|
if ( softc->pg_enabled[pgi] )
|
|
{
|
|
mode->plane_groups[pgi] = 1;
|
|
}
|
|
else if ( softc->pg_possible[pgi] )
|
|
{
|
|
mode->plane_groups[pgi] = 2;
|
|
}
|
|
else
|
|
{
|
|
mode->plane_groups[pgi] = 0;
|
|
}
|
|
}
|
|
|
|
mode->timing = softc->timing_regimen;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*"x_getcmap"
|
|
*
|
|
* Local routine to return color map values for either the 24-bit or the
|
|
* monochrome frame buffer. In addition to real lookup table manipulation,
|
|
* emulation of 8-bit indexed color maps is done for 24-bit mode.
|
|
* (Called by tcone_ioctl).
|
|
*
|
|
* = 0 if success
|
|
* = error indication otherwise
|
|
*/
|
|
static int x_getcmap( softc, cmap )
|
|
SOFTC *softc; /* -> characteristics for our unit. */
|
|
struct fbcmap *cmap; /* -> where to return the color map values. */
|
|
{
|
|
u_int count; /* # of color map entries to return. */
|
|
Tc1_Device_Map *device_reg; /* Pointer to the Brooktrees. */
|
|
Tcs_Device_Map *device_tcs; /* Pointer to the TCS card device regs. */
|
|
int force_update; /* Indicates if should access real luts. */
|
|
u_int index; /* Index of first entry to access. */
|
|
int n_entry; /* Loop index: current color map entry. */
|
|
int plane_group; /* Top 7 bits of index = plane group. */
|
|
u_char tmp_blue[TC_CMAP_SIZE]; /* Temporary for blue values. */
|
|
u_char tmp_green[TC_CMAP_SIZE]; /* Temporary for green values. */
|
|
u_char tmp_red[TC_CMAP_SIZE]; /* Temporary for red values. */
|
|
|
|
/*
|
|
* Initialize variables from caller's parameters, etc. Verify we need to
|
|
* actually move some data. A zero plane group defaults based on emulation
|
|
* type.
|
|
*/
|
|
count = cmap->count;
|
|
if ( (count == 0) || !cmap->red || !cmap->green || !cmap->blue )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
index = cmap->index & PIX_ALL_PLANES;
|
|
if (index+count > TC_CMAP_SIZE)
|
|
{
|
|
return EINVAL;
|
|
}
|
|
force_update = cmap->index & PR_FORCE_UPDATE;
|
|
if ( !(plane_group = PIX_ATTRGROUP(cmap->index)) )
|
|
{
|
|
plane_group = softc->pg_enabled[PIXPG_24BIT_COLOR] ?
|
|
PIXPG_24BIT_COLOR : PIXPG_8BIT_COLOR;
|
|
}
|
|
|
|
/* If there is no 8-bit frame buffer, and an update is not forced,
|
|
* get 8-bit index emulation color table entries for 24-bit buffer.
|
|
*/
|
|
if ( !force_update && (softc->pg_enabled[PIXPG_8BIT_COLOR] == 0)
|
|
&& (plane_group == PIXPG_24BIT_COLOR) )
|
|
{
|
|
if ( COPYOUT( &softc->em_red[index], cmap->red, count) ||
|
|
COPYOUT( &softc->em_green[index], cmap->green, count) ||
|
|
COPYOUT( &softc->em_blue[index], cmap->blue, count) )
|
|
{
|
|
return EFAULT;
|
|
}
|
|
}
|
|
|
|
/* Get entries for the actual Brooktree lookup tables for 8/24-bit buffer.
|
|
*/
|
|
else if ( plane_group == PIXPG_24BIT_COLOR ||
|
|
plane_group == PIXPG_8BIT_COLOR )
|
|
{
|
|
switch(softc->fb_model)
|
|
{
|
|
default:
|
|
case RASTEROPS_TC:
|
|
case RASTEROPS_TCP:
|
|
device_reg = softc->device_reg;
|
|
device_reg->dacs.bt457.all_address = index;
|
|
for (n_entry = 0; n_entry < count; n_entry++)
|
|
{
|
|
tmp_red[n_entry] = device_reg->dacs.bt457.red_color;
|
|
tmp_green[n_entry] = device_reg->dacs.bt457.green_color;
|
|
tmp_blue[n_entry] = device_reg->dacs.bt457.blue_color;
|
|
}
|
|
break;
|
|
case RASTEROPS_TCS:
|
|
device_tcs = softc->device_tcs;
|
|
device_tcs->dac.ram_read_addr = index;
|
|
for (n_entry = 0; n_entry < count; n_entry++)
|
|
{
|
|
tmp_red[n_entry] = device_tcs->dac.color;
|
|
tmp_green[n_entry] = device_tcs->dac.color;
|
|
tmp_blue[n_entry] = device_tcs->dac.color;
|
|
}
|
|
break;
|
|
case RASTEROPS_TCL:
|
|
break;
|
|
}
|
|
if ( COPYOUT( tmp_red, cmap->red, count) ||
|
|
COPYOUT( tmp_green, cmap->green, count) ||
|
|
COPYOUT( tmp_blue, cmap->blue, count) )
|
|
{
|
|
return EFAULT;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Get entries for the actual Brooktree lookup tables for monochrome
|
|
* overlay. (A shadow color map is accessed rather than hardware.)
|
|
*/
|
|
else if (plane_group == PIXPG_OVERLAY)
|
|
{
|
|
if ( COPYOUT( &softc->omap_red[index], cmap->red, count) ||
|
|
COPYOUT( &softc->omap_green[index], cmap->green, count) ||
|
|
COPYOUT( &softc->omap_blue[index], cmap->blue, count) )
|
|
{
|
|
return EFAULT;
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
printf("Illegal plane group %d encountered\n", plane_group);
|
|
return EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*"x_g_fb_info"
|
|
*
|
|
* Local routine to return a description of the frame buffers supported
|
|
* by this device instance. The plane groups are processed in order of
|
|
* their virtual address so that total_mmap_bytes can be properly calculated.
|
|
*
|
|
* = 0 if success
|
|
* = error indication otherwise
|
|
*/
|
|
static int x_g_fb_info( softc, info )
|
|
SOFTC *softc; /* -> characteristics for our unit. */
|
|
Pipio_Fb_Info *info; /* -> where to place frame buffer info. */
|
|
{
|
|
int fbi; /* Index: next frame buffer description to move. */
|
|
int mmi; /* Index: # of mmap_info entry looking at. */
|
|
Mmap_Info *mmp; /* Cursor: mmap_info entry looking at. */
|
|
|
|
fbi = 0;
|
|
|
|
for ( mmi=0, mmp=softc->mmap_info; mmi < softc->mmap_count; mmi++, mmp++ )
|
|
{
|
|
info->fb_descriptions[fbi].group = mmp->group;
|
|
info->fb_descriptions[fbi].width = softc->width;
|
|
info->fb_descriptions[fbi].height = softc->height;
|
|
info->fb_descriptions[fbi].mmap_size = mmp->end_offset-mmp->bgn_offset;
|
|
info->fb_descriptions[fbi].mmap_offset = mmp->bgn_offset;
|
|
switch(mmp->group)
|
|
{
|
|
case PIXPG_24BIT_COLOR:
|
|
info->fb_descriptions[fbi].depth = 32;
|
|
info->fb_descriptions[fbi].linebytes = softc->linebytes32;
|
|
break;
|
|
case PIXPG_8BIT_COLOR:
|
|
info->fb_descriptions[fbi].depth = 8;
|
|
info->fb_descriptions[fbi].linebytes = softc->linebytes8;
|
|
break;
|
|
default:
|
|
info->fb_descriptions[fbi].depth = 1;
|
|
info->fb_descriptions[fbi].linebytes = softc->linebytes1;
|
|
break;
|
|
}
|
|
fbi++;
|
|
}
|
|
|
|
info->frame_buffer_count = softc->mmap_count;
|
|
info->total_mmap_size = softc->mmap_info[softc->mmap_count-1].end_offset;
|
|
return 0;
|
|
}
|
|
|
|
#if NWIN > 0
|
|
/*"x_g_pixrect"
|
|
*
|
|
* Local routine to return the pixrect structure for use by the kernel to
|
|
* access this device instance.
|
|
*
|
|
* = 0 if success
|
|
* = error indication otherwise
|
|
*/
|
|
static int x_g_pixrect( softc, dev, fbpr )
|
|
SOFTC *softc; /* -> characteristics for our unit. */
|
|
dev_t dev; /* = device number. */
|
|
struct fbpixrect *fbpr; /* -> where to return pixrect info (ioctl data)*/
|
|
{
|
|
struct cg8_data *cg8d; /* Pointer to pixrect private data area. */
|
|
Pipio_Fb_Info fb_info; /* Frame buffer info about this device instance. */
|
|
struct cg4fb *fbp; /* Index: fb in pixrect private area now init'ing */
|
|
int i; /* Index: # of frame buffer now initializing. */
|
|
u_int initplanes; /* Plane group/mask for current plane group. */
|
|
Pixrect *tmppr; /* Pointer to pixrect (to call cg8_putattributes). */
|
|
|
|
tmppr = &softc->pr;
|
|
|
|
/* "Allocate" pixrect by pointing into our instance's private storage (the
|
|
* kernel will use this pixrect, so access is certainly possible!). Set the
|
|
* private data pointer.
|
|
*/
|
|
fbpr->fbpr_pixrect = &softc->pr;
|
|
softc->pr.pr_data = (caddr_t) & softc->tc1d;
|
|
|
|
/* Initialize pixrect area within our software characteristics area
|
|
* now that we are allocated. Also default driver's private data.
|
|
*/
|
|
softc->pr.pr_ops = &tcp_ops;
|
|
softc->pr.pr_size.x = softc->width;
|
|
softc->pr.pr_size.y = softc->height;
|
|
|
|
softc->tc1d.flags = 0;
|
|
softc->tc1d.planes = 0;
|
|
softc->tc1d.fd = minor (dev);
|
|
|
|
/* Get the information about the frame buffers and memories this instance
|
|
* supports. Then for each frame buffer provided by this device, initialize
|
|
* its characteristics (other than image pointers) in the pixrect private
|
|
* data area.
|
|
*/
|
|
x_g_fb_info(softc, &fb_info);
|
|
|
|
softc->tc1d.num_fbs = fb_info.frame_buffer_count;
|
|
DEBUGF(4, ("ioctl GPIXRECT num fbs = %d\n", softc->tc1d.num_fbs));
|
|
|
|
for (fbp=softc->tc1d.fb, i=0; i < fb_info.frame_buffer_count; fbp++, i++)
|
|
{
|
|
fbp->group = fb_info.fb_descriptions[i].group;
|
|
fbp->depth = fb_info.fb_descriptions[i].depth;
|
|
switch(fb_info.fb_descriptions[i].depth)
|
|
{
|
|
case 1: fbp->mprp.mpr.md_linebytes = softc->linebytes1; break;
|
|
case 8: fbp->mprp.mpr.md_linebytes = softc->linebytes8; break;
|
|
case 32: fbp->mprp.mpr.md_linebytes = softc->linebytes32; break;
|
|
default:
|
|
printf("Error unsupported depth %d encountered for plane group %i in GPIXRECT\n",
|
|
fb_info.fb_descriptions[i].depth,
|
|
fb_info.fb_descriptions[i].group);
|
|
break;
|
|
}
|
|
fbp->mprp.mpr.md_offset.x = 0;
|
|
fbp->mprp.mpr.md_offset.y = 0;
|
|
fbp->mprp.mpr.md_primary = 0;
|
|
fbp->mprp.mpr.md_flags = fb_info.fb_descriptions[i].depth != 1 ?
|
|
MP_DISPLAY | MP_PLANEMASK : MP_DISPLAY;
|
|
fbp->mprp.planes =
|
|
fb_info.fb_descriptions[i].depth != 1 ? PIX_ALL_PLANES : 0;
|
|
DEBUGF(5, ("ioctl GPIXRECT group %d depth %d\n",
|
|
fbp->group, fbp->depth));
|
|
}
|
|
|
|
/* The majority of the pixrect structure is now set up, so initialize the
|
|
* image pointers and perform any memory initializations which are
|
|
* necessary. We loop backwards to guarantee that the last frame buffer
|
|
* accessed is the monochrome.
|
|
*/
|
|
for (cg8d = cg8_d(tmppr), i = fb_info.frame_buffer_count-1; i >= 0; i--)
|
|
{
|
|
switch ( cg8d->fb[i].group )
|
|
{
|
|
case PIXPG_OVERLAY:
|
|
initplanes = PIX_GROUP(PIXPG_OVERLAY);
|
|
cg8_putattributes (tmppr, &initplanes);
|
|
DEBUGF(5, ("ioctl GPIXRECT monochrome pr_depth = %d\n",
|
|
tmppr->pr_depth));
|
|
cg8d->fb[i].mprp.mpr.md_image =
|
|
cg8d->mprp.mpr.md_image = (short *) softc->fb_mono;
|
|
pr_rop (tmppr, 0, 0, softc->pr.pr_size.x, softc->pr.pr_size.y,
|
|
PIX_SRC, (Pixrect *) 0, 0, 0);
|
|
break;
|
|
|
|
case PIXPG_OVERLAY_ENABLE:
|
|
initplanes = PIX_GROUP(PIXPG_OVERLAY_ENABLE);
|
|
cg8_putattributes (tmppr, &initplanes);
|
|
DEBUGF(5, ("ioctl GPIXRECT selection pr_depth = %d\n",
|
|
tmppr->pr_depth));
|
|
cg8d->fb[i].mprp.mpr.md_image = cg8d->mprp.mpr.md_image
|
|
= (short *) softc->fb_sel;
|
|
pr_rop(tmppr, 0, 0, softc->pr.pr_size.x, softc->pr.pr_size.y,
|
|
PIX_SRC | PIX_COLOR (1),
|
|
(Pixrect *) 0, 0, 0);
|
|
break;
|
|
|
|
case PIXPG_8BIT_COLOR:
|
|
cg8d->flags |= CG8_EIGHT_BIT_PRESENT;
|
|
cg8d->fb[i].mprp.mpr.md_image = cg8d->mprp.mpr.md_image
|
|
= (short *) softc->fb_8bit;
|
|
cg8d->mprp.mpr.md_linebytes = 0;
|
|
break;
|
|
|
|
case PIXPG_24BIT_COLOR:
|
|
cg8d->fb[i].mprp.mpr.md_image =
|
|
cg8d->mprp.mpr.md_image
|
|
= (short *) -1;
|
|
cg8d->mprp.mpr.md_linebytes = 0;
|
|
break;
|
|
|
|
case PIXPG_VIDEO_ENABLE:
|
|
cg8d->flags |= CG8_PIP_PRESENT;
|
|
cg8d->fb[i].mprp.mpr.md_image =
|
|
cg8_d (tmppr)->mprp.mpr.md_image = (short *) -1;
|
|
cg8d->mprp.mpr.md_linebytes = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* Enable video display.
|
|
*/
|
|
switch(softc->fb_model)
|
|
{
|
|
default:
|
|
mfb_set_video(&softc->device_reg->sun_mfb_reg, FBVIDEO_ON);
|
|
break;
|
|
case RASTEROPS_TCS:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif NWIN > 0
|
|
|
|
/*"x_g_type"
|
|
*
|
|
* Local routine to return the type of the active frame buffer and its
|
|
* resolution, etc.
|
|
*
|
|
* = 0 if success
|
|
* = error indication otherwise
|
|
*/
|
|
static int x_g_type( softc, fb )
|
|
SOFTC *softc; /* -> characteristics for our unit. */
|
|
struct fbtype *fb; /* -> where to put type info (ioctl data area). */
|
|
{
|
|
/* Return information based on the type of frame buffer being emulated.
|
|
*/
|
|
if ( softc->pg_enabled[PIXPG_24BIT_COLOR] )
|
|
{
|
|
/* If we are emulating a Sun monochrome BW2 return that data, otherwise
|
|
* return the actual information about the current frame buffer.
|
|
*/
|
|
switch (tc1_attrdefault.sattr.emu_type)
|
|
{
|
|
case FBTYPE_SUN2BW:
|
|
*fb = tc1typedefault;
|
|
fb->fb_height = softc->height;
|
|
fb->fb_width = softc->width;
|
|
fb->fb_size = softc->fb_mono_mmap_size;
|
|
break;
|
|
|
|
default:
|
|
*fb = tc1_attrdefault.fbtype;
|
|
fb->fb_height = softc->height;
|
|
fb->fb_width = softc->width;
|
|
fb->fb_size =
|
|
softc->fb_mono_mmap_size + softc->fb_sel_mmap_size +
|
|
softc->fb_8bit_mmap_size + softc->fb_tc_mmap_size;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*fb = cg4_attrdefault.fbtype;
|
|
fb->fb_height = softc->height;
|
|
fb->fb_width = softc->width;
|
|
fb->fb_size = softc->fb_mono_mmap_size + softc->fb_sel_mmap_size +
|
|
softc->fb_8bit_mmap_size;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*"x_s_emulation_mode"
|
|
*
|
|
* Local routine to set emulation mode for driver operations.
|
|
* Use the mode specification to determine how to configure the
|
|
* system.
|
|
*
|
|
* = 0 if success
|
|
* = error indication otherwise
|
|
*/
|
|
static int x_s_emulation_mode( softc, mode )
|
|
SOFTC *softc; /* characteristics for our unit. */
|
|
Pipio_Emulation *mode; /* -> mode of emulation to set. */
|
|
{
|
|
int color; /* Index: color to put into look-up table. */
|
|
Tc1_Device_Map *device_reg; /* Quick pointer to device registers. */
|
|
Tcs_Device_Map *device_tcs; /* Quick pointer to tcs device registers. */
|
|
int pgi; /* Index: entry in pg_enabled to access. */
|
|
|
|
/*
|
|
* Process the emulation timing and size specified by the caller.
|
|
* If our device is not capable of providing the specified timing
|
|
* or size return an error.
|
|
*/
|
|
switch ( mode->timing )
|
|
{
|
|
case NATIVE_TIMING:
|
|
if ( softc->fb_model == RASTEROPS_TCS )
|
|
{
|
|
tcs_init_native(softc);
|
|
}
|
|
break;
|
|
case NTSC_TIMING:
|
|
if ( softc->fb_model != RASTEROPS_TCS ) return EINVAL;
|
|
tcs_init_ntsc(softc);
|
|
break;
|
|
case PAL_TIMING:
|
|
if ( softc->fb_model != RASTEROPS_TCS ) return EINVAL;
|
|
tcs_init_pal(softc);
|
|
break;
|
|
default:
|
|
return EINVAL;
|
|
}
|
|
|
|
|
|
/*
|
|
* Set only the plane groups specified by the caller.
|
|
*/
|
|
for ( pgi = 0; pgi < FB_NPGS; pgi++ )
|
|
{
|
|
if ( mode->plane_groups[pgi] == 1 )
|
|
{
|
|
if ( softc->pg_possible[pgi] == 0 ) return EINVAL;
|
|
softc->pg_enabled[pgi] = 1;
|
|
}
|
|
else
|
|
{
|
|
softc->pg_enabled[pgi] = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If 24-bit memory is enabled, reset true color ramp in luts.
|
|
*/
|
|
if ( softc->pg_enabled[PIXPG_24BIT_COLOR] )
|
|
{
|
|
switch(softc->fb_model)
|
|
{
|
|
default:
|
|
device_reg = softc->device_reg;
|
|
device_reg->dacs.bt457.all_address = 0;
|
|
for (color = 0; color < TC_CMAP_SIZE; color++)
|
|
{
|
|
device_reg->dacs.bt457.red_color = color;
|
|
device_reg->dacs.bt457.green_color = color;
|
|
device_reg->dacs.bt457.blue_color = color;
|
|
}
|
|
break;
|
|
case RASTEROPS_TCS:
|
|
device_tcs = softc->device_tcs;
|
|
device_tcs->dac.ram_write_addr = 0;
|
|
for (color = 0; color < TC_CMAP_SIZE; color++)
|
|
{
|
|
device_tcs->dac.color = color;
|
|
device_tcs->dac.color = color;
|
|
device_tcs->dac.color = color;
|
|
}
|
|
break;
|
|
case RASTEROPS_TCL:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Recompute the memory mapping information, so new configuration
|
|
* will be mapped properly.
|
|
*/
|
|
x_build_mmap_info(softc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*"x_s_map_slot"
|
|
*
|
|
* Local routine to return information using test ioctl entry
|
|
* point.
|
|
*
|
|
* = 0 if success
|
|
* = error indication otherwise
|
|
*/
|
|
static int x_s_map_slot( softc, phys_addr )
|
|
SOFTC *softc; /* -> characteristics for our unit. */
|
|
u_int *phys_addr; /* -> where to put attributes(data area from ioctl) */
|
|
{
|
|
addr_t reg; /* Mapping point for region. */
|
|
|
|
if ( softc->test_basepage ) return 0;
|
|
if ( !(reg = (addr_t)map_regs( (addr_t)*phys_addr, (u_int)0x1000, 0x01)) )
|
|
{
|
|
return -1;
|
|
}
|
|
softc->test_basepage = fbgetpage(reg);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* OVERVIEW OF TC BOARD HARDWARE
|
|
*
|
|
* (1) The SBus TC Card product
|
|
* contains two frame buffers. One frame buffer is 24 bits deep,
|
|
* and its pixel values are treated as 3 8-bit indices into 3 separate
|
|
* 8-in-8-out lookup tables to yield 8 bits for each of the red, green,
|
|
* and blue guns of the monitor. Each of the 8-in-8-out lookup tables
|
|
* is loaded with a linear ramp (or possibly a gamma corrected ramp)
|
|
* yielding a true color display of pixel values.
|
|
*
|
|
* +------------+
|
|
* | | +---+
|
|
* | |---/--->|vlt|---/---> red
|
|
* | 24 | 8 +---+ 8
|
|
* | +
|
|
* | bit | +---+
|
|
* ---/--->| |---/--->|vlt|---/---> green
|
|
* 24 | frame | 8 +---+ 8
|
|
* | +
|
|
* | buffer | +---+
|
|
* | |---/--->|vlt|---/---> blue
|
|
* | | 8 +---+ 8
|
|
* +------------+
|
|
*
|
|
* (2) The other frame buffer is monochrome and is 1 bit deep.
|
|
* Its pixel values are treated as inputs into the overlay
|
|
* of the 8-in-8-out lookup tables associated with the
|
|
* 24-bit frame buffer. Thus, the 1-bit frame buffer appears
|
|
* as an overlay over the 24-bit frame buffer on the screen.
|
|
* For each pixel, if the overlay is visible the 24-bit value
|
|
* is not and vice-versa. Whether the overlay is visible or not
|
|
* is controlled by a separate 1-bit deep selection memory. The
|
|
* output of this memory is the input for the overlay transparency
|
|
* bit on each of the 8-in-8-out lookup tables. Thus, the value in
|
|
* the selection memory associated with a pixel specifies which
|
|
* value is displayed for a given pixel, the one from the 24-bit
|
|
* memory or the monochrome overlay.
|
|
*
|
|
* +--------+ +--------+
|
|
* | | +-----------+ | |
|
|
* | 1 |--/-->| red vlt |<--/--| 1 |
|
|
* | | 1 +-----------+ 1 | |
|
|
* | bit | +-----------+ | bit |
|
|
* ---/--->| |--/-->| green vlt |<--/--| |
|
|
* 1 | frame | 1 +-----------+ 1 |select. |
|
|
* | | +-----------+ | |
|
|
* | buffer |--/-->| blue vlt |<--/--| memory |
|
|
* | | 1 +-----------+ 1 | |
|
|
* +--------+ +--------+
|
|
*
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* INDEXED COLOR MAP EMULATION
|
|
*
|
|
* The SBus TCP support provides emulation of indexed color maps for both
|
|
* the 24-bit true color frame buffer and the monochrome overlay frame buffer.
|
|
* This support is done jointly by this kernel pixrect driver (tcone.c) and
|
|
* the normal pixrect driver colormap support (tc1_colormap.c).
|
|
*
|
|
* For indexed color map emulation in the 24-bit buffer the kernel level
|
|
* driver for the tc1 maintains a main memory color map with 256 entries. When
|
|
* pixels are written or read in emulation mode the entries in this color map
|
|
* are accessed to perform a mapping between the 8-bit value used by the user,
|
|
* and the 24-bit true color value actually written to frame buffer memory.
|
|
* This mapping is performed by routines in this module, which are called from
|
|
* other modules (e.g., cg8_getput.c). In emulation mode the actual lookup
|
|
* table entries in the 3 Brooktree 457 RAMDACs are not touched, only the
|
|
* separate main memory color map. However, it is also possible to actually
|
|
* access the look up table entries in the RAMDACs. This is done by specifying
|
|
* the PR_FORCE_UPDATE flag in the plane parameter passed to cg8_getcolormap
|
|
* or cg8_putcolormap.
|
|
*
|
|
* The monochrome overlay emulation is handled in tc1_colormap.c. It is also
|
|
* possible to by-pass the emulation and actually write the four overlay color
|
|
* values.
|
|
*/
|
|
|
|
/*""
|
|
* PHYSICAL TO VIRTUAL MEMORY MAPPING FOR DEVICES ON THE SBus TC Card
|
|
*
|
|
* This driver performs mapping for the devices on the SBus TC Card. The
|
|
* mapping makes the physical devices appear to be contiguous with each other
|
|
* within the virtual space
|
|
*
|
|
* Virtual Space Physical Space
|
|
*
|
|
* Physical Offset from
|
|
* address: device registers
|
|
* xx000000+------------------+
|
|
* | On-board PROMs |
|
|
* +------------------+
|
|
*
|
|
* xx400000+------------------+00000000
|
|
* | Device registers |
|
|
* Offset from device +------------------+
|
|
* registers
|
|
* 00000000+------------------+ xx800000+------------------+00400000
|
|
* | Monochrome buffer| | True color buffer|
|
|
* 00020000+------------------+ +------------------+
|
|
* | Selection memory |
|
|
* 00040000+------------------+ xxC00000+------------------+00800000
|
|
* | True color buffer| | Monochrome buffer|
|
|
* 00435000+------------------+ +------------------+
|
|
* | Device registers |
|
|
* +------------------+ xxD00000+------------------+00900000
|
|
* | Selection memory |
|
|
* +------------------+
|
|
*
|
|
* The offset from the device registers in virtual space is defined near the
|
|
* beginning of this file in constants of the form TCP_xxx_VADDR_OFFSET, where
|
|
* xxx is MONOCHROME, TRUE_COLOR, etc.
|
|
*
|
|
* The offset from the device registers in physical space is defined near the
|
|
* beginning of this file in constants of the form TCP_xxx_PADDR_OFFSET.
|
|
*
|
|
* The offset from the beginning of the SBus physical device space (and thus
|
|
* the on-board PROMs) is defined in constants of the form
|
|
* TCP_xxx_sbus_delta_offset.
|
|
*
|
|
* The mapping from virtual to physical space is accomplished in cgeightmmap,
|
|
* and is based on an offset relative to the beginning of the device registers
|
|
* in virtual address space. The reason the offset is based on the device
|
|
* registers is that the device registers where passed into map_regs to set up
|
|
* the virtual space.
|
|
*
|
|
* ADDITIONAL DEVICES ON THE SBus TCP Card (w/pip option)
|
|
*
|
|
* The SBus TCP Card provides two additional buffers which must be mapped
|
|
* these are the 8-bit view of the 24-bit true color memory and the video
|
|
* enable memory. This results in a virtual space which looks like:
|
|
*
|
|
* Virtual Space Physical Space
|
|
*
|
|
* Physical Offset from
|
|
* address: device registers
|
|
* xx000000+------------------+
|
|
* | On-board PROMs |
|
|
* +------------------+
|
|
*
|
|
* xx400000+------------------+00000000
|
|
* | Device registers |
|
|
* +------------------+
|
|
*
|
|
* xx700000+------------------+00000000
|
|
* | 8-bit buffer |
|
|
* Offset presented to cgeightmmap for +------------------+
|
|
* mapping
|
|
* 00000000+------------------+ xx800000+------------------+00400000
|
|
* | Monochrome buffer| | True color buffer|
|
|
* 00020000+------------------+ +------------------+
|
|
* | Selection memory |
|
|
* 00040000+------------------+ xxC00000+------------------+00800000
|
|
* | True color memory| | Monochrome buffer|
|
|
* 00435000+------------------+ +------------------+
|
|
* | 8-bit buffer |
|
|
* 00533000+------------------+ xxD00000+------------------+00900000
|
|
* | Video enable mem.| | Selection memory |
|
|
* 00553000+------------------+ +------------------+
|
|
* | Device Registers |
|
|
* +------------------+ xxE00000+------------------+00A00000
|
|
* | Video enable mem.|
|
|
* +------------------+
|
|
*/
|