summaryrefslogtreecommitdiff
path: root/chips/pm_misc.c
diff options
context:
space:
mode:
authorThomas Bushnell <thomas@gnu.org>1997-02-25 21:28:37 +0000
committerThomas Bushnell <thomas@gnu.org>1997-02-25 21:28:37 +0000
commitf07a4c844da9f0ecae5bbee1ab94be56505f26f7 (patch)
tree12b07c7e578fc1a5f53dbfde2632408491ff2a70 /chips/pm_misc.c
Initial source
Diffstat (limited to 'chips/pm_misc.c')
-rw-r--r--chips/pm_misc.c594
1 files changed, 594 insertions, 0 deletions
diff --git a/chips/pm_misc.c b/chips/pm_misc.c
new file mode 100644
index 0000000..d423645
--- /dev/null
+++ b/chips/pm_misc.c
@@ -0,0 +1,594 @@
+/*
+ * 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 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: pm_misc.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Driver for the VFB01/02 Mono/Color framebuffer (pmax)
+ * Hardware-independent operations, mostly shared with
+ * the CFB driver (see each individual function header),
+ * and possibly others.
+ */
+
+
+#include <platforms.h>
+
+#include <fb.h>
+
+#if defined(DECSTATION) || defined(FLAMINGO)
+#include <cfb.h>
+#include <mfb.h>
+#include <xcfb.h>
+#include <sfb.h>
+#define NPM (NFB+NCFB+NMFB+NXCFB+NSFB)
+#endif /*DECSTATION*/
+
+#ifdef VAXSTATION
+#define NPM (NFB)
+#endif /*VAXSTATION*/
+
+
+#if (NPM > 0)
+
+#include <mach/vm_param.h> /* PAGE_SIZE */
+#include <device/device_types.h>
+#include <vm/vm_map.h> /* kernel_pmap */
+
+#include <chips/screen_defs.h>
+#include <chips/pm_defs.h>
+
+
+#ifdef DECSTATION
+#define machine_btop mips_btop
+#define MONO_BM (256*1024)
+#endif /*DECSTATION*/
+
+#ifdef VAXSTATION
+#define machine_btop vax_btop
+/*
+ For now we use the last page of the frame for
+ the user_info structure.
+*/
+#define MONO_BM (256*1024-PAGE_SIZE)
+#endif /*VAXSTATION*/
+
+#ifdef FLAMINGO
+#define machine_btop alpha_btop
+#define MONO_BM (256*1024)
+#define LOG2_SIZEOF_LONG 3 /* 64bit archies */
+#endif /* FLAMINGO */
+
+#ifndef LOG2_SIZEOF_LONG
+#define LOG2_SIZEOF_LONG 2 /* 32bit archies */
+#endif
+
+
+/* Hardware state */
+pm_softc_t pm_softc_data[NPM];
+
+pm_softc_t*
+pm_alloc(
+ int unit,
+ char *cur,
+ unsigned char *fb,
+ unsigned char *pl)
+{
+ pm_softc_t *pm = &pm_softc_data[unit];
+
+ pm->cursor_registers = cur;
+ pm->framebuffer = fb;
+ pm->plane_mask = pl;
+ pm->vdac_registers = 0; /* later, if ever */
+
+ screen_attach(unit, (char *) pm);
+
+ return pm;
+}
+
+
+/*
+ * Routine to paint a char on a simple framebuffer.
+ * This is common to the pm, fb and cfb drivers.
+ */
+pm_char_paint(
+ screen_softc_t sc,
+ int c,
+ int row,
+ int col)
+{
+ register int incr;
+ int line_size;
+ register unsigned char *font, *bmap;
+ pm_softc_t *pm = (pm_softc_t*)sc->hw_state;
+
+ /*
+ * Here are the magic numbers that drive the loops below:
+ * incr bytes between scanlines of the glyph
+ * line_size bytes in a row, using the system font
+ *
+ * This code has been optimized to avoid multiplications,
+ * and is therefore much less obvious than it could be.
+ */
+ if (sc->flags & MONO_SCREEN) {
+ /*
+ * B&W screen: 1 bit/pixel
+ * incr --> 1 * BytesPerLine, with possible stride
+ */
+ incr = sc->frame_scanline_width >> 3;
+ } else {
+ /*
+ * Color screen: 8 bits/pixel
+ * incr --> 8 * BytesPerLine, with possible stride
+ */
+ incr = sc->frame_scanline_width;
+ col <<= 3;
+ }
+
+ /* not all compilers are smart about multiply by 15 */
+#if (KfontHeight==15)
+# define TIMES_KfontHeight(w) (((w)<<4)-(w))
+#else
+# define TIMES_KfontHeight(w) ((w)*KfontHeight)
+#endif
+ line_size = TIMES_KfontHeight(incr);
+
+ bmap = pm->framebuffer + col + (row * line_size);
+ font = &kfont_7x14[ (int)(c - ' ') * 15];
+ if (sc->flags & MONO_SCREEN) {
+ /*
+ * Unroll simple loops, take note of common cases
+ */
+ if (sc->standout) {
+# define mv() *bmap = ~*font++; bmap += incr;
+ mv();mv();mv();mv();mv();mv();mv();mv();
+ mv();mv();mv();mv();mv();mv();mv();
+# undef mv
+ } else if (c == ' ') {
+# define mv() *bmap = 0; bmap += incr;
+ mv();mv();mv();mv();mv();mv();mv();mv();
+ mv();mv();mv();mv();mv();mv();mv();
+# undef mv
+ } else {
+# define mv() *bmap = *font++; bmap += incr;
+ mv();mv();mv();mv();mv();mv();mv();mv();
+ mv();mv();mv();mv();mv();mv();mv();
+# undef mv
+ }
+ } else {
+ /*
+ * 8 bits per pixel --> paint one byte per each font bit.
+ * In order to spread out the 8 bits of a glyph line over
+ * the 64 bits per scanline use a simple vector multiply,
+ * taking 4 bits at a time to get the two resulting words
+ */
+ static unsigned int spread[16] = {
+ 0x00000000, 0x00000001, 0x00000100, 0x00000101,
+ 0x00010000, 0x00010001, 0x00010100, 0x00010101,
+ 0x01000000, 0x01000001, 0x01000100, 0x01000101,
+ 0x01010000, 0x01010001, 0x01010100, 0x01010101,
+ };
+ register int rev_video = sc->standout;
+ register int j;
+ for (j = 0; j < KfontHeight; j++) {
+ register unsigned char c = *font++;
+ if (rev_video) c = ~c;
+#if (LOG2_SIZEOF_LONG==3)
+ *((long*)bmap) = (long)spread[ c & 0xf ] |
+ ((long)(spread[ (c>>4) & 0xf ]) << 32);
+#else
+ ((int*)bmap)[0] = spread[ c & 0xf ];
+ ((int*)bmap)[1] = spread[ (c>>4) & 0xf ];
+#endif
+ bmap += incr;
+ }
+ }
+}
+
+/*
+ * Delete the line at the given row.
+ * This is common to the pm, fb and cfb drivers.
+ */
+pm_remove_line(
+ screen_softc_t sc,
+ short row)
+{
+ register long *dest, *src;
+ register long *end;
+ register long temp0,temp1,temp2,temp3;
+ register long i, scaninc, blockcnt;
+ long line_size, incr;
+ unsigned char *framebuffer;
+ pm_softc_t *pm = (pm_softc_t*)sc->hw_state;
+ long CharRows, CharCols;
+
+ CharRows = sc->up->max_row;
+ CharCols = sc->up->max_col;
+ framebuffer = pm->framebuffer;
+
+ /* Inner loop works 4 long words at a time (writebuffer deep) */
+# define BlockSizeShift (2+LOG2_SIZEOF_LONG)
+
+ /* To copy one (MONO) line, we need to iterate this many times */
+# define Blocks (CharCols>>BlockSizeShift)
+
+ /* Skip this many bytes to get to the next line */
+# define Slop(w) ((w) - (blockcnt<<BlockSizeShift))
+
+ if (sc->flags & MONO_SCREEN) {
+ blockcnt = Blocks;
+ /* See comments in pm_char_paint() */
+ incr = sc->frame_scanline_width >> 3;
+ } else {
+ blockcnt = Blocks << 3;
+ /* See comments in pm_char_paint() */
+ incr = sc->frame_scanline_width;
+ }
+ line_size = TIMES_KfontHeight(incr);
+
+ scaninc = (Slop(incr)) >> LOG2_SIZEOF_LONG; /* pointers are long* */
+
+ dest = (long *)(framebuffer + row * line_size);
+ src = (long *)((char*)dest + line_size);
+ end = (long *)(framebuffer + CharRows * line_size);
+ while (src < end) {
+ i = 0;
+ do {
+ temp0 = src[0];
+ temp1 = src[1];
+ temp2 = src[2];
+ temp3 = src[3];
+ dest[0] = temp0;
+ dest[1] = temp1;
+ dest[2] = temp2;
+ dest[3] = temp3;
+ dest += 4;
+ src += 4;
+ i++;
+ } while (i < blockcnt);
+ src += scaninc;
+ dest += scaninc;
+ }
+
+ /* Now zero out the last line */
+ bzero(framebuffer + (CharRows - 1) * line_size, line_size);
+
+ ascii_screen_rem_update(sc, row);
+}
+
+
+/*
+ * Open a new blank line at the given row.
+ * This is common to the pm, fb and cfb drivers.
+ */
+pm_insert_line(
+ screen_softc_t sc,
+ short row)
+{
+ register long *dest, *src;
+ register long *end;
+ register long temp0,temp1,temp2,temp3;
+ register long i, scaninc, blockcnt;
+ long line_size, incr;
+ unsigned char *framebuffer;
+ pm_softc_t *pm = (pm_softc_t*)sc->hw_state;
+ long CharRows, CharCols;
+
+ CharRows = sc->up->max_row;
+ CharCols = sc->up->max_col;
+
+ framebuffer = pm->framebuffer;
+
+ /* See above for comments */
+ if (sc->flags & MONO_SCREEN) {
+ blockcnt = Blocks;
+ /* See comments in pm_char_paint() */
+ incr = sc->frame_scanline_width >> 3;
+ } else {
+ blockcnt = Blocks << 3;
+ /* See comments in pm_char_paint() */
+ incr = sc->frame_scanline_width;
+ }
+ line_size = TIMES_KfontHeight(incr);
+
+ scaninc = Slop(incr) + ((2 * blockcnt) << BlockSizeShift);
+ scaninc >>= LOG2_SIZEOF_LONG; /* pointers are long* */
+ dest = (long *)(framebuffer + (CharRows - 1) * line_size);
+ src = (long *)((char*)dest - line_size);
+ end = (long *)(framebuffer + row * line_size);
+ while (src >= end) {
+ i = 0;
+ do {
+ temp0 = src[0];
+ temp1 = src[1];
+ temp2 = src[2];
+ temp3 = src[3];
+ dest[0] = temp0;
+ dest[1] = temp1;
+ dest[2] = temp2;
+ dest[3] = temp3;
+ dest += 4;
+ src += 4;
+ i++;
+ } while (i < blockcnt);
+ src -= scaninc;
+ dest -= scaninc;
+ }
+
+ /* Now zero out the line being opened */
+ bzero(framebuffer + row * line_size, line_size);
+
+ ascii_screen_ins_update(sc, row);
+}
+
+#undef Slop
+
+
+/*
+ * Initialize screen parameters in the
+ * user-mapped descriptor.
+ * This is common to various drivers.
+ */
+pm_init_screen_params(
+ screen_softc_t sc,
+ user_info_t *up)
+{
+ register int vis_x, vis_y;
+
+ up->frame_scanline_width = sc->frame_scanline_width;
+ up->frame_height = sc->frame_height;
+
+ vis_x = sc->frame_visible_width;
+ vis_y = sc->frame_visible_height;
+
+ up->max_x = vis_x;
+ up->max_y = vis_y;
+ up->max_cur_x = vis_x - 1;
+ up->max_cur_y = vis_y - 1;
+ up->min_cur_x = -15;
+ up->min_cur_y = -15;
+ up->max_row = vis_y / KfontHeight;
+ up->max_col = vis_x / KfontWidth;
+
+ up->version = 11;
+
+ up->mouse_threshold = 4;
+ up->mouse_scale = 2;
+
+ up->dev_dep_2.pm.tablet_scale_x = ((vis_x - 1) * 1000) / 2200;
+ up->dev_dep_2.pm.tablet_scale_y = ((vis_y - 1) * 1000) / 2200;
+}
+
+/*
+ * Clear the screen
+ * Used by pm, fb and cfb
+ */
+pm_clear_bitmap(
+ screen_softc_t sc)
+{
+ pm_softc_t *pm = (pm_softc_t *) sc->hw_state;
+ unsigned int screen_size;
+
+ /* Do not touch the non visible part */
+ screen_size = sc->frame_scanline_width * sc->frame_visible_height;
+ blkclr((char *)pm->framebuffer,
+ (sc->flags & MONO_SCREEN) ? (screen_size>>3) : screen_size);
+
+ /* clear ascii screenmap */
+ ascii_screen_fill(sc, ' ');
+}
+
+
+/*
+ * Size of the user-mapped structure
+ * Used by both pm and cfb
+ */
+pm_mem_need()
+{
+ return USER_INFO_SIZE;
+}
+
+/*
+ * Device-specific get status.
+ * Used by fb and cfb also.
+ */
+pm_get_status(
+ screen_softc_t sc,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ natural_t *status_count)
+{
+ if (flavor == SCREEN_GET_OFFSETS) {
+ unsigned *offs = (unsigned *) status;
+
+ offs[0] = PM_SIZE(sc); /* virtual size */
+ offs[1] = 0; /* offset of user_info_t */
+ *status_count = 2;
+ return D_SUCCESS;
+ } else
+ return D_INVALID_OPERATION;
+}
+
+/*
+ * Driver-specific set status
+ * Only partially used by fb and cfb.
+ */
+pm_set_status(
+ screen_softc_t sc,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ natural_t status_count)
+{
+ switch (flavor) {
+ case SCREEN_ADJ_MAPPED_INFO: {
+ unsigned user_addr = *(unsigned *) status;
+ user_info_t *up = sc->up;
+
+ /* Make it point to the event_queue, in user virtual */
+ up->evque.events = (screen_event_t *)(user_addr +
+ ((char*)up->event_queue - (char*)up));
+
+ /* Make it point to the point_track, in user virtual */
+ up->evque.track = (screen_timed_point_t *)(user_addr +
+ ((char*)up->point_track - (char*)up));
+
+ up->dev_dep_1.pm.planemask = (unsigned char *)(user_addr + USER_INFO_SIZE);
+
+ up->dev_dep_1.pm.bitmap = up->dev_dep_1.pm.planemask + PMASK_SIZE;
+
+ break;
+ }
+
+ case SCREEN_LOAD_CURSOR: {
+
+ sc->flags |= SCREEN_BEING_UPDATED;
+ dc503_load_cursor(sc->hw_state, (unsigned short*)status);
+ sc->flags &= ~SCREEN_BEING_UPDATED;
+
+ break;
+ }
+
+#ifdef DECSTATION
+ case SCREEN_SET_CURSOR_COLOR: {
+ pm_softc_t *pm = (pm_softc_t*) sc->hw_state;
+
+ sc->flags |= SCREEN_BEING_UPDATED;
+ bt478_cursor_color (pm->vdac_registers, (cursor_color_t*) status);
+ sc->flags &= ~SCREEN_BEING_UPDATED;
+
+ break;
+ }
+
+ case SCREEN_SET_CMAP_ENTRY: {
+ pm_softc_t *pm = (pm_softc_t*) sc->hw_state;
+ color_map_entry_t *e = (color_map_entry_t*) status;
+
+ if (e->index < 256) {
+ sc->flags |= SCREEN_BEING_UPDATED;
+ bt478_load_colormap_entry( pm->vdac_registers, e->index, &e->value);
+ sc->flags &= ~SCREEN_BEING_UPDATED;
+ }
+
+ break;
+ }
+#endif /*DECSTATION*/
+ default:
+ return D_INVALID_OPERATION;
+ }
+ return D_SUCCESS;
+}
+
+/*
+ * Map pages to user space
+ */
+vm_offset_t pm_map_page_empty = (vm_offset_t) 0;
+
+integer_t
+pm_map_page(
+ screen_softc_t sc,
+ vm_offset_t off,
+ int prot)
+{
+ int bitmapsize;
+ integer_t addr;
+ pm_softc_t *pm = (pm_softc_t *)sc->hw_state;
+ extern vm_offset_t pmap_extract( pmap_t map, vm_offset_t addr);
+
+ bitmapsize = BITMAP_SIZE(sc);
+
+#define OFF0 USER_INFO_SIZE /* user mapped info */
+#define OFF1 OFF0+PMASK_SIZE /* plane mask register */
+#define OFF2 OFF1+bitmapsize /* frame buffer mem */
+
+ if (off < OFF0)
+#ifdef DECSTATION
+ addr = kvtophys(sc->up);
+#else
+ addr = (integer_t) pmap_extract(kernel_pmap,
+ (vm_offset_t)sc->up);
+#endif
+ else
+ if (off < OFF1) {
+#ifdef VAXSTATION
+ if (pm_map_page_empty == 0) {
+ pm_map_page_empty = vm_page_grab_phys_addr();
+ }
+ addr = (integer_t)pmap_extract(kernel_pmap, pm_map_page_empty);
+#else
+ addr = (integer_t) pm->plane_mask;
+#endif
+ off -= OFF0;
+ } else
+ if (off < OFF2) {
+#ifdef DECSTATION
+ addr = (integer_t)pm->framebuffer;
+#else
+ addr = (integer_t)pmap_extract(kernel_pmap,
+ (vm_offset_t)pm->framebuffer);
+#endif
+ off -= OFF1;
+ } else
+ return D_INVALID_SIZE; /* ??? */
+
+ addr = machine_btop(addr + off);
+ return (addr);
+}
+
+
+/*
+ *-----------------------------------------------------------
+ * The rest of this file is stricly pmax/pvax-specific
+ *-----------------------------------------------------------
+ */
+#if (NFB > 0)
+
+/*
+ * Do what's needed when the X server exits
+ */
+pm_soft_reset(
+ screen_softc_t sc)
+{
+ pm_softc_t *pm = (pm_softc_t*) sc->hw_state;
+ user_info_t *up = sc->up;
+
+ /*
+ * Restore params in mapped structure
+ */
+ pm_init_screen_params(sc, up);
+ up->row = up->max_row - 2;
+ dc503_init(pm);
+
+#ifdef DECSTATION
+ if (sc->flags & MONO_SCREEN)
+ bt478_init_bw_map(pm->vdac_registers, pm->plane_mask);
+ else
+ bt478_init_color_map(pm->vdac_registers, pm->plane_mask);
+#endif /*DECSTATION*/
+}
+#endif /* NFB > 0 */
+
+
+#endif /* NPM > 0 */