* Copyright (c) 1992 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* Ralph Campbell and Rick Macklem.
* %sccs.include.redist.c%
* @(#)cfb.c 7.9 (Berkeley) %G%
* This file contains machine-dependent routines for the graphics device.
* Copyright (C) 1989 Digital Equipment Corporation.
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies.
* Digital Equipment Corporation makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
* from: $Header: /sprite/src/kernel/dev/ds3100.md/RCS/devGraphics.c,
* v 9.2 90/02/13 22:16:24 shirriff Exp $ SPRITE (DECWRL)";
* Copyright (c) 1991,1990,1989 Carnegie Mellon University
* 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
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
* Carnegie Mellon requests users of this software to return to
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
#include <machine/machConst.h>
#include <machine/pmioctl.h>
#include <pmax/pmax/maxine.h>
#include <pmax/pmax/cons.h>
#include <pmax/pmax/pmaxtype.h>
#include <pmax/dev/device.h>
#include <pmax/dev/cfbreg.h>
#include <pmax/dev/fbreg.h>
#define PMAX /* enable /dev/pm compatibility */
* These need to be mapped into user space.
static void cfbScreenInit();
static void cfbLoadCursor();
static void cfbRestoreCursorColor();
static void cfbCursorColor();
static void cfbInitColorMap();
static void cfbLoadColorMap();
static void bt459_set_cursor_ram(), bt459_video_on(), bt459_video_off();
static void bt459_select_reg(), bt459_write_reg();
static u_char
bt459_read_reg();
static void cfbConfigMouse(), cfbDeconfigMouse();
void cfbKbdEvent(), cfbMouseEvent(), cfbMouseButtons();
extern void (*dcDivertXInput
)();
extern void (*dcMouseEvent
)();
extern void (*dcMouseButtons
)();
extern void (*sccDivertXInput
)();
extern void (*sccMouseEvent
)();
extern void (*sccMouseButtons
)();
extern void (*dtopDivertXInput
)();
extern void (*dtopMouseEvent
)();
extern void (*dtopMouseButtons
)();
extern int pmax_boardtype
;
extern u_short defCursor
[32];
extern struct consdev cn_tab
;
struct driver cfbdriver
= {
#define CFB_OFFSET_VRAM 0x0 /* from module's base */
#define CFB_OFFSET_BT459 0x200000 /* Bt459 registers */
#define CFB_OFFSET_IREQ 0x300000 /* Interrupt req. control */
#define CFB_OFFSET_ROM 0x380000 /* Diagnostic ROM */
#define CFB_OFFSET_RESET 0x3c0000 /* Bt459 resets on writes */
#define CFB_FB_SIZE 0x100000 /* frame buffer size */
* Test to see if device is present.
* Return true if found and initialized ok.
register struct pmax_ctlr
*cp
;
register struct pmax_fb
*fp
= &cfbfb
;
if (!fp
->initialized
&& !cfbinit(cp
->pmax_addr
))
printf("cfb0 (color display)\n");
register struct pmax_fb
*fp
= &cfbfb
;
* Set up event queue for later
fp
->fbu
->scrInfo
.qe
.eSize
= PM_MAXEVQ
;
fp
->fbu
->scrInfo
.qe
.eHead
= fp
->fbu
->scrInfo
.qe
.eTail
= 0;
fp
->fbu
->scrInfo
.qe
.tcSize
= MOTION_BUFFER_SIZE
;
fp
->fbu
->scrInfo
.qe
.tcNext
= 0;
fp
->fbu
->scrInfo
.qe
.timestamp_ms
= TO_MS(time
);
register struct pmax_fb
*fp
= &cfbfb
;
bzero((caddr_t
)fp
->fr_addr
, 1024 * 864);
cfbPosCursor(fp
->col
* 8, fp
->row
* 15);
cfbioctl(dev
, cmd
, data
, flag
, p
)
register struct pmax_fb
*fp
= &cfbfb
;
return (fbmmap(fp
, dev
, data
, p
));
fp
->fbu
->scrInfo
.mouse
= *(pmCursor
*)data
;
cfbPosCursor(fp
->fbu
->scrInfo
.mouse
.x
, fp
->fbu
->scrInfo
.mouse
.y
);
kpCmdPtr
= (pmKpCmd
*)data
;
if (kpCmdPtr
->nbytes
== 0)
(*fp
->KBDPutc
)(fp
->kbddev
, (int)kpCmdPtr
->cmd
);
for (; kpCmdPtr
->nbytes
> 0; cp
++, kpCmdPtr
->nbytes
--) {
if (kpCmdPtr
->nbytes
== 1)
(*fp
->KBDPutc
)(fp
->kbddev
, (int)*cp
);
*(PM_Info
**)data
= &fp
->fbu
->scrInfo
;
cfbLoadCursor((unsigned short *)data
);
cfbCursorColor((unsigned int *)data
);
cfbLoadColorMap((ColorMap
*)data
);
printf("cfb0: Unknown ioctl command %x\n", cmd
);
struct pmax_fb
*fp
= &cfbfb
;
if (fp
->fbu
->scrInfo
.qe
.eHead
!= fp
->fbu
->scrInfo
.qe
.eTail
)
* Return the physical page number that corresponds to byte offset 'off'.
len
= pmax_round_page(((vm_offset_t
)&cfbu
& PGOFSET
) + sizeof(cfbu
));
return pmax_btop(MACH_CACHED_TO_PHYS(&cfbu
) + off
);
if (off
>= cfbfb
.fr_size
)
return pmax_btop(MACH_UNCACHED_TO_PHYS(cfbfb
.fr_addr
) + off
);
static u_char cursor_RGB
[6]; /* cursor color 2 & 3 */
* XXX This assumes 2bits/cursor pixel so that the 1Kbyte cursor RAM
* defines a 64x64 cursor. If the bt459 does not map the cursor RAM
* this way, this code is Screwed!
register int i
, j
, k
, pos
;
register u_short ap
, bp
, out
;
* Fill in the cursor sprite using the A and B planes, as provided
* XXX This will have to change when the X server knows that this
for (k
= 0; k
< 16; k
++) {
for (i
= 0; i
< 4; i
++) {
out
= (out
<< 2) | ((ap
& 0x1) << 1) |
out
= ((out
>> 2) & 0x3f) |
bt459_set_cursor_ram(pos
, out
);
bt459_set_cursor_ram(pos
, 0);
bt459_set_cursor_ram(pos
, 0);
* Set a cursor ram value.
bt459_set_cursor_ram(pos
, val
)
register bt459_regmap_t
*regs
= (bt459_regmap_t
*)
(cfbfb
.fr_addr
+ CFB_OFFSET_BT459
);
bt459_write_reg(regs
, BT459_REG_CRAM_BASE
+ pos
, val
);
nval
= bt459_read_reg(regs
, BT459_REG_CRAM_BASE
+ pos
);
} while (val
!= nval
&& ++cnt
< 10);
* Generic register access
bt459_select_reg(regs
, regno
)
regs
->addr_hi
= regno
>> 8;
bt459_write_reg(regs
, regno
, val
)
regs
->addr_hi
= regno
>> 8;
bt459_read_reg(regs
, regno
)
regs
->addr_hi
= regno
>> 8;
register bt459_regmap_t
*regs
;
register struct pmax_fb
*fp
= &cfbfb
;
/* check for no frame buffer */
fp
->fr_addr
= (char *)(cp
+ CFB_OFFSET_VRAM
);
fp
->fr_size
= CFB_FB_SIZE
;
* Must be in Uncached space since the fbuaccess structure is
* mapped into the user's address space uncached.
fp
->fbu
= (struct fbuaccess
*)
MACH_PHYS_TO_UNCACHED(MACH_CACHED_TO_PHYS(&cfbu
));
fp
->posCursor
= cfbPosCursor
;
if (tb_kbdmouseconfig(fp
))
regs
= (bt459_regmap_t
*)(fp
->fr_addr
+ CFB_OFFSET_BT459
);
if (bt459_read_reg(regs
, BT459_REG_ID
) != 0x4a)
*(volatile int *)(fp
->fr_addr
+ CFB_OFFSET_RESET
) = 0;
DELAY(2000); /* ???? check right time on specs! ???? */
bt459_write_reg(regs
, BT459_REG_CMD0
, 0x40);
/* no zooming, no panning */
bt459_write_reg(regs
, BT459_REG_CMD1
, 0x00);
* signature test, X-windows cursor, no overlays, SYNC* PLL,
* normal RAM select, 7.5 IRE pedestal, do sync
bt459_write_reg(regs
, BT459_REG_CMD2
, 0xc2);
bt459_write_reg(regs
, BT459_REG_CMD2
, 0xc0);
bt459_write_reg(regs
, BT459_REG_PRM
, 0xff);
bt459_write_reg(regs
, BT459_REG_PBM
, 0x00);
bt459_write_reg(regs
, BT459_REG_ORM
, 0x00);
bt459_write_reg(regs
, BT459_REG_OBM
, 0x00);
/* no interleave, no underlay */
bt459_write_reg(regs
, BT459_REG_ILV
, 0x00);
/* normal operation, no signature analysis */
bt459_write_reg(regs
, BT459_REG_TEST
, 0x00);
* no blinking, 1bit cross hair, XOR reg&crosshair,
* no crosshair on either plane 0 or 1,
* regular cursor on both planes.
bt459_write_reg(regs
, BT459_REG_CCR
, 0xc0);
bt459_write_reg(regs
, BT459_REG_CXLO
, 0x00);
bt459_write_reg(regs
, BT459_REG_CXHI
, 0x00);
bt459_write_reg(regs
, BT459_REG_CYLO
, 0x00);
bt459_write_reg(regs
, BT459_REG_CYHI
, 0x00);
/* no crosshair window */
bt459_write_reg(regs
, BT459_REG_WXLO
, 0x00);
bt459_write_reg(regs
, BT459_REG_WXHI
, 0x00);
bt459_write_reg(regs
, BT459_REG_WYLO
, 0x00);
bt459_write_reg(regs
, BT459_REG_WYHI
, 0x00);
bt459_write_reg(regs
, BT459_REG_WWLO
, 0x00);
bt459_write_reg(regs
, BT459_REG_WWHI
, 0x00);
bt459_write_reg(regs
, BT459_REG_WHLO
, 0x00);
bt459_write_reg(regs
, BT459_REG_WHHI
, 0x00);
* Initialize screen info.
fp
->fbu
->scrInfo
.max_row
= 56;
fp
->fbu
->scrInfo
.max_col
= 80;
fp
->fbu
->scrInfo
.max_x
= 1024;
fp
->fbu
->scrInfo
.max_y
= 864;
fp
->fbu
->scrInfo
.max_cur_x
= 1023;
fp
->fbu
->scrInfo
.max_cur_y
= 863;
fp
->fbu
->scrInfo
.version
= 11;
fp
->fbu
->scrInfo
.mthreshold
= 4;
fp
->fbu
->scrInfo
.mscale
= 2;
fp
->fbu
->scrInfo
.min_cur_x
= 0;
fp
->fbu
->scrInfo
.min_cur_y
= 0;
fp
->fbu
->scrInfo
.qe
.timestamp_ms
= TO_MS(time
);
fp
->fbu
->scrInfo
.qe
.eSize
= PM_MAXEVQ
;
fp
->fbu
->scrInfo
.qe
.eHead
= fp
->fbu
->scrInfo
.qe
.eTail
= 0;
fp
->fbu
->scrInfo
.qe
.tcSize
= MOTION_BUFFER_SIZE
;
fp
->fbu
->scrInfo
.qe
.tcNext
= 0;
* Initialize the color map, the screen, and the mouse.
if (cn_tab
.cn_fb
== (struct pmax_fb
*)0)
* ----------------------------------------------------------------------------
* The screen is initialized.
* ----------------------------------------------------------------------------
register struct pmax_fb
*fp
= &cfbfb
;
* We want an LSI terminal emulation. We want the graphics
* terminal to scroll from the bottom. So start at the bottom.
* Load the cursor with the default values
cfbLoadCursor(defCursor
);
* ----------------------------------------------------------------------------
* Routine to restore the color of the cursor.
* ----------------------------------------------------------------------------
bt459_regmap_t
*regs
= (bt459_regmap_t
*)(cfbfb
.fr_addr
+ CFB_OFFSET_BT459
);
bt459_select_reg(regs
, BT459_REG_CCOLOR_2
);
for (i
= 0; i
< 6; i
++) {
regs
->addr_reg
= cursor_RGB
[i
];
bt459_select_reg(regs
, BT459_REG_CCOLOR_1
);
for (i
= 0; i
< 3; i
++) {
regs
->addr_reg
= cursor_RGB
[i
];
bt459_select_reg(regs
, BT459_REG_CCOLOR_3
);
for (i
= 3; i
< 6; i
++) {
regs
->addr_reg
= cursor_RGB
[i
];
* ----------------------------------------------------------------------------
* Set the color of the cursor.
* ----------------------------------------------------------------------------
cursor_RGB
[i
] = (u_char
)(color
[i
] >> 8);
*----------------------------------------------------------------------
*----------------------------------------------------------------------
bt459_regmap_t
*regs
= (bt459_regmap_t
*)(cfbfb
.fr_addr
+ CFB_OFFSET_BT459
);
register struct pmax_fb
*fp
= &cfbfb
;
if (y
< fp
->fbu
->scrInfo
.min_cur_y
|| y
> fp
->fbu
->scrInfo
.max_cur_y
)
y
= fp
->fbu
->scrInfo
.max_cur_y
;
if (x
< fp
->fbu
->scrInfo
.min_cur_x
|| x
> fp
->fbu
->scrInfo
.max_cur_x
)
x
= fp
->fbu
->scrInfo
.max_cur_x
;
fp
->fbu
->scrInfo
.cursor
.x
= x
; /* keep track of real cursor */
fp
->fbu
->scrInfo
.cursor
.y
= y
; /* position, indep. of mouse */
bt459_select_reg(regs
, BT459_REG_CXLO
);
* ----------------------------------------------------------------------------
* Initialize the color map.
* The colormap is initialized appropriately.
* ----------------------------------------------------------------------------
bt459_regmap_t
*regs
= (bt459_regmap_t
*)(cfbfb
.fr_addr
+ CFB_OFFSET_BT459
);
bt459_select_reg(regs
, 0);
regs
->addr_cmap
= 0; MachEmptyWriteBuffer();
regs
->addr_cmap
= 0; MachEmptyWriteBuffer();
regs
->addr_cmap
= 0; MachEmptyWriteBuffer();
for (i
= 1; i
< 256; i
++) {
regs
->addr_cmap
= 0xff; MachEmptyWriteBuffer();
regs
->addr_cmap
= 0xff; MachEmptyWriteBuffer();
regs
->addr_cmap
= 0xff; MachEmptyWriteBuffer();
for (i
= 0; i
< 3; i
++) {
cursor_RGB
[i
+ 3] = 0xff;
* ----------------------------------------------------------------------------
* The color map is loaded.
* ----------------------------------------------------------------------------
bt459_regmap_t
*regs
= (bt459_regmap_t
*)(cfbfb
.fr_addr
+ CFB_OFFSET_BT459
);
bt459_select_reg(regs
, ptr
->index
);
regs
->addr_cmap
= ptr
->Entry
.red
; MachEmptyWriteBuffer();
regs
->addr_cmap
= ptr
->Entry
.green
; MachEmptyWriteBuffer();
regs
->addr_cmap
= ptr
->Entry
.blue
; MachEmptyWriteBuffer();
u_char color0
[3]; /* saved color map entry zero */
u_char off
; /* TRUE if display is off */
* ----------------------------------------------------------------------------
* Enable the video display.
* The display is enabled.
* ----------------------------------------------------------------------------
bt459_regmap_t
*regs
= (bt459_regmap_t
*)(cfbfb
.fr_addr
+ CFB_OFFSET_BT459
);
/* restore old color map entry zero */
bt459_select_reg(regs
, 0);
regs
->addr_cmap
= vstate
.color0
[0];
regs
->addr_cmap
= vstate
.color0
[1];
regs
->addr_cmap
= vstate
.color0
[2];
/* enable normal display */
bt459_write_reg(regs
, BT459_REG_PRM
, 0xff);
bt459_write_reg(regs
, BT459_REG_CCR
, 0xc0);
* ----------------------------------------------------------------------------
* Disable the video display.
* The display is disabled.
* ----------------------------------------------------------------------------
bt459_regmap_t
*regs
= (bt459_regmap_t
*)(cfbfb
.fr_addr
+ CFB_OFFSET_BT459
);
/* save old color map entry zero */
bt459_select_reg(regs
, 0);
vstate
.color0
[0] = regs
->addr_cmap
;
vstate
.color0
[1] = regs
->addr_cmap
;
vstate
.color0
[2] = regs
->addr_cmap
;
/* set color map entry zero to zero */
bt459_select_reg(regs
, 0);
bt459_write_reg(regs
, BT459_REG_PRM
, 0);
bt459_write_reg(regs
, BT459_REG_CCR
, 0);
* cfb keyboard and mouse input. Just punt to the generic ones in fb.c
fbMouseEvent(newRepPtr
, &cfbfb
);
cfbMouseButtons(newRepPtr
)
fbMouseButtons(newRepPtr
, &cfbfb
);
* Configure the mouse and keyboard based on machine type
switch (pmax_boardtype
) {
dcDivertXInput
= cfbKbdEvent
;
dcMouseEvent
= cfbMouseEvent
;
dcMouseButtons
= cfbMouseButtons
;
sccDivertXInput
= cfbKbdEvent
;
sccMouseEvent
= cfbMouseEvent
;
sccMouseButtons
= cfbMouseButtons
;
dtopDivertXInput
= cfbKbdEvent
;
dtopMouseEvent
= cfbMouseEvent
;
dtopMouseButtons
= cfbMouseButtons
;
printf("Can't configure mouse/keyboard\n");
switch (pmax_boardtype
) {
dcDivertXInput
= (void (*)())0;
dcMouseEvent
= (void (*)())0;
dcMouseButtons
= (void (*)())0;
sccDivertXInput
= (void (*)())0;
sccMouseEvent
= (void (*)())0;
sccMouseButtons
= (void (*)())0;
dtopDivertXInput
= (void (*)())0;
dtopMouseEvent
= (void (*)())0;
dtopMouseButtons
= (void (*)())0;
printf("Can't deconfigure mouse/keyboard\n");