|
|
GNU Mach 1.0
/*
* Mach Operating System
* Copyright (c) 1991,1990,1989 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or [email protected]
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
* File: ims332.c
* Author: Alessandro Forin, Carnegie Mellon University
* Date: 1/92
*
* Routines for the Inmos IMS-G332 Colour video controller
*/
#include <platforms.h>
#include <chips/ims332.h>
#include <chips/screen.h>
#include <chips/xcfb_monitor.h>
/*
* Generic register access
*/
typedef volatile unsigned char *ims332_padded_regmap_t;
#ifdef MAXINE
unsigned int
ims332_read_register(regs, regno)
unsigned char *regs;
{
unsigned char *rptr;
register unsigned int val, v1;
/* spec sez: */
rptr = regs + 0x80000 + (regno << 4);
val = * ((volatile unsigned short *) rptr );
v1 = * ((volatile unsigned short *) regs );
return (val & 0xffff) | ((v1 & 0xff00) << 8);
}
ims332_write_register(regs, regno, val)
unsigned char *regs;
register unsigned int val;
{
unsigned char *wptr;
/* spec sez: */
wptr = regs + 0xa0000 + (regno << 4);
* ((volatile unsigned int *)(regs)) = (val >> 8) & 0xff00;
* ((volatile unsigned short *)(wptr)) = val;
}
#define assert_ims332_reset_bit(r) *r &= ~0x40
#define deassert_ims332_reset_bit(r) *r |= 0x40
#else /*MAXINE*/
#define ims332_read_register(p,r) \
((unsigned int *)(p)) [ (r) ]
#define ims332_write_register(p,r,v) \
((unsigned int *)(p)) [ (r) ] = (v)
#endif /*MAXINE*/
/*
* Color map
*/
ims332_load_colormap( regs, map)
ims332_padded_regmap_t *regs;
color_map_t *map;
{
register int i;
for (i = 0; i < 256; i++, map++)
ims332_load_colormap_entry(regs, i, map);
}
ims332_load_colormap_entry( regs, entry, map)
ims332_padded_regmap_t *regs;
color_map_t *map;
{
/* ?? stop VTG */
ims332_write_register(regs, IMS332_REG_LUT_BASE + (entry & 0xff),
(map->blue << 16) |
(map->green << 8) |
(map->red));
}
ims332_init_colormap( regs)
ims332_padded_regmap_t *regs;
{
color_map_t m;
m.red = m.green = m.blue = 0;
ims332_load_colormap_entry( regs, 0, &m);
m.red = m.green = m.blue = 0xff;
ims332_load_colormap_entry( regs, 1, &m);
ims332_load_colormap_entry( regs, 255, &m);
/* since we are at it, also fix cursor LUT */
ims332_load_colormap_entry( regs, IMS332_REG_CURSOR_LUT_0, &m);
ims332_load_colormap_entry( regs, IMS332_REG_CURSOR_LUT_1, &m);
/* *we* do not use this, but the prom does */
ims332_load_colormap_entry( regs, IMS332_REG_CURSOR_LUT_2, &m);
}
#if 1/*debug*/
ims332_print_colormap( regs)
ims332_padded_regmap_t *regs;
{
register int i;
for (i = 0; i < 256; i++) {
register unsigned int color;
color = ims332_read_register( regs, IMS332_REG_LUT_BASE + i);
printf("%x->[x%x x%x x%x]\n", i,
(color >> 16) & 0xff,
(color >> 8) & 0xff,
color & 0xff);
}
}
#endif
/*
* Video on/off
*
* It is unfortunate that X11 goes backward with white@0
* and black@1. So we must stash away the zero-th entry
* and fix it while screen is off. Also must remember
* it, sigh.
*/
struct vstate {
ims332_padded_regmap_t *regs;
unsigned short off;
};
ims332_video_off(vstate, up)
struct vstate *vstate;
user_info_t *up;
{
register ims332_padded_regmap_t *regs = vstate->regs;
register unsigned *save, csr;
if (vstate->off)
return;
/* Yes, this is awful */
save = (unsigned *)up->dev_dep_2.gx.colormap;
*save = ims332_read_register(regs, IMS332_REG_LUT_BASE);
ims332_write_register(regs, IMS332_REG_LUT_BASE, 0);
ims332_write_register( regs, IMS332_REG_COLOR_MASK, 0);
/* cursor now */
csr = ims332_read_register(regs, IMS332_REG_CSR_A);
csr |= IMS332_CSR_A_DISABLE_CURSOR;
ims332_write_register(regs, IMS332_REG_CSR_A, csr);
vstate->off = 1;
}
ims332_video_on(vstate, up)
struct vstate *vstate;
user_info_t *up;
{
register ims332_padded_regmap_t *regs = vstate->regs;
register unsigned *save, csr;
if (!vstate->off)
return;
/* Like I said.. */
save = (unsigned *)up->dev_dep_2.gx.colormap;
ims332_write_register(regs, IMS332_REG_LUT_BASE, *save);
ims332_write_register( regs, IMS332_REG_COLOR_MASK, 0xffffffff);
/* cursor now */
csr = ims332_read_register(regs, IMS332_REG_CSR_A);
csr &= ~IMS332_CSR_A_DISABLE_CURSOR;
ims332_write_register(regs, IMS332_REG_CSR_A, csr);
vstate->off = 0;
}
/*
* Cursor
*/
ims332_pos_cursor(regs,x,y)
ims332_padded_regmap_t *regs;
register int x,y;
{
ims332_write_register( regs, IMS332_REG_CURSOR_LOC,
((x & 0xfff) << 12) | (y & 0xfff) );
}
ims332_cursor_color( regs, color)
ims332_padded_regmap_t *regs;
color_map_t *color;
{
/* Bg is color[0], Fg is color[1] */
ims332_write_register(regs, IMS332_REG_CURSOR_LUT_0,
(color->blue << 16) |
(color->green << 8) |
(color->red));
color++;
ims332_write_register(regs, IMS332_REG_CURSOR_LUT_1,
(color->blue << 16) |
(color->green << 8) |
(color->red));
}
ims332_cursor_sprite( regs, cursor)
ims332_padded_regmap_t *regs;
unsigned short *cursor;
{
register int i;
/* We *could* cut this down a lot... */
for (i = 0; i < 512; i++, cursor++)
ims332_write_register( regs,
IMS332_REG_CURSOR_RAM+i, *cursor);
}
/*
* Initialization
*/
ims332_init(regs, reset, mon)
ims332_padded_regmap_t *regs;
unsigned int *reset;
xcfb_monitor_type_t mon;
{
int shortdisplay, broadpulse, frontporch;
assert_ims332_reset_bit(reset);
delay(1); /* specs sez 50ns.. */
deassert_ims332_reset_bit(reset);
/* CLOCKIN appears to receive a 6.25 Mhz clock --> PLL 12 for 75Mhz monitor */
ims332_write_register(regs, IMS332_REG_BOOT, 12 | IMS332_BOOT_CLOCK_PLL);
/* initialize VTG */
ims332_write_register(regs, IMS332_REG_CSR_A,
IMS332_BPP_8 | IMS332_CSR_A_DISABLE_CURSOR);
delay(50); /* spec does not say */
/* datapath registers (values taken from prom's settings) */
frontporch = mon->line_time - (mon->half_sync * 2 +
mon->back_porch +
mon->frame_visible_width / 4);
shortdisplay = mon->line_time / 2 - (mon->half_sync * 2 +
mon->back_porch + frontporch);
broadpulse = mon->line_time / 2 - frontporch;
ims332_write_register( regs, IMS332_REG_HALF_SYNCH, mon->half_sync);
ims332_write_register( regs, IMS332_REG_BACK_PORCH, mon->back_porch);
ims332_write_register( regs, IMS332_REG_DISPLAY,
mon->frame_visible_width / 4);
ims332_write_register( regs, IMS332_REG_SHORT_DIS, shortdisplay);
ims332_write_register( regs, IMS332_REG_BROAD_PULSE, broadpulse);
ims332_write_register( regs, IMS332_REG_V_SYNC, mon->v_sync * 2);
ims332_write_register( regs, IMS332_REG_V_PRE_EQUALIZE,
mon->v_pre_equalize);
ims332_write_register( regs, IMS332_REG_V_POST_EQUALIZE,
mon->v_post_equalize);
ims332_write_register( regs, IMS332_REG_V_BLANK, mon->v_blank * 2);
ims332_write_register( regs, IMS332_REG_V_DISPLAY,
mon->frame_visible_height * 2);
ims332_write_register( regs, IMS332_REG_LINE_TIME, mon->line_time);
ims332_write_register( regs, IMS332_REG_LINE_START, mon->line_start);
ims332_write_register( regs, IMS332_REG_MEM_INIT, mon->mem_init);
ims332_write_register( regs, IMS332_REG_XFER_DELAY, mon->xfer_delay);
ims332_write_register( regs, IMS332_REG_COLOR_MASK, 0xffffff);
ims332_init_colormap( regs );
ims332_write_register(regs, IMS332_REG_CSR_A,
IMS332_BPP_8 | IMS332_CSR_A_DMA_DISABLE | IMS332_CSR_A_VTG_ENABLE);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.