/* * 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: bt459.c * Author: Alessandro Forin, Carnegie Mellon University * Date: 9/90 * * Routines for the bt459 RAMDAC */ #include #include #include #ifdef DECSTATION typedef struct { volatile unsigned char addr_lo; char pad0[3]; volatile unsigned char addr_hi; char pad1[3]; volatile unsigned char addr_reg; char pad2[3]; volatile unsigned char addr_cmap; char pad3[3]; } bt459_ds_padded_regmap_t; #define bt459_padded_regmap_t bt459_ds_padded_regmap_t #define mb() /* no write/read reordering problems */ #endif /* DECSTATION */ #ifdef FLAMINGO /* Sparse space ! */ typedef struct { volatile unsigned int addr_lo; int pad0; volatile unsigned int addr_hi; int pad1; volatile unsigned int addr_reg; int pad2; volatile unsigned int addr_cmap; int pad3; } bt459_fl_padded_regmap_t; #define bt459_padded_regmap_t bt459_fl_padded_regmap_t #define mb() wbflush() #endif /* FLAMINGO */ #ifndef bt459_padded_regmap_t typedef bt459_regmap_t bt459_padded_regmap_t; #define wbflush() #endif /* * Generic register access */ #define bt459_select_reg_macro(r,n) \ (r)->addr_lo = (n); mb(); \ (r)->addr_hi = (n) >> 8; \ wbflush(); void bt459_select_reg( bt459_padded_regmap_t *regs, int regno) { bt459_select_reg_macro( regs, regno); } void bt459_write_reg( bt459_padded_regmap_t *regs, int regno, unsigned char val) { bt459_select_reg_macro( regs, regno ); regs->addr_reg = val; wbflush(); } unsigned char bt459_read_reg( bt459_padded_regmap_t *regs, int regno) { bt459_select_reg_macro( regs, regno ); return regs->addr_reg; } /* * Color map */ bt459_load_colormap_entry( bt459_padded_regmap_t *regs, int entry, color_map_t *map) { bt459_select_reg(regs, entry & 0xff); regs->addr_cmap = map->red; wbflush(); regs->addr_cmap = map->green; wbflush(); regs->addr_cmap = map->blue; wbflush(); } bt459_init_colormap( bt459_padded_regmap_t *regs) { register int i; bt459_select_reg(regs, 0); regs->addr_cmap = 0; wbflush(); regs->addr_cmap = 0; wbflush(); regs->addr_cmap = 0; wbflush(); regs->addr_cmap = 0xff; wbflush(); regs->addr_cmap = 0xff; wbflush(); regs->addr_cmap = 0xff; wbflush(); bt459_select_reg(regs, 255); regs->addr_cmap = 0xff; wbflush(); regs->addr_cmap = 0xff; wbflush(); regs->addr_cmap = 0xff; wbflush(); } #if 1/*debug*/ bt459_print_colormap( bt459_padded_regmap_t *regs) { register int i; for (i = 0; i < 256; i++) { register unsigned char red, green, blue; bt459_select_reg(regs, i); red = regs->addr_cmap; wbflush(); green = regs->addr_cmap; wbflush(); blue = regs->addr_cmap; wbflush(); printf("%x->[x%x x%x x%x]\n", i, red, green, blue); } } #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 { bt459_padded_regmap_t *regs; unsigned short off; }; bt459_video_off( struct vstate *vstate, user_info_t *up) { register bt459_padded_regmap_t *regs = vstate->regs; unsigned char *save; if (vstate->off) return; /* Yes, this is awful */ save = (unsigned char *)up->dev_dep_2.gx.colormap; bt459_select_reg(regs, 0); *save++ = regs->addr_cmap; *save++ = regs->addr_cmap; *save++ = regs->addr_cmap; bt459_select_reg(regs, 0); regs->addr_cmap = 0; wbflush(); regs->addr_cmap = 0; wbflush(); regs->addr_cmap = 0; wbflush(); bt459_write_reg( regs, BT459_REG_PRM, 0); bt459_write_reg( regs, BT459_REG_CCR, 0); vstate->off = 1; } bt459_video_on( struct vstate *vstate, user_info_t *up) { register bt459_padded_regmap_t *regs = vstate->regs; unsigned char *save; if (!vstate->off) return; /* Like I said.. */ save = (unsigned char *)up->dev_dep_2.gx.colormap; bt459_select_reg(regs, 0); regs->addr_cmap = *save++; wbflush(); regs->addr_cmap = *save++; wbflush(); regs->addr_cmap = *save++; wbflush(); bt459_write_reg( regs, BT459_REG_PRM, 0xff); bt459_write_reg( regs, BT459_REG_CCR, 0xc0); vstate->off = 0; } /* * Cursor */ bt459_pos_cursor( bt459_padded_regmap_t *regs, register int x, register int y) { #define lo(v) ((v)&0xff) #define hi(v) (((v)&0xf00)>>8) bt459_write_reg( regs, BT459_REG_CXLO, lo(x + 219)); bt459_write_reg( regs, BT459_REG_CXHI, hi(x + 219)); bt459_write_reg( regs, BT459_REG_CYLO, lo(y + 34)); bt459_write_reg( regs, BT459_REG_CYHI, hi(y + 34)); } bt459_cursor_color( bt459_padded_regmap_t *regs, color_map_t *color) { register int i; bt459_select_reg_macro( regs, BT459_REG_CCOLOR_2); for (i = 0; i < 2; i++) { regs->addr_reg = color->red; wbflush(); regs->addr_reg = color->green; wbflush(); regs->addr_reg = color->blue; wbflush(); color++; } } bt459_cursor_sprite( bt459_padded_regmap_t *regs, unsigned char *cursor) { register int i, j; /* * As per specs, must run a check to see if we * had contention. If so, re-write the cursor. */ for (i = 0, j = 0; j < 2; j++) { /* loop once to write */ for ( ; i < 1024; i++) bt459_write_reg( regs, BT459_REG_CRAM_BASE+i, cursor[i]); /* loop to check, if fail write again */ for (i = 0; i < 1024; i++) if (bt459_read_reg( regs, BT459_REG_CRAM_BASE+i) != cursor[i]) break; if (i == 1024) break;/* all is well now */ } } /* * Initialization */ bt459_init( bt459_padded_regmap_t *regs, volatile char *reset, int mux) { if (bt459_read_reg(regs, BT459_REG_ID) != 0x4a) panic("bt459"); if (mux == 4) { /* use 4:1 input mux */ bt459_write_reg( regs, BT459_REG_CMD0, 0x40); } else if (mux == 5) { /* use 5:1 input mux */ bt459_write_reg( regs, BT459_REG_CMD0, 0xc0); } /* else donno */ *reset = 0; /* force chip reset */ /* 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); /* get all pixel bits */ bt459_write_reg( regs, BT459_REG_PRM, 0xff); /* no blinking */ bt459_write_reg( regs, BT459_REG_PBM, 0x00); /* no overlay */ bt459_write_reg( regs, BT459_REG_ORM, 0x00); /* no overlay blink */ 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); /* home cursor */ 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); }