diff --git a/sys/arch/amiga/dev/grf_cv.c b/sys/arch/amiga/dev/grf_cv.c new file mode 100644 index 000000000000..09e465f35ce4 --- /dev/null +++ b/sys/arch/amiga/dev/grf_cv.c @@ -0,0 +1,1238 @@ +/* + * Copyright (c) 1995 Michael Teske + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Ezra Story, by Kari + * Mettinen and by Bernd Ernesti. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "grfcv.h" +#if NGRFCV > 0 + +#undef CV64CONSOLE + +/* + * Graphics routines for the CyberVision 64 board, using the S3 Trio64. + * + * Modified for CV64 from + * Kari Mettinen's Cirrus driver by Michael Teske 10/95 + * For questions mail me at teske@dice2.desy.de + * + * Thanks to Tekelec Airtronic for providing me with a S3 Trio64 documentation. + * Thanks to Bernd 'the fabulous bug-finder' Ernesti for bringing my messy + * source to NetBSD style :) + * + * TODO: + * Hardware Cursor support + * Blitter support + * Remove the white bord in one 8bit mode + * + * BUGS: + * Xamiag24 and grf_cv can crash when you use fvwm with xterm's. + * Use the xterm's with the '-ah' option to avoid this for the moment. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int cv_mondefok __P((struct grfvideo_mode *)); +void cv_boardinit(); +static unsigned short compute_clock __P((unsigned long)); +int cv_getvmode __P((struct grf_softc *, struct grfvideo_mode *)); +int cv_setvmode __P((struct grf_softc *, unsigned int)); +int cv_setmonitor __P((struct grf_softc *, struct grfvideo_mode *)); +int cv_toggle __P((struct grf_softc *,unsigned short)); +int cv_getcmap __P((struct grf_softc *, struct grf_colormap *)); +int cv_putcmap __P((struct grf_softc *, struct grf_colormap *)); +void cv_off __P((struct grf_softc *)); +int cv_blank __P((struct grf_softc *, int *)); +void cv_inittextmode __P((struct grf_softc *)); + +int cv_ioctl __P((register struct grf_softc *gp, int cmd, void *data)); +void grfcvattach __P((struct device *, struct device *, void *)); +int grfcvprint __P((void *, char *)); +int grfcvmatch __P((struct device *, struct cfdata *, void *)); +void cv_memset __P((unsigned char *, unsigned char, int)); + +/* Graphics display definitions. + * These are filled by 'grfconfig' using GRFIOCSETMON. + */ +#define monitor_def_max 8 +static struct grfvideo_mode monitor_def[8] = { + {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0} +}; +static struct grfvideo_mode *monitor_current = &monitor_def[0]; +#define MAXPIXELCLOCK 135000000 /* safety */ + + +/* Console display definition. + * Default hardcoded text mode. This grf_cv is set up to + * use one text mode only, and this is it. You may use + * grfconfig to change the mode after boot. + */ + +/* Console font */ +#define S3FONT kernel_font_8x8 +#define S3FONTX 8 +#define S3FONTY 8 +extern unsigned char S3FONT[]; + +struct grfcvtext_mode cvconsole_mode = { + {255, "", 25000000, 640, 400, 4, 80, 82, 84, 90, 95, 406, + 441, 412, 426, 447}, + S3FONTX, S3FONTY, 80, 506/S3FONTY, S3FONT, 32, 255 +}; + + +/* Console colors */ +unsigned char cvconscolors[3][3] = { /* background, foreground, hilite */ + {0,0x40,0x50}, {152,152,152}, {255,255,255} +}; + +unsigned char pass_toggle; /* passthru status tracker */ + + +/* Board Address of CV64 */ + +static void *cv_boardaddr; +static int cv_fbsize; + +int +grfcv_cnprobe() +{ + int rv; + rv = CN_DEAD; + return(rv); +} + +/* standard driver stuff */ +struct cfdriver grfcvcd = { + NULL, "grfcv", (cfmatch_t)grfcvmatch, grfcvattach, + DV_DULL, sizeof(struct grf_softc), NULL, 0 +}; +static struct cfdata *cfdata; + + +/* Reads from the fb must be done at addr + 0x02000000 */ +#define READ_OFFSET 0x02000000 + +/* + * Get frambuffer memory size. + * phase5 didn't provide the bit in CR36, + * so we have to do it this way. + * Return 0 for 2MB, 1 for 4MB + */ + +static int +cv_has_4mb (volatile char *fb) +{ + volatile unsigned long *testfbw, *testfbr; + + /* write patterns in memory and test if they can be read */ + testfbw = (volatile unsigned long *) fb; + *testfbw = 0x87654321; + testfbr = (volatile unsigned long *)(fb + READ_OFFSET); + if (*testfbr != 0x87654321) + return(0); + /* upper memory region */ + testfbw = (volatile unsigned long *)(fb + 0x00200000); + testfbr = (volatile unsigned long *)(fb + 0x00200000 + READ_OFFSET); + *testfbw = 0x87654321; + if (*testfbr != 0x87654321) + return(0); + *testfbw = 0xAAAAAAAA; + if (*testfbr != 0xAAAAAAAA) + return(0); + *testfbw = 0x55555555; + if (*testfbr != 0x55555555) + return(0); + return(1); +} + +int +grfcvmatch(pdp, cfp, auxp) + struct device *pdp; + struct cfdata *cfp; + void *auxp; +{ + struct zbus_args *zap; + + zap = auxp; + +#ifndef CV64CONSOLE + if (amiga_realconfig == 0) + return(0); +#endif + + /* Lets be Paranoid: Test man and prod id */ + if (zap->manid != 8512 || zap->prodid != 34) + return(0); + + cv_boardaddr = zap->va; + +#ifdef CV64CONSOLE + if (amiga_realconfig == 0) { + cfdata = cfp; + } +#endif + + return(1); +} + +void +grfcvattach(pdp, dp, auxp) + struct device *pdp, *dp; + void *auxp; +{ + static struct grf_softc congrf; + struct zbus_args *zap; + struct grf_softc *gp; + static char attachflag = 0; + + zap = auxp; + + printf("\n"); + + /* make sure id's have matched */ + if (!cv_boardaddr) + return; + + /* do all that messy console/grf stuff */ + if (dp == NULL) + gp = &congrf; + else + gp = (struct grf_softc *)dp; + + if (dp != NULL && congrf.g_regkva != 0) { + /* + * inited earlier, just copy (not device struct) + */ + bcopy(&congrf.g_display, &gp->g_display, + (char *)&gp[1] - (char *)&gp->g_display); + } else { + gp->g_regkva = (volatile caddr_t)cv_boardaddr + READ_OFFSET; + gp->g_fbkva = (volatile caddr_t)cv_boardaddr + 0x01400000; + + gp->g_unit = GRF_CV64_UNIT; + gp->g_mode = cv_mode; + gp->g_conpri = grfcv_cnprobe(); + gp->g_flags = GF_ALIVE; + + /* wakeup the board */ + cv_boardinit(gp); + +#ifdef CV64CONSOLE + grfcv_iteinit(gp); + (void)cv_load_mon(gp, &cvconsole_mode); +#endif + } + + /* + * attach grf (once) + */ + if (amiga_config_found(cfdata, &gp->g_device, gp, grfcvprint)) { + attachflag = 1; + printf("grfcv: CyberVision64 with %dMB being used\n", cv_fbsize/0x100000); + } else { + if (!attachflag) + printf("grfcv unattached!!\n"); + } +} + +int +grfcvprint(auxp, pnp) + void *auxp; + char *pnp; +{ + if (pnp) + printf("ite at %s: ", pnp); + return(UNCONF); +} + + +/* + * Computes M, N, and R values from + * given input frequency. It uses a table of + * precomputed values, to keep CPU time low. + * + * The return value consist of: + * lower byte: Bits 4-0: N Divider Value + * Bits 5-6: R Value for e.g. SR10 or SR12 + * higher byte: Bits 0-6: M divider value for e.g. SR11 or SR13 + */ + +static unsigned short +compute_clock(freq) + unsigned long freq; +{ + + static unsigned char *mnr, *save; /* M, N + R vals */ + unsigned long work_freq, r; + unsigned short erg; + long diff, d2; + + /* 0xBEBC20 = 12.5M */ + /* 0x080BEFC0 = 135M */ + if (freq < 0x00BEBC20 || freq > 0x080BEFC0) { + printf("grfcv: Wrong clock frequency: %dMHz", freq/1000000); + printf("grfcv: Using default frequency: 25MHz"); + freq = 0x017D7840; + } + + mnr = clocks; /* there the vals are stored */ + d2 = 0x7fffffff; + + while (*mnr) { /* mnr vals are 0-terminated */ + work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2); + + r = (mnr[1] >> 5) & 0x03; + if (r != 0) + work_freq=work_freq >> r; /* r is the freq divider */ + + work_freq *= 0x3E8; /* 2nd part of OSC */ + + diff = abs(freq - work_freq); + + if (d2 >= diff) { + d2 = diff; + /* In save are the vals for minimal diff */ + save = mnr; + } + mnr += 2; + } + erg = *((unsigned short *)save); + + return (erg); +} + + +void +cv_boardinit(gp) + struct grf_softc *gp; +{ + unsigned char *ba = gp->g_regkva; + unsigned char test; + unsigned int clockpar; + int i; + + /* Reset board */ + for (i = 0; i < 6; i++) + cv_write_port (0xff, ba - READ_OFFSET); /* Clear all bits */ + + /* Return to operational Mode */ + cv_write_port(0x8004, ba - READ_OFFSET); + + /* Wakeup Chip */ + vgaw(ba, SREG_VIDEO_SUBS_ENABLE, 0x10); + vgaw(ba, SREG_OPTION_SELECT, 0x1); + vgaw(ba, SREG_VIDEO_SUBS_ENABLE, 0x8); + + vgaw(ba, GREG_MISC_OUTPUT_W, 0x23); + + WCrt(ba, CRT_ID_REGISTER_LOCK_1, 0x48); /* unlock S3 VGA regs */ + WCrt(ba, CRT_ID_REGISTER_LOCK_2, 0xA5); /* unlock syscontrol */ + + test = RCrt(ba, CRT_ID_SYSTEM_CONFIG); + test = test | 0x01; /* enable enhaced register access */ + test = test & 0xEF; /* clear bit 4, 0 wait state */ + WCrt(ba, CRT_ID_SYSTEM_CONFIG, test); + + /* + * bit 1=1: enable enhanced mode functions + * bit 4=1: enable linear adressing + */ + vgaw(ba, ECR_ADV_FUNC_CNTL, 0x11); + + /* enable cpu acess, color mode, high 64k page */ + vgaw(ba, GREG_MISC_OUTPUT_W, 0x23); + + /* Cpu base addr */ + WCrt(ba, CRT_ID_EXT_SYS_CNTL_4, 0x0); + + /* Reset. This does nothing, but everyone does it:) */ + WSeq(ba, SEQ_ID_RESET, 0x3); + + WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x1); /* 8 Dot Clock */ + WSeq(ba, SEQ_ID_MAP_MASK, 0xF); /* Enable write planes */ + WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x0); /* Character Font */ + + WSeq(ba, SEQ_ID_MEMORY_MODE, 0x2); /* Complete mem access */ + + WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x6); /* Unlock extensions */ + test = RSeq(ba, SEQ_ID_BUS_REQ_CNTL); /* Bus Request */ + + /* enable 4MB fast Page Mode */ + test = test | 1 << 6; + WSeq(ba, SEQ_ID_BUS_REQ_CNTL, test); + + test = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2); /* Clksyn2 read */ + + /* immediately Clkload bit clear */ + test = test & 0xDF; + WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, test); + + /* Memory CLOCK: 0x3473BC0 = 55 MHz. DO NOT CHANGE IT ! */ + clockpar = compute_clock(0x3473BC0); + + test = (clockpar & 0xFF00) >> 8; + WSeq(ba, SEQ_ID_MCLK_HI, test); /* PLL N-Divider Value */ + + test = clockpar & 0xFF; + WSeq(ba, SEQ_ID_MCLK_LO, test); /* PLL M-Divider Value */ + + /* We now load an 25 MHz, 31 kHz, 640x480 standard VGA Mode. */ + /* DCLK */ + WSeq(ba, SEQ_ID_DCLK_HI, 0x13); + WSeq(ba, SEQ_ID_DCLK_LO, 0x41); + + test = RSeq (ba, SEQ_ID_CLKSYN_CNTL_2); + test = test | 0x22; + + /* DCLK + MCLK Clock immediate load! */ + WSeq(ba,SEQ_ID_CLKSYN_CNTL_2, test); + + /* DCLK load */ + test = vgar(ba, 0x3cc); + test = test | 0x0c; + vgaw(ba, 0x3c2, test); + + /* Clear bit 5 again, prevent further loading. */ + WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, 0x2); + + WCrt(ba, CRT_ID_HOR_TOTAL, 0x5F); + WCrt(ba, CRT_ID_HOR_DISP_ENA_END, 0x4F); + WCrt(ba, CRT_ID_START_HOR_BLANK, 0x50); + WCrt(ba, CRT_ID_END_HOR_BLANK, 0x82); + WCrt(ba, CRT_ID_START_HOR_RETR, 0x54); + WCrt(ba, CRT_ID_END_HOR_RETR, 0x80); + WCrt(ba, CRT_ID_VER_TOTAL, 0xBF); + + WCrt(ba, CRT_ID_OVERFLOW, 0x1F); /* overflow reg */ + + WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x0); /* no panning */ + + WCrt(ba, CRT_ID_MAX_SCAN_LINE, 0x40); /* vscan */ + + WCrt(ba, CRT_ID_CURSOR_START, 0x00); + WCrt(ba, CRT_ID_CURSOR_END, 0x00); + + /* Display start adress */ + WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00); + WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00); + + /* Cursor location */ + WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x0); + WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); + + /* Vertical retrace */ + WCrt(ba, CRT_ID_START_VER_RETR, 0x9C); + WCrt(ba, CRT_ID_END_VER_RETR, 0x0E); + + WCrt(ba, CRT_ID_VER_DISP_ENA_END, 0x8F); + WCrt(ba, CRT_ID_SCREEN_OFFSET, 0x50); + + WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x00); + + WCrt(ba, CRT_ID_START_VER_BLANK, 0x96); + WCrt(ba, CRT_ID_END_VER_BLANK, 0xB9); + + WCrt(ba, CRT_ID_MODE_CONTROL, 0xE3); + + WCrt(ba, CRT_ID_LINE_COMPARE, 0xFF); + + WCrt(ba, CRT_ID_BACKWAD_COMP_3, 0x10); /* FIFO enabled */ + + /* Refresh count 1, High speed text font, enhanced color mode */ + WCrt(ba, CRT_ID_MISC_1, 0x35); + + /* start fifo position */ + WCrt(ba, CRT_ID_DISPLAY_FIFO, 0x5a); + + WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, 0x70); + + /* address window position */ + WCrt(ba, CRT_ID_LAW_POS_LO, 0x40); + + /* N Parameter for Display FIFO */ + WCrt(ba, CRT_ID_EXT_MEM_CNTL_3, 0xFF); + + WGfx(ba, GCT_ID_SET_RESET, 0x0); + WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x0); + WGfx(ba, GCT_ID_COLOR_COMPARE, 0x0); + WGfx(ba, GCT_ID_DATA_ROTATE, 0x0); + WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x0); + WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x40); + WGfx(ba, GCT_ID_MISC, 0x01); + WGfx(ba, GCT_ID_COLOR_XCARE, 0x0F); + WGfx(ba, GCT_ID_BITMASK, 0xFF); + + /* colors for text mode */ + for (i = 0; i <= 0xf; i++) + WAttr (ba, i, i); + + WAttr(ba,ACT_ID_ATTR_MODE_CNTL,0x41); + WAttr(ba,ACT_ID_OVERSCAN_COLOR,0x01); + WAttr(ba,ACT_ID_COLOR_PLANE_ENA,0x0F); + WAttr(ba,ACT_ID_HOR_PEL_PANNING,0x0); + WAttr(ba,ACT_ID_COLOR_SELECT,0x0); + + vgaw(ba, VDAC_MASK, 0xFF); /* DAC Mask */ + + *((unsigned long *)(ba + ECR_FRGD_COLOR)) = 0xFF; + *((unsigned long *)(ba + ECR_BKGD_COLOR)) = 0; + + /* colors initially set to greyscale */ + + vgaw(ba, VDAC_ADDRESS_W, 0); + for (i = 255; i >= 0 ; i--) { + vgaw(ba, VDAC_DATA, i); + vgaw(ba, VDAC_DATA, i); + vgaw(ba, VDAC_DATA, i); + } + + /* GFx hardware cursor off */ + WCrt(ba, CRT_ID_HWGC_MODE, 0x00); + + /* Set first to 4 MB, so test will work */ + WCrt(ba, CRT_ID_LAW_CNTL, 0x13); + + /* find *correct* fbsize of z3 board */ + if (cv_has_4mb((volatile char *)cv_boardaddr + 0x01400000)) { + cv_fbsize = 1024 * 1024 * 4; + WCrt(ba, CRT_ID_LAW_CNTL, 0x13); /* 4 MB */ + } else { + cv_fbsize = 1024 * 1024 * 2; + WCrt(ba, CRT_ID_LAW_CNTL, 0x12); /* 2 MB */ + } + + /* If I knew what this really does... but it _is_ necessary + to get any gfx on the screen!! Undocumented register? */ + WAttr(ba, 0x33, 0); +} + + +int +cv_getvmode(gp, vm) + struct grf_softc *gp; + struct grfvideo_mode *vm; +{ + struct grfvideo_mode *gv; + +#ifdef CV64CONSOLE + /* Handle grabbing console mode */ + if (vm->mode_num == 255) { + bcopy(&cvconsole_mode, vm, sizeof(struct grfvideo_mode)); + /* XXX so grfconfig can tell us the correct text + * dimensions. + */ + vm->depth = cvconsole_mode.fy; + return(0); + } +#endif + if (vm->mode_num && vm->mode_num > monitor_def_max) + return(EINVAL); + + if (!vm->mode_num) + vm->mode_num = (monitor_current - monitor_def) + 1; + + gv = monitor_def + (vm->mode_num - 1); + if (gv->mode_num == 0) + return(EINVAL); + + bcopy(gv, vm, sizeof(struct grfvideo_mode)); + return(0); +} + + +int +cv_setvmode(gp, mode) + struct grf_softc *gp; + unsigned mode; +{ + if (!mode || (mode > monitor_def_max) || + monitor_def[mode-1].mode_num == 0) + return(EINVAL); + + monitor_current = monitor_def + (mode - 1); + + return(0); +} + +void +cv_off(gp) + struct grf_softc *gp; +{ + char *ba = gp->g_regkva - READ_OFFSET; + + /* we'll put the pass-through on for cc ite and set Full Bandwidth + * bit on just in case it didn't work...but then it doesn't matter + * does it? =) + */ + cvscreen(1, ba); +} + +int +cv_blank(gp, on) + struct grf_softc *gp; + int *on; +{ + char *ba = gp->g_regkva; + + if (*on) /* 1 = blank, 0 = normal display */ + gfx_on_off(1, ba); + else + gfx_on_off(0, ba); + + return (0); +} + + +/* + * Change the mode of the display. + * Return a UNIX error number or 0 for success. + */ +int +cv_mode(gp, cmd, arg, a2, a3) + register struct grf_softc *gp; + int cmd; + void *arg; + int a2, a3; +{ + int error; + + switch (cmd) { + case GM_GRFON: + error = cv_load_mon (gp, + (struct grfcvtext_mode *) monitor_current) ? 0 : EINVAL; + return(error); + + case GM_GRFOFF: +#ifndef CV64CONSOLE + cv_off(gp); +#else + cv_load_mon(gp, &cvconsole_mode); +#endif + return(0); + + case GM_GRFCONFIG: + return(0); + + case GM_GRFGETVMODE: + return(cv_getvmode (gp, (struct grfvideo_mode *) arg)); + + case GM_GRFSETVMODE: + error = cv_setvmode (gp, *(unsigned *) arg); + if (!error && (gp->g_flags & GF_GRFON)) + cv_load_mon(gp, + (struct grfcvtext_mode *) monitor_current); + return(error); + + case GM_GRFGETNUMVM: + *(int *)arg = monitor_def_max; + return(0); + + case GM_GRFIOCTL: + return(cv_ioctl (gp, (int) arg, (caddr_t) a2)); + + default: + break; + } + + return(EINVAL); +} + +int +cv_ioctl (gp, cmd, data) + register struct grf_softc *gp; + int cmd; + void *data; +{ + switch (cmd) { + case GRFIOCGSPRITEPOS: + case GRFIOCSSPRITEPOS: + case GRFIOCSSPRITEINF: + case GRFIOCGSPRITEINF: + case GRFIOCGSPRITEMAX: + break; + + case GRFIOCGETCMAP: + return(cv_getcmap (gp, (struct grf_colormap *) data)); + + case GRFIOCPUTCMAP: + return(cv_putcmap (gp, (struct grf_colormap *) data)); + + case GRFIOCBITBLT: + break; + + case GRFTOGGLE: + return(cv_toggle (gp, 0)); + + case GRFIOCSETMON: + return(cv_setmonitor (gp, (struct grfvideo_mode *)data)); + + case GRFIOCBLANK: + return(cv_blank (gp, (int *)data)); + } + return(EINVAL); +} + +int +cv_setmonitor(gp, gv) + struct grf_softc *gp; + struct grfvideo_mode *gv; +{ + struct grfvideo_mode *md; + +#ifdef CV64CONSOLE + /* handle interactive setting of console mode */ + if (gv->mode_num == 255 && gv->depth == 4) { + bcopy(gv, &cvconsole_mode.gv, sizeof(struct grfvideo_mode)); + cvconsole_mode.rows = gv->disp_height / cvconsole_mode.fy; + cvconsole_mode.cols = gv->disp_width / cvconsole_mode.fx; + if (!(gp->g_flags & GF_GRFON)) + cv_load_mon(gp, &cvconsole_mode); + ite_reinit(gp->g_itedev); + return(0); + } +#endif + + if (!gv->mode_num || gv->mode_num > monitor_def_max) + return(EINVAL); + + if ((gv->depth == 24 && (gv->pixel_clock > 50000000)) || + ((gv->depth == 15 || gv->depth == 16) && (gv->pixel_clock > 80000000)) || + (gv->pixel_clock > MAXPIXELCLOCK)) + return(EINVAL); + + md = monitor_def + (gv->mode_num - 1); + + bcopy(gv, md, sizeof(struct grfvideo_mode)); + return(0); +} + +int +cv_getcmap(gfp, cmap) + struct grf_softc *gfp; + struct grf_colormap *cmap; +{ + volatile unsigned char *ba; + u_char red[256], green[256], blue[256], *rp, *gp, *bp; + short x; + int error; + + if (cmap->count == 0 || cmap->index >= 256) + return 0; + + if (cmap->index + cmap->count > 256) + cmap->count = 256 - cmap->index; + + ba = gfp->g_regkva; + /* first read colors out of the chip, then copyout to userspace */ + vgaw (ba, VDAC_ADDRESS_W, cmap->index); + x = cmap->count - 1; + + rp = red + cmap->index; + gp = green + cmap->index; + bp = blue + cmap->index; + + do { + *rp++ = vgar (ba, VDAC_DATA) << 2; + *gp++ = vgar (ba, VDAC_DATA) << 2; + *bp++ = vgar (ba, VDAC_DATA) << 2; + } while (x-- > 0); + + if (!(error = copyout (red + cmap->index, cmap->red, cmap->count)) + && !(error = copyout (green + cmap->index, cmap->green, cmap->count)) + && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count))) + return(0); + + return(error); +} + +int +cv_putcmap(gfp, cmap) + struct grf_softc *gfp; + struct grf_colormap *cmap; +{ + volatile unsigned char *ba; + u_char red[256], green[256], blue[256], *rp, *gp, *bp; + short x; + int error; + + if (cmap->count == 0 || cmap->index >= 256) + return(0); + + if (cmap->index + cmap->count > 256) + cmap->count = 256 - cmap->index; + + /* first copy the colors into kernelspace */ + if (!(error = copyin (cmap->red, red + cmap->index, cmap->count)) + && !(error = copyin (cmap->green, green + cmap->index, cmap->count)) + && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) { + ba = gfp->g_regkva; + vgaw (ba, VDAC_ADDRESS_W, cmap->index); + x = cmap->count - 1; + + rp = red + cmap->index; + gp = green + cmap->index; + bp = blue + cmap->index; + + do { + vgaw (ba, VDAC_DATA, *rp++ >> 2); + vgaw (ba, VDAC_DATA, *gp++ >> 2); + vgaw (ba, VDAC_DATA, *bp++ >> 2); + } while (x-- > 0); + return(0); + } + else + return(error); +} + + +int +cv_toggle(gp,wopp) + struct grf_softc *gp; + unsigned short wopp; /* don't need that one yet, ill */ +{ + volatile unsigned char *ba; + + ba = gp->g_regkva-0x0200000; + + if (pass_toggle) { + cvscreen(0, ba); + } else { + cvscreen(1,ba); + } + return(0); +} + + +int +cv_mondefok(mdp) + struct grfvideo_mode *mdp; +{ + if (mdp->mode_num == 0) + return(0); + + switch(mdp->depth) { + case 1: + case 4: + return(0); /* remove this when ite5 is ready */ + case 8: + if (mdp->pixel_clock > MAXPIXELCLOCK) + return(0); + return(1); + case 15: + case 16: + if (mdp->pixel_clock > 80000000) + return(0); + return(1); + case 24: + if (mdp->pixel_clock > 50000000) + return(0); + return(1); + default: + return(0); + } +} + +int +cv_load_mon(gp, md) + struct grf_softc *gp; + struct grfcvtext_mode *md; +{ + struct grfvideo_mode *gv; + struct grfinfo *gi; + volatile unsigned char *ba; + volatile unsigned char *fb; + unsigned short mnr; + unsigned short HT,HDE,HBS,HBE,HSS,HSE,VDE,VBS,VBE,VSS,VSE,VT; + char LACE, DBLSCAN, TEXT; + int uplim, lowlim; + char test; + + /* turn gfx off, don't mess up the display */ + gfx_on_off(1, ba); + + /* identity */ + gv = &md->gv; + TEXT = (gv->depth == 4); + + if (!cv_mondefok(gv)) { + printf("mondef not ok\n"); + return(0); + } + + ba = gp->g_regkva; + fb = gp->g_fbkva; + + /* provide all needed information in grf device-independant + * locations + */ + gp->g_data = (caddr_t) gv; + gi = &gp->g_display; + gi->gd_regaddr = (caddr_t) ztwopa (ba); + gi->gd_regsize = 64 * 1024; + gi->gd_fbaddr = (caddr_t) kvtop (fb); + gi->gd_fbsize = cv_fbsize; + gi->gd_colors = 1 << gv->depth; + gi->gd_planes = gv->depth; + gi->gd_fbwidth = gv->disp_width; + gi->gd_fbheight = gv->disp_height; + gi->gd_fbx = 0; + gi->gd_fby = 0; + if (TEXT) { + gi->gd_dwidth = md->fx * md->cols; + gi->gd_dheight = md->fy * md->rows; + } else { + gi->gd_dwidth = gv->disp_width; + gi->gd_dheight = gv->disp_height; + } + gi->gd_dx = 0; + gi->gd_dy = 0; + + /* get display mode parameters */ + + HBS = gv->hblank_start; + HBE = gv->hblank_stop; + HSS = gv->hsync_start; + HSE = gv->hsync_stop; + HT = gv->htotal; + VBS = gv->vblank_start; + VSS = gv->vsync_start; + VSE = gv->vsync_stop; + VBE = gv->vblank_stop; + VT = gv->vtotal; + + if (TEXT) + HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1; + else + HDE = (gv->disp_width + 3) / 8 - 1; /*HBS;*/ + VDE = gv->disp_height - 1; + + /* figure out whether lace or dblscan is needed */ + + uplim = gv->disp_height + (gv->disp_height / 4); + lowlim = gv->disp_height - (gv->disp_height / 4); + LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0; + DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0; + + /* adjustments */ + + if (LACE) + VDE /= 2; + + WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e); + WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); + WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff); + WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); + + /* Set clock */ + + switch (gv->depth) { + case 15: + case 16: + mnr = compute_clock(gv->pixel_clock * 2); + break; + case 24: + mnr = compute_clock(gv->pixel_clock * 3); + break; + default: + mnr = compute_clock(gv->pixel_clock); + break; + } + + WSeq(ba, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8) ); + WSeq(ba, SEQ_ID_DCLK_LO, (mnr & 0xFF)); + + /* load display parameters into board */ + + WCrt(ba, CRT_ID_EXT_HOR_OVF, + ((HT & 0x100) ? 0x01 : 0x00) | + ((HDE & 0x100) ? 0x02 : 0x00) | + ((HBS & 0x100) ? 0x04 : 0x00) | + /* ((HBE & 0x40) ? 0x08 : 0x00) | */ /* Later... */ + ((HSS & 0x100) ? 0x10 : 0x00) | + /* ((HSE & 0x20) ? 0x20 : 0x00) | */ + (((HT-5) & 0x100) ? 0x40 : 0x00) ); + + WCrt(ba, CRT_ID_EXT_VER_OVF, + 0x40 | /* Line compare */ + ((VT & 0x400) ? 0x01 : 0x00) | + ((VDE & 0x400) ? 0x02 : 0x00) | + ((VBS & 0x400) ? 0x04 : 0x00) | + ((VSS & 0x400) ? 0x10 : 0x00) ); + + WCrt(ba, CRT_ID_HOR_TOTAL, HT); + WCrt(ba, CRT_ID_DISPLAY_FIFO, HT - 5); + + WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE)); + WCrt(ba, CRT_ID_START_HOR_BLANK, HBS); + WCrt(ba, CRT_ID_END_HOR_BLANK, ((HBE & 0x1f) | 0x80)); + WCrt(ba, CRT_ID_START_HOR_RETR, HSS); + WCrt(ba, CRT_ID_END_HOR_RETR, + (HSE & 0x1f) | + ((HBE & 0x20) ? 0x80 : 0x00) ); + WCrt(ba, CRT_ID_VER_TOTAL, VT); + WCrt(ba, CRT_ID_OVERFLOW, + 0x10 | + ((VT & 0x100) ? 0x01 : 0x00) | + ((VDE & 0x100) ? 0x02 : 0x00) | + ((VSS & 0x100) ? 0x04 : 0x00) | + ((VBS & 0x100) ? 0x08 : 0x00) | + ((VT & 0x200) ? 0x20 : 0x00) | + ((VDE & 0x200) ? 0x40 : 0x00) | + ((VSS & 0x200) ? 0x80 : 0x00) ); + + WCrt(ba, CRT_ID_MAX_SCAN_LINE, + 0x40 | /* TEXT ? 0x00 ??? */ + (DBLSCAN ? 0x80 : 0x00) | + ((VBS & 0x200) ? 0x20 : 0x00) | + (TEXT ? ((md->fy - 1) & 0x1f) : 0x00)); + + WCrt(ba, CRT_ID_MODE_CONTROL, + ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xe3)); + + /* text cursor */ + + if (TEXT) { +#if 1 + WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2); + WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1); +#else + WCrt(ba, CRT_ID_CURSOR_START, 0x00); + WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f); +#endif + WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->fy - 1) & 0x1f); + + WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); + WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); + } + + WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00); + WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00); + + WCrt(ba, CRT_ID_START_VER_RETR, VSS); + WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f)); + WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE); + WCrt(ba, CRT_ID_START_VER_BLANK, VBS); + WCrt(ba, CRT_ID_END_VER_BLANK, VBE); + + WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); + WCrt(ba, CRT_ID_LACE_RETR_START, HT / 2); + WCrt(ba, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00)); + + WGfx(ba, GCT_ID_GRAPHICS_MODE, + ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40)); + WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01)); + + WSeq (ba, SEQ_ID_MEMORY_MODE, + ((TEXT || (gv->depth == 1)) ? 0x6 : 0x02)); + + vgaw(ba, VDAC_MASK, 0xff); + + /* Must use dblclk mode for pixclk > 80MHz */ + if (gv->depth == 8 && gv->pixel_clock > 80000000) { + test = RSeq (ba,SEQ_ID_CLKSYN_CNTL_2); + test |= 0x10; + WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, test); + delay (100000); + WSeq(ba, SEQ_ID_RAMDAC_CNTL, 0x80); + } else { + test = RSeq (ba,SEQ_ID_CLKSYN_CNTL_2); + test &= 0xef; + WSeq(ba, SEQ_ID_CLKSYN_CNTL_2, test); + delay (100000); + WSeq(ba, SEQ_ID_RAMDAC_CNTL, 0x00); + } + + test = RCrt(ba, CRT_ID_EXT_MISC_CNTL_2); + test &= 0xf; + + switch (gv->depth) { + case 1: + case 4: /* text */ + HDE = gv->disp_width / 16; + break; + case 8: + if (gv->pixel_clock > 80000000) + WCrt (ba, CRT_ID_EXT_MISC_CNTL_2 ,0x10 | test); + else + WCrt (ba, CRT_ID_EXT_MISC_CNTL_2 ,0x00 | test); + HDE = gv->disp_width / 8; + break; + case 15: + WCrt (ba, CRT_ID_EXT_MISC_CNTL_2 ,0x30 | test); + HDE = gv->disp_width / 4; + break; + case 16: + WCrt (ba, CRT_ID_EXT_MISC_CNTL_2 ,0x50 | test); + HDE = gv->disp_width / 4; + break; + case 24: + WCrt (ba, CRT_ID_EXT_MISC_CNTL_2 ,0xd0 | test); + HDE = (gv->disp_width / 8) * 3; + break; + } + + WCrt(ba, CRT_ID_SCREEN_OFFSET, HDE); + + test = RCrt(ba, CRT_ID_EXT_SYS_CNTL_2); + /* HDE Overflow in bits 4-5 */ + test |= (HDE >> 4) & 0x30; + WCrt(ba, CRT_ID_EXT_SYS_CNTL_2, test); + + delay(100000); + WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x41)); + delay(100000); + WAttr(ba, ACT_ID_COLOR_PLANE_ENA, + (gv->depth == 1) ? 0x01 : 0x0f); + delay(100000); + + /* text initialization */ + + if (TEXT) { + cv_inittextmode(gp); + } + + /* M-Parameter of Display FIFO + * this is dependant on the pixel clock + * If someone knows a better formula, please tell me! + */ + switch(gv->depth) { + case 24: + test = (unsigned char) ((140.0 / (gv->pixel_clock * 3) - 1.0) * 64.0 -1); + break; + case 15: + case 16: + test = (unsigned char) ((140.0 / (gv->pixel_clock * 2) - 1.0) * 64.0 -1); + break; + default: + test = (unsigned char) ((140.0 / gv->pixel_clock - 1.0) * 64.0 -1); + break; + } + +/* test = (unsigned char) ((140.0 / ((gv->depth == 24) ? gv->pixel_clock * 3 : gv->pixel_clock) -1.0) * 64.0 - 1); */ + + test = (test & 0x1f) >> 3; + if (test < 0x18) + test = 0x18; + WCrt(ba, CRT_ID_EXT_MEM_CNTL_2, test); + delay(10000); + + /* Some kind of Magic */ + WAttr(ba, 0x33, 0); + + /* turn gfx on again */ + gfx_on_off(0, ba); + + /* Pass-through */ + cvscreen(0, ba - 0x2000000); + + return(1); +} + +void +cv_inittextmode(gp) + struct grf_softc *gp; +{ + struct grfcvtext_mode *tm = (struct grfcvtext_mode *)gp->g_data; + volatile unsigned char *ba = gp->g_regkva; + unsigned char *fb = gp->g_fbkva; + unsigned char *c, *f, y; + unsigned short z; + + + /* load text font into beginning of display memory. + * Each character cell is 32 bytes long (enough for + * 4 planes) + */ + + SetTextPlane(ba, 0x02); + c = (unsigned char *)(fb); + f = tm->fdata; + for (z = 0; z < tm->fdstart; z++, c+=(32-tm->fy)) + for (y=0; y < tm->fy; y++) + *c++ = 0; + for (; z <= tm->fdend; z++, c+=(32-tm->fy)) + for (y=0; y < tm->fy; y++) + *c++ = *f++; + for (; z < 256; z++, c+=(32-tm->fy)) + for (y=0; y < tm->fy; y++) + *c++ = 0; + + /* clear out text/attr planes (three screens worth) */ + + SetTextPlane(ba, 0x01); + cv_memset(fb, 0x07, tm->cols*tm->rows*3); + SetTextPlane(ba, 0x00); + cv_memset(fb, 0x20, tm->cols*tm->rows*3); + + /* print out a little init msg */ + + c = (unsigned char *)(fb) + (tm->cols-16); + strcpy(c, "CV64"); + c[6] = 0x20; + + /* set colors (B&W) */ + + vgaw(ba, VDAC_ADDRESS_W, 0); + for (z=0; z<256; z++) { + unsigned char r, g, b; + + y = (z & 1) ? ((z > 7) ? 2 : 1) : 0; + + r = cvconscolors[y][0]; + g = cvconscolors[y][1]; + b = cvconscolors[y][2]; + vgaw(ba, VDAC_DATA, r >> 2); + vgaw(ba, VDAC_DATA, g >> 2); + vgaw(ba, VDAC_DATA, b >> 2); + } +} + +void +cv_memset(d, c, l) + unsigned char *d; + unsigned char c; + int l; +{ + for(; l > 0; l--) + *d++ = c; +} + +#endif /* NGRFCV */ diff --git a/sys/arch/amiga/dev/grf_cvreg.h b/sys/arch/amiga/dev/grf_cvreg.h new file mode 100644 index 000000000000..d82281d99f06 --- /dev/null +++ b/sys/arch/amiga/dev/grf_cvreg.h @@ -0,0 +1,510 @@ +/* + * Copyright (c) 1995 Michael Teske + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Ezra Story, by Kari + * Mettinen and by Bernd Ernesti. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _GRF_CVREG_H +#define _GRF_CVREG_H + +/* + * This is derived from ciruss driver source + */ + +/* Extension to grfvideo_mode to support text modes. + * This can be passed to both text & gfx functions + * without worry. If gv.depth == 4, then the extended + * fields for a text mode are present. + */ + +struct grfcvtext_mode { + struct grfvideo_mode gv; + unsigned short fx; /* font x dimension */ + unsigned short fy; /* font y dimension */ + unsigned short cols; /* screen dimensions */ + unsigned short rows; + void *fdata; /* font data */ + unsigned short fdstart; + unsigned short fdend; +}; + + +/* read VGA register */ +#define vgar(ba, reg) (*(((volatile unsigned char *)ba)+reg)) + +/* write VGA register */ +#define vgaw(ba, reg, val) \ + *(((volatile unsigned char *)ba)+reg) = ((val) & 0xff) + +/* + * defines for the used register addresses (mw) + * + * NOTE: there are some registers that have different addresses when + * in mono or color mode. We only support color mode, and thus + * some addresses won't work in mono-mode! + * + * General and VGA-registers taken from retina driver. Fixed a few + * bugs in it. (SR and GR read address is Port + 1, NOT Port) + * + */ + +/* General Registers: */ +#define GREG_MISC_OUTPUT_R 0x03CC +#define GREG_MISC_OUTPUT_W 0x03C2 +#define GREG_FEATURE_CONTROL_R 0x03CA +#define GREG_FEATURE_CONTROL_W 0x03DA +#define GREG_INPUT_STATUS0_R 0x03C2 +#define GREG_INPUT_STATUS1_R 0x03DA + +/* Setup Registers: */ +#define SREG_OPTION_SELECT 0x0102 +#define SREG_VIDEO_SUBS_ENABLE 0x46E8 + +/* Attribute Controller: */ +#define ACT_ADDRESS 0x03C0 +#define ACT_ADDRESS_R 0x03C1 +#define ACT_ADDRESS_W 0x03C0 +#define ACT_ADDRESS_RESET 0x03DA +#define ACT_ID_PALETTE0 0x00 +#define ACT_ID_PALETTE1 0x01 +#define ACT_ID_PALETTE2 0x02 +#define ACT_ID_PALETTE3 0x03 +#define ACT_ID_PALETTE4 0x04 +#define ACT_ID_PALETTE5 0x05 +#define ACT_ID_PALETTE6 0x06 +#define ACT_ID_PALETTE7 0x07 +#define ACT_ID_PALETTE8 0x08 +#define ACT_ID_PALETTE9 0x09 +#define ACT_ID_PALETTE10 0x0A +#define ACT_ID_PALETTE11 0x0B +#define ACT_ID_PALETTE12 0x0C +#define ACT_ID_PALETTE13 0x0D +#define ACT_ID_PALETTE14 0x0E +#define ACT_ID_PALETTE15 0x0F +#define ACT_ID_ATTR_MODE_CNTL 0x10 +#define ACT_ID_OVERSCAN_COLOR 0x11 +#define ACT_ID_COLOR_PLANE_ENA 0x12 +#define ACT_ID_HOR_PEL_PANNING 0x13 +#define ACT_ID_COLOR_SELECT 0x14 + +/* Graphics Controller: */ +#define GCT_ADDRESS 0x03CE +#define GCT_ADDRESS_R 0x03CF +#define GCT_ADDRESS_W 0x03CF +#define GCT_ID_SET_RESET 0x00 +#define GCT_ID_ENABLE_SET_RESET 0x01 +#define GCT_ID_COLOR_COMPARE 0x02 +#define GCT_ID_DATA_ROTATE 0x03 +#define GCT_ID_READ_MAP_SELECT 0x04 +#define GCT_ID_GRAPHICS_MODE 0x05 +#define GCT_ID_MISC 0x06 +#define GCT_ID_COLOR_XCARE 0x07 +#define GCT_ID_BITMASK 0x08 + +/* Sequencer: */ +#define SEQ_ADDRESS 0x03C4 +#define SEQ_ADDRESS_R 0x03C5 +#define SEQ_ADDRESS_W 0x03C5 +#define SEQ_ID_RESET 0x00 +#define SEQ_ID_CLOCKING_MODE 0x01 +#define SEQ_ID_MAP_MASK 0x02 +#define SEQ_ID_CHAR_MAP_SELECT 0x03 +#define SEQ_ID_MEMORY_MODE 0x04 +#define SEQ_ID_UNKNOWN1 0x05 +#define SEQ_ID_UNKNOWN2 0x06 +#define SEQ_ID_UNKNOWN3 0x07 +/* S3 extensions */ +#define SEQ_ID_UNLOCK_EXT 0x08 +#define SEQ_ID_EXT_SEQ_REG9 0x09 +#define SEQ_ID_BUS_REQ_CNTL 0x0A +#define SEQ_ID_EXT_MISC_SEQ 0x0B +#define SEQ_ID_UNKNOWN4 0x0C +#define SEQ_ID_EXT_SEQ 0x0D +#define SEQ_ID_UNKNOWN5 0x0E +#define SEQ_ID_UNKNOWN6 0x0F +#define SEQ_ID_MCLK_LO 0x10 +#define SEQ_ID_MCLK_HI 0x11 +#define SEQ_ID_DCLK_LO 0x12 +#define SEQ_ID_DCLK_HI 0x13 +#define SEQ_ID_CLKSYN_CNTL_1 0x14 +#define SEQ_ID_CLKSYN_CNTL_2 0x15 +#define SEQ_ID_CLKSYN_TEST_HI 0x16 /* reserved for S3 testing of the */ +#define SEQ_ID_CLKSYN_TEST_LO 0x17 /* internal clock synthesizer */ +#define SEQ_ID_RAMDAC_CNTL 0x18 + +/* CRT Controller: */ +#define CRT_ADDRESS 0x03D4 +#define CRT_ADDRESS_R 0x03D5 +#define CRT_ADDRESS_W 0x03D5 +#define CRT_ID_HOR_TOTAL 0x00 +#define CRT_ID_HOR_DISP_ENA_END 0x01 +#define CRT_ID_START_HOR_BLANK 0x02 +#define CRT_ID_END_HOR_BLANK 0x03 +#define CRT_ID_START_HOR_RETR 0x04 +#define CRT_ID_END_HOR_RETR 0x05 +#define CRT_ID_VER_TOTAL 0x06 +#define CRT_ID_OVERFLOW 0x07 +#define CRT_ID_PRESET_ROW_SCAN 0x08 +#define CRT_ID_MAX_SCAN_LINE 0x09 +#define CRT_ID_CURSOR_START 0x0A +#define CRT_ID_CURSOR_END 0x0B +#define CRT_ID_START_ADDR_HIGH 0x0C +#define CRT_ID_START_ADDR_LOW 0x0D +#define CRT_ID_CURSOR_LOC_HIGH 0x0E +#define CRT_ID_CURSOR_LOC_LOW 0x0F +#define CRT_ID_START_VER_RETR 0x10 +#define CRT_ID_END_VER_RETR 0x11 +#define CRT_ID_VER_DISP_ENA_END 0x12 +#define CRT_ID_SCREEN_OFFSET 0x13 +#define CRT_ID_UNDERLINE_LOC 0x14 +#define CRT_ID_START_VER_BLANK 0x15 +#define CRT_ID_END_VER_BLANK 0x16 +#define CRT_ID_MODE_CONTROL 0x17 +#define CRT_ID_LINE_COMPARE 0x18 +#define CRT_ID_GD_LATCH_RBACK 0x22 +#define CRT_ID_ACT_TOGGLE_RBACK 0x24 +#define CRT_ID_ACT_INDEX_RBACK 0x26 +/* S3 extensions: S3 VGA Registers */ +#define CRT_ID_DEVICE_HIGH 0x2D +#define CRT_ID_DEVICE_LOW 0x2E +#define CRT_ID_REVISION 0x2F +#define CRT_ID_CHIP_ID_REV 0x30 +#define CRT_ID_MEMORY_CONF 0x31 +#define CRT_ID_BACKWAD_COMP_1 0x32 +#define CRT_ID_BACKWAD_COMP_2 0x33 +#define CRT_ID_BACKWAD_COMP_3 0x34 +#define CRT_ID_REGISTER_LOCK 0x35 +#define CRT_ID_CONFIG_1 0x36 +#define CRT_ID_CONFIG_2 0x37 +#define CRT_ID_REGISTER_LOCK_1 0x38 +#define CRT_ID_REGISTER_LOCK_2 0x39 +#define CRT_ID_MISC_1 0x3A +#define CRT_ID_DISPLAY_FIFO 0x3B +#define CRT_ID_LACE_RETR_START 0x3C +/* S3 extensions: System Control Registers */ +#define CRT_ID_SYSTEM_CONFIG 0x40 +#define CRT_ID_BIOS_FLAG 0x41 +#define CRT_ID_LACE_CONTROL 0x42 +#define CRT_ID_EXT_MODE 0x43 +#define CRT_ID_HWGC_MODE 0x45 /* HWGC = Hardware Graphics Cursor */ +#define CRT_ID_HWGC_ORIGIN_X_HI 0x46 +#define CRT_ID_HWGC_ORIGIN_X_LO 0x47 +#define CRT_ID_HWGC_ORIGIN_Y_HI 0x48 +#define CRT_ID_HWGC_ORIGIN_Y_LO 0x49 +#define CRT_ID_HWGC_FG_STACK 0x4A +#define CRT_ID_HWGC_BG_STACK 0x4B +#define CRT_ID_HWGC_START_AD_HI 0x4C +#define CRT_ID_HWGC_START_AD_LO 0x4D +#define CRT_ID_HWGC_DSTART_X 0x4E +#define CRT_ID_HWGC_DSTART_Y 0x4F +/* S3 extensions: System Extension Registers */ +#define CRT_ID_EXT_SYS_CNTL_1 0x50 +#define CRT_ID_EXT_SYS_CNTL_2 0x51 +#define CRT_ID_EXT_BIOS_FLAG_1 0x52 +#define CRT_ID_EXT_MEM_CNTL_1 0x53 +#define CRT_ID_EXT_MEM_CNTL_2 0x54 +#define CRT_ID_EXT_DAC_CNTL 0x55 +#define CRT_ID_EX_SYNC_1 0x56 +#define CRT_ID_EX_SYNC_2 0x57 +#define CRT_ID_LAW_CNTL 0x58 /* LAW = Linear Address Window */ +#define CRT_ID_LAW_POS_HI 0x59 +#define CRT_ID_LAW_POS_LO 0x5A +#define CRT_ID_GOUT_PORT 0x5C +#define CRT_ID_EXT_HOR_OVF 0x5D +#define CRT_ID_EXT_VER_OVF 0x5E +#define CRT_ID_EXT_MEM_CNTL_3 0x60 +#define CRT_ID_EX_SYNC_3 0x63 +#define CRT_ID_EXT_MISC_CNTL 0x65 +#define CRT_ID_EXT_MISC_CNTL_1 0x66 +#define CRT_ID_EXT_MISC_CNTL_2 0x67 +#define CRT_ID_CONFIG_3 0x68 +#define CRT_ID_EXT_SYS_CNTL_3 0x69 +#define CRT_ID_EXT_SYS_CNTL_4 0x6A +#define CRT_ID_EXT_BIOS_FLAG_3 0x6B +#define CRT_ID_EXT_BIOS_FLAG_4 0x6C + +/* Enhanced Commands Registers: */ +#define ECR_SUBSYSTEM_STAT 0x42E8 +#define ECR_SUBSYSTEM_CNTL 0x42E8 +#define ECR_ADV_FUNC_CNTL 0x4AE8 +#define ECR_CURRENT_Y_POS 0x82E8 +#define ECR_CURRENT_Y_POS2 0x82EA /* Trio64 only */ +#define ECR_CURRENT_X_POS 0x86E8 +#define ECR_CURRENT_X_POS2 0x86EA /* Trio64 only */ +#define ECR_DEST_Y__AX_STEP 0x8AE8 +#define ECR_DEST_Y2__AX_STEP2 0x8AEA /* Trio64 only */ +#define ECR_DEST_X__DIA_STEP 0x8EE8 +#define ECR_DEST_X2__DIA_STEP2 0x8EEA /* Trio64 only */ +#define ECR_ERR_TERM 0x92E8 +#define ECR_ERR_TERM2 0x92EA /* Trio64 only */ +#define ECR_MAJ_AXIS_PIX_CNT 0x96E8 +#define ECR_MAJ_AXIS_PIX_CNT2 0x96EA /* Trio64 only */ +#define ECR_GP_STAT 0x9AE8 /* GP = Graphics Processor */ +#define ECR_DRAW_CMD 0x9AE8 +#define ECR_DRAW_CMD2 0x9AEA /* Trio64 only */ +#define ECR_SHORT_STROKE 0x9EE8 +#define ECR_BKGD_COLOR 0xA2E8 /* BKGD = Background */ +#define ECR_FRGD_COLOR 0xA6E8 /* FRGD = Foreground */ +#define ECR_BITPLANE_WRITE_MASK 0xAAE8 +#define ECR_BITPLANE_READ_MASK 0xAEE8 +#define ECR_COLOR_COMPARE 0xB2E8 +#define ECR_BKGD_MIX 0xB6E8 +#define ECR_FRGD_MIX 0xBAE8 +#define ECR_READ_REG_DATA 0xBEE8 +#define ECR_ID_MIN_AXIS_PIX_CNT 0x00 +#define ECR_ID_SCISSORS_TOP 0x01 +#define ECR_ID_SCISSORS_LEFT 0x02 +#define ECR_ID_SCISSORS_BUTTOM 0x03 +#define ECR_ID_SCISSORS_RIGHT 0x04 +#define ECR_ID_PIX_CNTL 0x0A +#define ECR_ID_MULT_CNTL_MISC_2 0x0D +#define ECR_ID_MULT_CNTL_MISC 0x0E +#define ECR_ID_READ_SEL 0x0F +#define ECR_PIX_TRANS 0xE2E8 +#define ECR_PIX_TRANS_EXT 0xE2EA +#define ECR_PATTERN_Y 0xEAE8 /* Trio64 only */ +#define ECR_PATTERN_X 0xEAEA /* Trio64 only */ + + +/* Pass-through */ +#define PASS_ADDRESS 0x40001 +#define PASS_ADDRESS_W 0x40001 + +/* Video DAC */ +#define VDAC_ADDRESS 0x03c8 +#define VDAC_ADDRESS_W 0x03c8 +#define VDAC_ADDRESS_R 0x03c7 +#define VDAC_STATE 0x03c7 +#define VDAC_DATA 0x03c9 +#define VDAC_MASK 0x03c6 + + +#define WGfx(ba, idx, val) \ + do { vgaw(ba, GCT_ADDRESS, idx); vgaw(ba, GCT_ADDRESS_W , val); } while (0) + +#define WSeq(ba, idx, val) \ + do { vgaw(ba, SEQ_ADDRESS, idx); vgaw(ba, SEQ_ADDRESS_W , val); } while (0) + +#define WCrt(ba, idx, val) \ + do { vgaw(ba, CRT_ADDRESS, idx); vgaw(ba, CRT_ADDRESS_W , val); } while (0) + +#define WAttr(ba, idx, val) \ + do { \ + unsigned char tmp;\ + tmp = vgar(ba, ACT_ADDRESS_RESET);\ + vgaw(ba, ACT_ADDRESS_W, idx);\ + vgaw(ba, ACT_ADDRESS_W, val);\ + } while (0) + + +#define SetTextPlane(ba, m) \ + do { \ + WGfx(ba, GCT_ID_READ_MAP_SELECT, m & 3 );\ + WSeq(ba, SEQ_ID_MAP_MASK, (1 << (m & 3)));\ + } while (0) + +/* Special wakeup/passthrough registers on graphics boards + * + * The methods have diverged a bit for each board, so + * WPass(P) has been converted into a set of specific + * inline functions. + */ + +static inline unsigned char +RAttr(ba, idx) + volatile void *ba; + short idx; +{ + + vgaw(ba, ACT_ADDRESS_W, idx); + delay(0); + return vgar(ba, ACT_ADDRESS_R); +} + +static inline unsigned char +RSeq(ba, idx) + volatile void *ba; + short idx; +{ + vgaw(ba, SEQ_ADDRESS, idx); + return vgar(ba, SEQ_ADDRESS_R); +} + +static inline unsigned char +RCrt(ba, idx) + volatile void *ba; + short idx; +{ + vgaw(ba, CRT_ADDRESS, idx); + return vgar(ba, CRT_ADDRESS_R); +} + +static inline unsigned char +RGfx(ba, idx) + volatile void *ba; + short idx; +{ + vgaw(ba, GCT_ADDRESS, idx); + return vgar(ba, GCT_ADDRESS_R); +} + + +static inline void +cv_write_port(bits, BoardAddr) + unsigned short bits; + volatile unsigned char *BoardAddr; +{ + volatile char *addr; + static unsigned char CVPortBits=0; /* mirror port bits here */ + + addr = BoardAddr + 0x40001; + if (bits & 0x8000) + CVPortBits |= bits&0xFF; /* Set bits */ + else { + bits = bits & 0xFF; + bits = (~bits) & 0xFF ; + CVPortBits &= bits; /* Clear bits */ + } + + *addr = CVPortBits; +} + +#define set_port_bits(b, ba) cv_write_port((unsigned short )b | 0x8000,ba) +#define clear_port_bits(b, ba) cv_write_port((unsigned short )b & 0xff,ba) + + +/* + * Monitor Switch + * 0 = CyberVision Signal + * 1 = Amiga Signal, + * ba = boardaddr + */ + +static inline void +cvscreen(toggle, ba) + char toggle; + volatile unsigned char *ba; +{ + + if (toggle) + cv_write_port (0x10, ba); + else + cv_write_port (0x8010, ba); +} + +/* 0 = on, 1= off */ +/* ba= registerbase */ +static inline void +gfx_on_off(toggle, ba) + char toggle; + volatile unsigned char *ba; +{ + unsigned char r; + + toggle &= 0x1; + toggle = toggle << 5; + + r = RSeq(ba, 0x1); + r &= 0xDF; /* Bit 5 auf 0!!! */ + WSeq(ba, 1, r | toggle); +} + +int cv_mode __P((register struct grf_softc *gp, int cmd, void *arg, int a2, int a3)); +int cv_load_mon __P((struct grf_softc *gp, struct grfcvtext_mode *gv)); +int grfcv_cnprobe __P((void)); +#if 0 +void grfcv_iteinit __P((struct grf_softc *gp)); +#endif + +static unsigned char clocks[]={ +0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69, +0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c, +0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a, +0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69, +0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65, +0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63, +0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d, +0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49, +0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42, +0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43, +0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49, +0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a, +0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49, +0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41, +0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43, +0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45, +0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45, +0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45, +0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44, +0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46, +0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f, +0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22, +0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46, +0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b, +0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44, +0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26, +0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b, +0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25, +0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25, +0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21, +0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29, +0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29, +0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29, +0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28, +0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26, +0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21, +0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28, +0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27, +0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22, +0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27, +0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27, +0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21, +0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26, +0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27, +0x13, 0x1, 0x13, 0x1, 0x7d, 0x27, 0x4c, 0x9, +0x37, 0x22, 0x5b, 0xb, 0x71, 0x26, 0x5c, 0xb, +0x6b, 0xd, 0x47, 0x23, 0x14, 0x1, 0x4f, 0x9, +0x23, 0x3, 0x75, 0x26, 0x7d, 0xf, 0x1c, 0x2, +0x51, 0x9, 0x59, 0x24, 0x61, 0xb, 0x69, 0x25, +0x79, 0x26, 0x34, 0x5, 0x1d, 0x2, 0x6b, 0x25, +0x54, 0x9, 0x35, 0x5, 0x45, 0x7, 0x6d, 0x25, +0x7d, 0x26, 0x16, 0x1, 0x7f, 0x26, 0x77, 0xd, +0x4f, 0x23, 0x78, 0xd, 0x2f, 0x21, 0x27, 0x3, +0x1f, 0x2, 0x59, 0x9, 0x6a, 0xb, 0x73, 0x25, +0x6b, 0xb, 0x63, 0x24, 0x5b, 0x9, 0x20, 0x2, +0x7e, 0xd, 0x4b, 0x7, 0x65, 0x24, 0x43, 0x22, +0x18, 0x1, 0x6f, 0xb, 0x5e, 0x9, 0x70, 0xb, +0x2a, 0x3, 0x33, 0x4, 0x45, 0x6, 0x60, 0x9, +0x7b, 0xc, 0x19, 0x1, 0x19, 0x1, 0x7d, 0xc, +0x74, 0xb, 0x50, 0x7, 0x75, 0xb, 0x63, 0x9, +0x51, 0x7, 0x23, 0x2, 0x3f, 0x5, 0x1a, 0x1, +0x65, 0x9, 0x2d, 0x3, 0x40, 0x5, 0x0, 0x0, +}; + +#endif /* _GRF_RHREG_H */ +