* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
* This code is derived from software contributed to Berkeley by
* Ralph Campbell and Rick Macklem.
* %sccs.include.redist.c%
* @(#)xcfb.c 8.1 (Berkeley) %G%
* 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.
* 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)";
#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/xcfbreg.h>
#include <pmax/dev/dtopreg.h>
#include <pmax/dev/fbreg.h>
* These need to be mapped into user space.
static void xcfbScreenInit();
static void xcfbLoadCursor();
static void xcfbRestoreCursorColor();
static void xcfbCursorColor();
static void xcfbInitColorMap();
static void xcfbLoadColorMap();
static u_int
ims332_read_register();
static void ims332_write_register();
static void ims332_load_colormap_entry();
static void ims332_video_off();
static void ims332_video_on();
void xcfbKbdEvent(), xcfbMouseEvent(), xcfbMouseButtons();
extern void dtopKBDPutc();
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 xcfbdriver
= {
* Test to see if device is present.
* Return true if found and initialized ok.
register struct pmax_ctlr
*cp
;
register struct pmax_fb
*fp
= &xcfbfb
;
if (pmax_boardtype
!= DS_MAXINE
)
if (!fp
->initialized
&& !xcfbinit())
printf("xcfb0 (color display)\n");
register struct pmax_fb
*fp
= &xcfbfb
;
* 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
);
dtopDivertXInput
= xcfbKbdEvent
;
dtopMouseEvent
= xcfbMouseEvent
;
dtopMouseButtons
= xcfbMouseButtons
;
register struct pmax_fb
*fp
= &xcfbfb
;
dtopDivertXInput
= (void (*)())0;
dtopMouseEvent
= (void (*)())0;
dtopMouseButtons
= (void (*)())0;
bzero((caddr_t
)fp
->fr_addr
, 1024 * 768);
xcfbPosCursor(fp
->col
* 8, fp
->row
* 15);
xcfbioctl(dev
, cmd
, data
, flag
, p
)
register struct pmax_fb
*fp
= &xcfbfb
;
return (fbmmap(fp
, dev
, data
, p
));
fp
->fbu
->scrInfo
.mouse
= *(pmCursor
*)data
;
xcfbPosCursor(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
;
xcfbLoadCursor((unsigned short *)data
);
xcfbCursorColor((unsigned int *)data
);
xcfbLoadColorMap((ColorMap
*)data
);
dtopDivertXInput
= xcfbKbdEvent
;
dtopMouseEvent
= xcfbMouseEvent
;
dtopMouseButtons
= xcfbMouseButtons
;
dtopDivertXInput
= (void (*)())0;
dtopMouseEvent
= (void (*)())0;
dtopMouseButtons
= (void (*)())0;
xcfbRestoreCursorColor();
printf("xcfb0: Unknown ioctl command %x\n", cmd
);
* Return the physical page number that corresponds to byte offset 'off'.
len
= pmax_round_page(((vm_offset_t
)&xcfbu
& PGOFSET
) + sizeof(xcfbu
));
return pmax_btop(MACH_CACHED_TO_PHYS(&xcfbu
) + off
);
if (off
>= xcfbfb
.fr_size
)
return pmax_btop(MACH_UNCACHED_TO_PHYS(xcfbfb
.fr_addr
) + off
);
struct pmax_fb
*fp
= &xcfbfb
;
if (fp
->fbu
->scrInfo
.qe
.eHead
!= fp
->fbu
->scrInfo
.qe
.eTail
)
static u_char cursor_RGB
[6]; /* cursor color 2 & 3 */
* Routines for the Inmos IMS-G332 Colour video controller
* Author: Alessandro Forin, Carnegie Mellon University
ims332_read_register(regno
)
register u_char
*regs
= (u_char
*)IMS332_ADDRESS
;
rptr
= regs
+ 0x80000 + (regno
<< 4);
val
= *((volatile u_short
*) rptr
);
v1
= *((volatile u_short
*) regs
);
return (val
& 0xffff) | ((v1
& 0xff00) << 8);
ims332_write_register(regno
, val
)
register unsigned int val
;
register u_char
*regs
= (u_char
*)IMS332_ADDRESS
;
wptr
= regs
+ 0xa0000 + (regno
<< 4);
*((volatile u_int
*)(regs
)) = (val
>> 8) & 0xff00;
*((volatile u_short
*)(wptr
)) = val
;
#define assert_ims332_reset_bit(r) *r &= ~0x40
#define deassert_ims332_reset_bit(r) *r |= 0x40
ims332_load_colormap_entry(ptr
->index
, ptr
);
ims332_load_colormap_entry(entry
, map
)
ims332_write_register(IMS332_REG_LUT_BASE
+ (entry
& 0xff),
(map
->Entry
.blue
<< 16) |
(map
->Entry
.green
<< 8) |
m
.Entry
.red
= m
.Entry
.green
= m
.Entry
.blue
= 0;
ims332_load_colormap_entry(0, &m
);
m
.Entry
.red
= m
.Entry
.green
= m
.Entry
.blue
= 0xff;
for (i
= 1; i
< 256; i
++)
ims332_load_colormap_entry(i
, &m
);
for (i
= 0; i
< 3; i
++) {
cursor_RGB
[i
+ 3] = 0xff;
xcfbRestoreCursorColor();
* 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
xcfb_vstate
.save
= ims332_read_register(IMS332_REG_LUT_BASE
);
ims332_write_register(IMS332_REG_LUT_BASE
, 0);
ims332_write_register(IMS332_REG_COLOR_MASK
, 0);
csr
= ims332_read_register(IMS332_REG_CSR_A
);
csr
|= IMS332_CSR_A_DISABLE_CURSOR
;
ims332_write_register(IMS332_REG_CSR_A
, csr
);
ims332_write_register(IMS332_REG_LUT_BASE
, xcfb_vstate
.save
);
ims332_write_register(IMS332_REG_COLOR_MASK
, 0xffffffff);
csr
= ims332_read_register(IMS332_REG_CSR_A
);
csr
&= ~IMS332_CSR_A_DISABLE_CURSOR
;
ims332_write_register(IMS332_REG_CSR_A
, csr
);
register struct pmax_fb
*fp
= &xcfbfb
;
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 */
ims332_write_register(IMS332_REG_CURSOR_LOC
,
((x
& 0xfff) << 12) | (y
& 0xfff));
/* Bg is color[0], Fg is color[1] */
ims332_write_register(IMS332_REG_CURSOR_LUT_0
,
ims332_write_register(IMS332_REG_CURSOR_LUT_1
, 0x7f0000);
ims332_write_register(IMS332_REG_CURSOR_LUT_2
,
* ----------------------------------------------------------------------------
* Set the color of the cursor.
* ----------------------------------------------------------------------------
cursor_RGB
[i
] = (u_char
)(color
[i
] >> 8);
xcfbRestoreCursorColor();
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
< 8; i
++) {
out
= ((out
>> 2) & 0x3fff) |
ims332_write_register(IMS332_REG_CURSOR_RAM
+ pos
, out
);
ims332_write_register(IMS332_REG_CURSOR_RAM
+ pos
, 0);
ims332_write_register(IMS332_REG_CURSOR_RAM
+ pos
, 0);
register u_int
*reset
= (u_int
*)IMS332_RESET_ADDRESS
;
register struct pmax_fb
*fp
= &xcfbfb
;
* Or Cached? A comment in the Mach driver suggests that the X server
* runs faster in cached address space, but the X server is going
* to blow away the data cache whenever it updates the screen, so..
MACH_PHYS_TO_UNCACHED(XINE_PHYS_CFB_START
+ VRAM_OFFSET
);
* 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(&xcfbu
));
fp
->posCursor
= xcfbPosCursor
;
fp
->KBDPutc
= dtopKBDPutc
;
fp
->kbddev
= makedev(DTOPDEV
, DTOPKBD_PORT
);
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(IMS332_REG_BOOT
, 12 | IMS332_BOOT_CLOCK_PLL
);
ims332_write_register(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) */
ims332_write_register(IMS332_REG_HALF_SYNCH
, 0x10);
ims332_write_register(IMS332_REG_BACK_PORCH
, 0x21);
ims332_write_register(IMS332_REG_DISPLAY
, 0x100);
ims332_write_register(IMS332_REG_SHORT_DIS
, 0x5d);
ims332_write_register(IMS332_REG_BROAD_PULSE
, 0x9f);
ims332_write_register(IMS332_REG_V_SYNC
, 0xc);
ims332_write_register(IMS332_REG_V_PRE_EQUALIZE
, 2);
ims332_write_register(IMS332_REG_V_POST_EQUALIZE
, 2);
ims332_write_register(IMS332_REG_V_BLANK
, 0x2a);
ims332_write_register(IMS332_REG_V_DISPLAY
, 0x600);
ims332_write_register(IMS332_REG_LINE_TIME
, 0x146);
ims332_write_register(IMS332_REG_LINE_START
, 0x10);
ims332_write_register(IMS332_REG_MEM_INIT
, 0xa);
ims332_write_register(IMS332_REG_XFER_DELAY
, 0xa);
ims332_write_register(IMS332_REG_COLOR_MASK
, 0xffffff);
* Initialize screen info.
fp
->fbu
->scrInfo
.max_row
= 50;
fp
->fbu
->scrInfo
.max_col
= 80;
fp
->fbu
->scrInfo
.max_x
= 1024;
fp
->fbu
->scrInfo
.max_y
= 768;
fp
->fbu
->scrInfo
.max_cur_x
= 1008;
fp
->fbu
->scrInfo
.max_cur_y
= 752;
fp
->fbu
->scrInfo
.version
= 11;
fp
->fbu
->scrInfo
.mthreshold
= 4;
fp
->fbu
->scrInfo
.mscale
= 2;
fp
->fbu
->scrInfo
.min_cur_x
= -15;
fp
->fbu
->scrInfo
.min_cur_y
= -15;
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;
ims332_write_register(IMS332_REG_CSR_A
,
IMS332_BPP_8
| IMS332_CSR_A_DMA_DISABLE
| IMS332_CSR_A_VTG_ENABLE
);
if (cn_tab
.cn_fb
== (struct pmax_fb
*)0)
* ----------------------------------------------------------------------------
* The screen is initialized.
* ----------------------------------------------------------------------------
register struct pmax_fb
*fp
= &xcfbfb
;
* 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
xcfbLoadCursor(defCursor
);
* xcfb keyboard and mouse input. Just punt to the generic ones in fb.c
xcfbMouseEvent(newRepPtr
)
fbMouseEvent(newRepPtr
, &xcfbfb
);
xcfbMouseButtons(newRepPtr
)
fbMouseButtons(newRepPtr
, &xcfbfb
);